Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f3b405856d
commit
610d783b61
11 changed files with 118 additions and 92 deletions
|
@ -1,11 +1,5 @@
|
|||
---
|
||||
RSpec/TimecopTravel:
|
||||
Exclude:
|
||||
- ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb
|
||||
- ee/spec/lib/gitlab/geo/git_push_http_spec.rb
|
||||
- ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb
|
||||
- ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb
|
||||
- ee/spec/models/broadcast_message_spec.rb
|
||||
- ee/spec/models/burndown_spec.rb
|
||||
- spec/workers/concerns/reenqueuer_spec.rb
|
||||
- qa/spec/support/repeater_spec.rb
|
||||
|
|
|
@ -1 +1 @@
|
|||
bf43ae6382796653099fe76455e52b3e15df049e
|
||||
c47bb5beba81703b7c2bb2b3d1c138cb667fa80c
|
||||
|
|
|
@ -261,6 +261,7 @@ export default {
|
|||
v-if="canCancelPipeline"
|
||||
:loading="isCanceling"
|
||||
:disabled="isCanceling"
|
||||
class="gl-ml-3"
|
||||
variant="danger"
|
||||
data-testid="cancelPipeline"
|
||||
@click="cancelPipeline()"
|
||||
|
|
|
@ -10,3 +10,5 @@ export const i18n = {
|
|||
fetchError: s__('WorkItem|Something went wrong when fetching the work item. Please try again.'),
|
||||
updateError: s__('WorkItem|Something went wrong while updating the work item. Please try again.'),
|
||||
};
|
||||
|
||||
export const DEFAULT_MODAL_TYPE = 'Task';
|
||||
|
|
|
@ -6,6 +6,7 @@ import workItemQuery from '../graphql/work_item.query.graphql';
|
|||
import createWorkItemMutation from '../graphql/create_work_item.mutation.graphql';
|
||||
import createWorkItemFromTaskMutation from '../graphql/create_work_item_from_task.mutation.graphql';
|
||||
import projectWorkItemTypesQuery from '../graphql/project_work_item_types.query.graphql';
|
||||
import { DEFAULT_MODAL_TYPE } from '../constants';
|
||||
|
||||
import ItemTitle from '../components/item_title.vue';
|
||||
|
||||
|
@ -77,6 +78,13 @@ export default {
|
|||
text: node.name,
|
||||
}));
|
||||
},
|
||||
result() {
|
||||
if (!this.selectedWorkItemType && this.isModal) {
|
||||
this.selectedWorkItemType = this.formOptions.find(
|
||||
(options) => options.text === DEFAULT_MODAL_TYPE,
|
||||
)?.value;
|
||||
}
|
||||
},
|
||||
error() {
|
||||
this.error = this.$options.fetchTypesErrorText;
|
||||
},
|
||||
|
|
|
@ -53,6 +53,7 @@ class SessionsController < Devise::SessionsController
|
|||
protect_from_forgery with: :exception, prepend: true, except: :destroy
|
||||
|
||||
feature_category :authentication_and_authorization
|
||||
urgency :low
|
||||
|
||||
CAPTCHA_HEADER = 'X-GitLab-Show-Login-Captcha'
|
||||
MAX_FAILED_LOGIN_ATTEMPTS = 5
|
||||
|
|
|
@ -663,7 +663,7 @@ module API
|
|||
optional :skip_users, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Filter out users with the specified IDs'
|
||||
use :pagination
|
||||
end
|
||||
get ':id/users', feature_category: :authentication_and_authorization do
|
||||
get ':id/users', urgency: :low, feature_category: :authentication_and_authorization do
|
||||
users = DeclarativePolicy.subject_scope { user_project.team.users }
|
||||
users = users.search(params[:search]) if params[:search].present?
|
||||
users = users.where_not_in(params[:skip_users]) if params[:skip_users].present?
|
||||
|
|
|
@ -33,13 +33,13 @@ module Trigger
|
|||
ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
|
||||
end
|
||||
|
||||
def invoke!(post_comment: false, downstream_job_name: nil)
|
||||
def invoke!(downstream_job_name: nil)
|
||||
pipeline_variables = variables
|
||||
|
||||
puts "Triggering downstream pipeline on #{downstream_project_path}"
|
||||
puts "with variables #{pipeline_variables}"
|
||||
|
||||
pipeline = gitlab_client(:downstream).run_trigger(
|
||||
pipeline = downstream_client.run_trigger(
|
||||
downstream_project_path,
|
||||
trigger_token,
|
||||
ref,
|
||||
|
@ -48,18 +48,17 @@ module Trigger
|
|||
puts "Triggered downstream pipeline: #{pipeline.web_url}\n"
|
||||
puts "Waiting for downstream pipeline status"
|
||||
|
||||
Trigger::CommitComment.post!(pipeline, gitlab_client(:upstream)) if post_comment
|
||||
downstream_job =
|
||||
if downstream_job_name
|
||||
gitlab_client(:downstream).pipeline_jobs(downstream_project_path, pipeline.id).auto_paginate.find do |potential_job|
|
||||
downstream_client.pipeline_jobs(downstream_project_path, pipeline.id).auto_paginate.find do |potential_job|
|
||||
potential_job.name == downstream_job_name
|
||||
end
|
||||
end
|
||||
|
||||
if downstream_job
|
||||
Trigger::Job.new(downstream_project_path, downstream_job.id, gitlab_client(:downstream))
|
||||
Trigger::Job.new(downstream_project_path, downstream_job.id, downstream_client)
|
||||
else
|
||||
Trigger::Pipeline.new(downstream_project_path, pipeline.id, gitlab_client(:downstream))
|
||||
Trigger::Pipeline.new(downstream_project_path, pipeline.id, downstream_client)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -80,17 +79,19 @@ module Trigger
|
|||
|
||||
private
|
||||
|
||||
# Override to trigger and work with pipeline on different GitLab instance
|
||||
# type: :downstream -> downstream build and pipeline status
|
||||
# type: :upstream -> this project, e.g. for posting comments
|
||||
def gitlab_client(_type)
|
||||
# By default, always use the same client
|
||||
@gitlab_client ||= Gitlab.client(
|
||||
def com_gitlab_client
|
||||
@com_gitlab_client ||= Gitlab.client(
|
||||
endpoint: 'https://gitlab.com/api/v4',
|
||||
private_token: self.class.access_token
|
||||
)
|
||||
end
|
||||
|
||||
# This client is used for downstream build and pipeline status
|
||||
# Can be overridden
|
||||
def downstream_client
|
||||
com_gitlab_client
|
||||
end
|
||||
|
||||
# Must be overridden
|
||||
def downstream_project_path
|
||||
raise NotImplementedError
|
||||
|
@ -283,12 +284,12 @@ module Trigger
|
|||
# Remove a remote branch in gitlab-docs.
|
||||
#
|
||||
def cleanup!
|
||||
environment = gitlab_client(:downstream).environments(downstream_project_path, name: downstream_environment).first
|
||||
environment = com_gitlab_client.environments(downstream_project_path, name: downstream_environment).first
|
||||
return unless environment
|
||||
|
||||
environment = gitlab_client(:downstream).stop_environment(downstream_project_path, environment.id)
|
||||
environment = com_gitlab_client.stop_environment(downstream_project_path, environment.id)
|
||||
if environment.state == 'stopped'
|
||||
puts "=> Downstream environment '#{downstream_environment}' stopped"
|
||||
puts "=> Downstream environment '#{downstream_environment}' stopped."
|
||||
else
|
||||
puts "=> Downstream environment '#{downstream_environment}' failed to stop."
|
||||
end
|
||||
|
@ -357,26 +358,21 @@ module Trigger
|
|||
class DatabaseTesting < Base
|
||||
IDENTIFIABLE_NOTE_TAG = 'gitlab-org/database-team/gitlab-com-database-testing:identifiable-note'
|
||||
|
||||
def self.access_token
|
||||
ENV['GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN']
|
||||
end
|
||||
|
||||
def invoke!(post_comment: false, downstream_job_name: nil)
|
||||
def invoke!(downstream_job_name: nil)
|
||||
pipeline = super
|
||||
gitlab = gitlab_client(:upstream)
|
||||
project_path = variables['TOP_UPSTREAM_SOURCE_PROJECT']
|
||||
merge_request_id = variables['TOP_UPSTREAM_MERGE_REQUEST_IID']
|
||||
comment = "<!-- #{IDENTIFIABLE_NOTE_TAG} --> \nStarted database testing [pipeline](https://ops.gitlab.net/#{downstream_project_path}/-/pipelines/#{pipeline.id}) " \
|
||||
"(limited access). This comment will be updated once the pipeline has finished running."
|
||||
|
||||
# Look for an existing note
|
||||
db_testing_notes = gitlab.merge_request_notes(project_path, merge_request_id).auto_paginate.select do |note|
|
||||
db_testing_notes = com_gitlab_client.merge_request_notes(project_path, merge_request_id).auto_paginate.select do |note|
|
||||
note.body.include?(IDENTIFIABLE_NOTE_TAG)
|
||||
end
|
||||
|
||||
if db_testing_notes.empty?
|
||||
# This is the first note
|
||||
note = gitlab.create_merge_request_note(project_path, merge_request_id, comment)
|
||||
note = com_gitlab_client.create_merge_request_note(project_path, merge_request_id, comment)
|
||||
|
||||
puts "Posted comment to:\n"
|
||||
puts "https://gitlab.com/#{project_path}/-/merge_requests/#{merge_request_id}#note_#{note.id}"
|
||||
|
@ -385,19 +381,15 @@ module Trigger
|
|||
|
||||
private
|
||||
|
||||
def gitlab_client(type)
|
||||
@gitlab_clients ||= {
|
||||
downstream: Gitlab.client(
|
||||
endpoint: 'https://ops.gitlab.net/api/v4',
|
||||
private_token: self.class.access_token
|
||||
),
|
||||
upstream: Gitlab.client(
|
||||
endpoint: 'https://gitlab.com/api/v4',
|
||||
private_token: Base.access_token
|
||||
)
|
||||
}
|
||||
def ops_gitlab_client
|
||||
@ops_gitlab_client ||= Gitlab.client(
|
||||
endpoint: 'https://ops.gitlab.net/api/v4',
|
||||
private_token: ENV['GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN']
|
||||
)
|
||||
end
|
||||
|
||||
@gitlab_clients[type]
|
||||
def downstream_client
|
||||
ops_gitlab_client
|
||||
end
|
||||
|
||||
def trigger_token
|
||||
|
@ -426,18 +418,6 @@ module Trigger
|
|||
end
|
||||
end
|
||||
|
||||
class CommitComment
|
||||
def self.post!(downstream_pipeline, gitlab_client)
|
||||
gitlab_client.create_commit_comment(
|
||||
ENV['CI_PROJECT_PATH'],
|
||||
Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'],
|
||||
"The [`#{ENV['CI_JOB_NAME']}`](#{ENV['CI_JOB_URL']}) job from pipeline #{ENV['CI_PIPELINE_URL']} triggered #{downstream_pipeline.web_url} downstream.")
|
||||
|
||||
rescue Gitlab::Error::Error => error
|
||||
puts "Ignoring the following error: #{error}"
|
||||
end
|
||||
end
|
||||
|
||||
class Pipeline
|
||||
INTERVAL = 60 # seconds
|
||||
MAX_DURATION = 3600 * 3 # 3 hours
|
||||
|
|
|
@ -49,6 +49,7 @@ export const projectWorkItemTypesQueryResponse = {
|
|||
nodes: [
|
||||
{ id: 'gid://gitlab/WorkItems::Type/1', name: 'Issue' },
|
||||
{ id: 'gid://gitlab/WorkItems::Type/2', name: 'Incident' },
|
||||
{ id: 'gid://gitlab/WorkItems::Type/3', name: 'Task' },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -158,6 +158,11 @@ describe('Create work item component', () => {
|
|||
it('adds padding for content', () => {
|
||||
expect(findContent().classes('gl-px-5')).toBe(true);
|
||||
});
|
||||
|
||||
it('defaults type to `Task`', async () => {
|
||||
await waitForPromises();
|
||||
expect(findSelect().attributes('value')).toBe('gid://gitlab/WorkItems::Type/3');
|
||||
});
|
||||
});
|
||||
|
||||
it('displays a loading icon inside dropdown when work items query is loading', () => {
|
||||
|
@ -181,7 +186,7 @@ describe('Create work item component', () => {
|
|||
});
|
||||
|
||||
it('displays a list of work item types', () => {
|
||||
expect(findSelect().attributes('options').split(',')).toHaveLength(3);
|
||||
expect(findSelect().attributes('options').split(',')).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('selects a work item type on click', async () => {
|
||||
|
|
|
@ -21,29 +21,36 @@ RSpec.describe Trigger do
|
|||
'GITLAB_USER_NAME' => 'gitlab_user_name',
|
||||
'GITLAB_USER_LOGIN' => 'gitlab_user_login',
|
||||
'QA_IMAGE' => 'qa_image',
|
||||
'OMNIBUS_GITLAB_CACHE_UPDATE' => 'omnibus_gitlab_cache_update'
|
||||
'OMNIBUS_GITLAB_CACHE_UPDATE' => 'omnibus_gitlab_cache_update',
|
||||
'OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN' => nil,
|
||||
'DOCS_PROJECT_API_TOKEN' => nil
|
||||
}
|
||||
end
|
||||
|
||||
let(:stubbed_downstream_gitlab_client) { double('downstream_gitlab_api_client') }
|
||||
let(:gitlab_client_private_token) { env['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN'] }
|
||||
let(:com_api_endpoint) { 'https://gitlab.com/api/v4' }
|
||||
let(:com_api_token) { env['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN'] }
|
||||
let(:com_gitlab_client) { double('com_gitlab_client') }
|
||||
|
||||
let(:downstream_gitlab_client_endpoint) { com_api_endpoint }
|
||||
let(:downstream_gitlab_client_token) { com_api_token }
|
||||
let(:downstream_gitlab_client) { com_gitlab_client }
|
||||
|
||||
let(:stubbed_pipeline) { Struct.new(:id, :web_url).new(42, 'pipeline_url') }
|
||||
let(:trigger_token) { env['CI_JOB_TOKEN'] }
|
||||
let(:api_endpoint) { 'https://gitlab.com/api/v4' }
|
||||
|
||||
before do
|
||||
stub_env(env)
|
||||
allow(subject).to receive(:puts)
|
||||
allow(Gitlab).to receive(:client)
|
||||
.with(
|
||||
endpoint: api_endpoint,
|
||||
private_token: gitlab_client_private_token
|
||||
endpoint: downstream_gitlab_client_endpoint,
|
||||
private_token: downstream_gitlab_client_token
|
||||
)
|
||||
.and_return(stubbed_downstream_gitlab_client)
|
||||
.and_return(downstream_gitlab_client)
|
||||
end
|
||||
|
||||
def expect_run_trigger_with_params(variables = {})
|
||||
expect(stubbed_downstream_gitlab_client).to receive(:run_trigger)
|
||||
expect(downstream_gitlab_client).to receive(:run_trigger)
|
||||
.with(
|
||||
downstream_project_path,
|
||||
trigger_token,
|
||||
|
@ -105,24 +112,11 @@ RSpec.describe Trigger do
|
|||
it 'waits for downstream pipeline' do
|
||||
expect_run_trigger_with_params
|
||||
expect(Trigger::Pipeline).to receive(:new)
|
||||
.with(downstream_project_path, stubbed_pipeline.id, stubbed_downstream_gitlab_client)
|
||||
.with(downstream_project_path, stubbed_pipeline.id, downstream_gitlab_client)
|
||||
|
||||
subject.invoke!
|
||||
end
|
||||
|
||||
context 'with post_comment: true' do
|
||||
before do
|
||||
stub_env('CI_COMMIT_REF_NAME', "#{ref}-ee")
|
||||
end
|
||||
|
||||
it 'posts a comment' do
|
||||
expect_run_trigger_with_params
|
||||
expect(Trigger::CommitComment).to receive(:post!).with(stubbed_pipeline, stubbed_downstream_gitlab_client)
|
||||
|
||||
subject.invoke!(post_comment: true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with downstream_job_name: "foo"' do
|
||||
let(:downstream_job) { Struct.new(:id, :name).new(42, 'foo') }
|
||||
let(:paginated_resources) { Struct.new(:auto_paginate).new([downstream_job]) }
|
||||
|
@ -133,10 +127,10 @@ RSpec.describe Trigger do
|
|||
|
||||
it 'fetches the downstream job' do
|
||||
expect_run_trigger_with_params
|
||||
expect(stubbed_downstream_gitlab_client).to receive(:pipeline_jobs)
|
||||
expect(downstream_gitlab_client).to receive(:pipeline_jobs)
|
||||
.with(downstream_project_path, stubbed_pipeline.id).and_return(paginated_resources)
|
||||
expect(Trigger::Job).to receive(:new)
|
||||
.with(downstream_project_path, downstream_job.id, stubbed_downstream_gitlab_client)
|
||||
.with(downstream_project_path, downstream_job.id, downstream_gitlab_client)
|
||||
|
||||
subject.invoke!(downstream_job_name: 'foo')
|
||||
end
|
||||
|
@ -405,7 +399,6 @@ RSpec.describe Trigger do
|
|||
let(:env) do
|
||||
super().merge(
|
||||
'QA_IMAGE' => 'qa_image',
|
||||
'OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN' => nil,
|
||||
'GITLAB_QA_OPTIONS' => 'gitlab_qa_options',
|
||||
'QA_TESTS' => 'qa_tests',
|
||||
'ALLURE_JOB_NAME' => 'allure_job_name'
|
||||
|
@ -651,6 +644,8 @@ RSpec.describe Trigger do
|
|||
end
|
||||
|
||||
describe Trigger::Docs do
|
||||
let(:downstream_project_path) { 'gitlab-org/gitlab-docs' }
|
||||
|
||||
describe '#variables' do
|
||||
describe "BRANCH_CE" do
|
||||
before do
|
||||
|
@ -760,14 +755,12 @@ RSpec.describe Trigger do
|
|||
end
|
||||
|
||||
describe '#invoke!' do
|
||||
let(:downstream_project_path) { 'gitlab-org/gitlab-docs' }
|
||||
let(:trigger_token) { 'docs_trigger_token' }
|
||||
let(:ref) { 'main' }
|
||||
|
||||
let(:env) do
|
||||
super().merge(
|
||||
'CI_PROJECT_PATH' => 'gitlab-org/gitlab-foss',
|
||||
'DOCS_PROJECT_API_TOKEN' => nil,
|
||||
'DOCS_TRIGGER_TOKEN' => trigger_token
|
||||
)
|
||||
end
|
||||
|
@ -804,6 +797,42 @@ RSpec.describe Trigger do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cleanup!' do
|
||||
let(:downstream_environment_response) { double('downstream_environment', id: 42) }
|
||||
let(:downstream_environments_response) { [downstream_environment_response] }
|
||||
|
||||
before do
|
||||
expect(com_gitlab_client).to receive(:environments)
|
||||
.with(downstream_project_path, name: subject.__send__(:downstream_environment))
|
||||
.and_return(downstream_environments_response)
|
||||
expect(com_gitlab_client).to receive(:stop_environment)
|
||||
.with(downstream_project_path, downstream_environment_response.id)
|
||||
.and_return(downstream_environment_stopping_response)
|
||||
end
|
||||
|
||||
context "when stopping the environment succeeds" do
|
||||
let(:downstream_environment_stopping_response) { double('downstream_environment', state: 'stopped') }
|
||||
|
||||
it 'displays a success message' do
|
||||
expect(subject).to receive(:puts)
|
||||
.with("=> Downstream environment '#{subject.__send__(:downstream_environment)}' stopped.")
|
||||
|
||||
subject.cleanup!
|
||||
end
|
||||
end
|
||||
|
||||
context "when stopping the environment fails" do
|
||||
let(:downstream_environment_stopping_response) { double('downstream_environment', state: 'running') }
|
||||
|
||||
it 'displays a failure message' do
|
||||
expect(subject).to receive(:puts)
|
||||
.with("=> Downstream environment '#{subject.__send__(:downstream_environment)}' failed to stop.")
|
||||
|
||||
subject.cleanup!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Trigger::DatabaseTesting do
|
||||
|
@ -848,15 +877,20 @@ RSpec.describe Trigger do
|
|||
describe '#invoke!' do
|
||||
let(:downstream_project_path) { 'gitlab-com/database-team/gitlab-com-database-testing' }
|
||||
let(:trigger_token) { 'gitlabcom_database_testing_access_token' }
|
||||
let(:api_endpoint) { 'https://ops.gitlab.net/api/v4' }
|
||||
let(:gitlab_client_private_token) { 'gitlabcom_database_testing_access_token' }
|
||||
let(:ops_api_endpoint) { 'https://ops.gitlab.net/api/v4' }
|
||||
let(:ops_api_token) { 'gitlabcom_database_testing_access_token' }
|
||||
let(:ops_gitlab_client) { double('ops_gitlab_client') }
|
||||
|
||||
let(:downstream_gitlab_client_endpoint) { ops_api_endpoint }
|
||||
let(:downstream_gitlab_client_token) { ops_api_token }
|
||||
let(:downstream_gitlab_client) { ops_gitlab_client }
|
||||
|
||||
let(:ref) { 'master' }
|
||||
let(:stubbed_upstream_gitlab_client) { double('upstream_gitlab_api_client') }
|
||||
let(:mr_notes) { [double(body: described_class::IDENTIFIABLE_NOTE_TAG)] }
|
||||
|
||||
let(:env) do
|
||||
super().merge(
|
||||
'GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN' => gitlab_client_private_token,
|
||||
'GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN' => ops_api_token,
|
||||
'GITLABCOM_DATABASE_TESTING_TRIGGER_TOKEN' => trigger_token
|
||||
)
|
||||
end
|
||||
|
@ -864,11 +898,11 @@ RSpec.describe Trigger do
|
|||
before do
|
||||
allow(Gitlab).to receive(:client)
|
||||
.with(
|
||||
endpoint: 'https://gitlab.com/api/v4',
|
||||
private_token: env['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
|
||||
endpoint: com_api_endpoint,
|
||||
private_token: com_api_token
|
||||
)
|
||||
.and_return(stubbed_upstream_gitlab_client)
|
||||
allow(stubbed_upstream_gitlab_client).to receive(:merge_request_notes)
|
||||
.and_return(com_gitlab_client)
|
||||
allow(com_gitlab_client).to receive(:merge_request_notes)
|
||||
.with(
|
||||
env['CI_PROJECT_PATH'],
|
||||
env['CI_MERGE_REQUEST_IID']
|
||||
|
@ -919,7 +953,7 @@ RSpec.describe Trigger do
|
|||
|
||||
it 'posts a new note' do
|
||||
expect_run_trigger_with_params
|
||||
expect(stubbed_upstream_gitlab_client).to receive(:create_merge_request_note)
|
||||
expect(com_gitlab_client).to receive(:create_merge_request_note)
|
||||
.with(
|
||||
env['CI_PROJECT_PATH'],
|
||||
env['CI_MERGE_REQUEST_IID'],
|
||||
|
|
Loading…
Reference in a new issue