summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-31 19:27:02 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-31 19:27:02 +0000
commit44d033747da39826bcf6e50adc26e7130159f90b (patch)
tree9557e682489fc8f776bccb70618927d533edc184
parenta47a6d6fd56f92497b164d45ff9b53023202c4b1 (diff)
downloadgitlab-ce-44d033747da39826bcf6e50adc26e7130159f90b.tar.gz
Add latest changes from gitlab-org/gitlab@15-10-stable-ee
-rw-r--r--.gitlab/ci/notify.gitlab-ci.yml12
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml7
-rw-r--r--danger/stable_branch_patch/Dangerfile2
-rw-r--r--scripts/api/create_merge_request_discussion.rb33
-rw-r--r--scripts/api/get_package_and_test_job.rb39
-rwxr-xr-xscripts/generate-failed-package-and-test-mr-message.rb79
-rw-r--r--spec/scripts/api/create_merge_request_discussion_spec.rb40
-rw-r--r--spec/scripts/api/get_package_and_test_job_spec.rb47
-rw-r--r--spec/scripts/generate_failed_package_and_test_mr_message_spec.rb79
-rw-r--r--spec/tooling/danger/stable_branch_spec.rb2
-rw-r--r--tooling/danger/stable_branch.rb10
11 files changed, 343 insertions, 7 deletions
diff --git a/.gitlab/ci/notify.gitlab-ci.yml b/.gitlab/ci/notify.gitlab-ci.yml
index 795a0cd6439..90ae1813e5f 100644
--- a/.gitlab/ci/notify.gitlab-ci.yml
+++ b/.gitlab/ci/notify.gitlab-ci.yml
@@ -95,3 +95,15 @@ create-issues-for-failing-tests:
- ${FAILING_ISSUE_JSON_DIR}/
when: always
expire_in: 2 days
+
+notify-package-and-test-failure:
+ extends:
+ - .notify-defaults
+ - .notify:rules:notify-package-and-test-failure
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}
+ before_script:
+ - source scripts/utils.sh
+ - apt-get update
+ - install_gitlab_gem
+ script:
+ - scripts/generate-failed-package-and-test-mr-message.rb
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index b4301c72347..eb00fb9ced4 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1140,6 +1140,13 @@
when: on_failure
allow_failure: true
+.notify:rules:notify-package-and-test-failure:
+ rules:
+ - <<: *if-not-canonical-namespace
+ when: never
+ - <<: *if-merge-request-targeting-stable-branch
+ when: on_failure
+
###############
# Pages rules #
###############
diff --git a/danger/stable_branch_patch/Dangerfile b/danger/stable_branch_patch/Dangerfile
index 2ac1b14c91f..a4b557c1eaa 100644
--- a/danger/stable_branch_patch/Dangerfile
+++ b/danger/stable_branch_patch/Dangerfile
@@ -2,7 +2,7 @@
if stable_branch.encourage_package_and_qa_execution?
markdown(<<~MARKDOWN)
- ## QA `e2e:package-and-test`
+ ## QA `e2e:package-and-test-ee`
**@#{helper.mr_author}, the `package-and-test` job must complete before merging this merge request.***
diff --git a/scripts/api/create_merge_request_discussion.rb b/scripts/api/create_merge_request_discussion.rb
new file mode 100644
index 00000000000..2b380d2e216
--- /dev/null
+++ b/scripts/api/create_merge_request_discussion.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'gitlab'
+require_relative 'default_options'
+
+class CreateMergeRequestDiscussion
+ def initialize(options)
+ @merge_request = options.fetch(:merge_request)
+ @project = options.fetch(:project)
+
+ # If api_token is nil, it's set to '' to allow unauthenticated requests (for forks).
+ api_token = options.fetch(:api_token, '')
+
+ warn "No API token given." if api_token.empty?
+
+ @client = Gitlab.client(
+ endpoint: options.fetch(:endpoint, API::DEFAULT_OPTIONS[:endpoint]),
+ private_token: api_token
+ )
+ end
+
+ def execute(content)
+ client.create_merge_request_discussion(
+ project,
+ merge_request.fetch('iid'),
+ body: content
+ )
+ end
+
+ private
+
+ attr_reader :merge_request, :client, :project
+end
diff --git a/scripts/api/get_package_and_test_job.rb b/scripts/api/get_package_and_test_job.rb
new file mode 100644
index 00000000000..dbc29f754d0
--- /dev/null
+++ b/scripts/api/get_package_and_test_job.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'gitlab'
+
+require_relative 'default_options'
+
+class GetPackageAndTestJob
+ def initialize(options)
+ @project = options.fetch(:project)
+ @pipeline_id = options.fetch(:pipeline_id)
+
+ # If api_token is nil, it's set to '' to allow unauthenticated requests (for forks).
+ api_token = options.fetch(:api_token, '')
+
+ warn "No API token given." if api_token.empty?
+
+ @client = Gitlab.client(
+ endpoint: options.fetch(:endpoint) || API::DEFAULT_OPTIONS[:endpoint],
+ private_token: api_token
+ )
+ end
+
+ def execute
+ package_and_test_job = nil
+
+ client.pipeline_bridges(project, pipeline_id, scope: 'failed', per_page: 100).auto_paginate do |job|
+ if job['name'].include?('package-and-test')
+ package_and_test_job = job
+ break
+ end
+ end
+
+ package_and_test_job
+ end
+
+ private
+
+ attr_reader :project, :pipeline_id, :exclude_allowed_to_fail_jobs, :client
+end
diff --git a/scripts/generate-failed-package-and-test-mr-message.rb b/scripts/generate-failed-package-and-test-mr-message.rb
new file mode 100755
index 00000000000..a53b393498c
--- /dev/null
+++ b/scripts/generate-failed-package-and-test-mr-message.rb
@@ -0,0 +1,79 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+require 'optparse'
+require 'json'
+
+require_relative 'api/create_merge_request_discussion'
+require_relative 'api/commit_merge_requests'
+require_relative 'api/get_package_and_test_job'
+
+class GenerateFailedPackageAndTestMrMessage
+ DEFAULT_OPTIONS = {
+ project: nil
+ }.freeze
+
+ def initialize(options)
+ @project = options.fetch(:project)
+ end
+
+ def execute
+ return unless failed_package_and_test_job
+
+ add_discussion_to_mr
+ end
+
+ private
+
+ attr_reader :project
+
+ def add_discussion_to_mr
+ CreateMergeRequestDiscussion.new(
+ API::DEFAULT_OPTIONS.merge(merge_request: merge_request)
+ ).execute(content)
+ end
+
+ def failed_package_and_test_job
+ @failed_package_and_test_job ||= GetPackageAndTestJob.new(API::DEFAULT_OPTIONS).execute
+ end
+
+ def merge_request
+ @merge_request ||= CommitMergeRequests.new(
+ API::DEFAULT_OPTIONS.merge(sha: ENV['CI_MERGE_REQUEST_SOURCE_BRANCH_SHA'])
+ ).execute.first
+ end
+
+ def content
+ <<~MARKDOWN
+ :warning: @#{author_username} The `e2e:package-and-test-ee` job has failed.
+
+ - Pipeline: #{pipeline_link}
+ - `package-and-test` pipeline: #{failed_package_and_test_job['web_url']}
+
+ Ping your team's associated Software Engineer in Test (SET) to confirm the failures are unrelated to the merge request.
+ If there's no SET assigned, ask for assistance on the `#quality` Slack channel.
+ MARKDOWN
+ end
+
+ def author_username
+ merge_request['author']['username'] if merge_request
+ end
+
+ def pipeline_link
+ "[##{ENV['CI_PIPELINE_ID']}](#{ENV['CI_PIPELINE_URL']})"
+ end
+end
+
+if $PROGRAM_NAME == __FILE__
+ options = GenerateFailedPackageAndTestMrMessage::DEFAULT_OPTIONS.dup
+
+ OptionParser.new do |opts|
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ GenerateFailedPackageAndTestMrMessage.new(options).execute
+end
diff --git a/spec/scripts/api/create_merge_request_discussion_spec.rb b/spec/scripts/api/create_merge_request_discussion_spec.rb
new file mode 100644
index 00000000000..3867f6532a9
--- /dev/null
+++ b/spec/scripts/api/create_merge_request_discussion_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../scripts/api/create_merge_request_discussion'
+
+RSpec.describe CreateMergeRequestDiscussion, feature_category: :tooling do
+ describe '#execute' do
+ let(:project_id) { 12345 }
+ let(:iid) { 1 }
+ let(:content) { 'test123' }
+
+ let(:options) do
+ {
+ api_token: 'token',
+ endpoint: 'https://example.gitlab.com',
+ project: project_id,
+ merge_request: {
+ 'iid' => iid
+ }
+ }
+ end
+
+ subject { described_class.new(options).execute(content) }
+
+ it 'requests commit_merge_requests from the gitlab client' do
+ expected_result = true
+ client = double('Gitlab::Client') # rubocop:disable RSpec/VerifiedDoubles
+
+ expect(Gitlab).to receive(:client)
+ .with(endpoint: options[:endpoint], private_token: options[:api_token])
+ .and_return(client)
+
+ expect(client).to receive(:create_merge_request_discussion).with(
+ project_id, iid, body: content
+ ).and_return(expected_result)
+
+ expect(subject).to eq(expected_result)
+ end
+ end
+end
diff --git a/spec/scripts/api/get_package_and_test_job_spec.rb b/spec/scripts/api/get_package_and_test_job_spec.rb
new file mode 100644
index 00000000000..60bb26cbcaf
--- /dev/null
+++ b/spec/scripts/api/get_package_and_test_job_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../scripts/api/get_package_and_test_job'
+
+RSpec.describe GetPackageAndTestJob, feature_category: :tooling do
+ describe '#execute' do
+ let(:project) { 12345 }
+ let(:pipeline_id) { 1 }
+
+ let(:options) do
+ {
+ api_token: 'token',
+ endpoint: 'https://example.gitlab.com',
+ project: project,
+ pipeline_id: pipeline_id
+ }
+ end
+
+ subject { described_class.new(options).execute }
+
+ it 'requests commit_merge_requests from the gitlab client' do
+ client_result = [
+ { 'name' => 'foo' },
+ { 'name' => 'e2e:package-and-test-ee' },
+ { 'name' => 'bar' }
+ ]
+ client = double('Gitlab::Client') # rubocop:disable RSpec/VerifiedDoubles
+ client_response = double('Gitlab::ClientResponse') # rubocop:disable RSpec/VerifiedDoubles
+
+ expect(Gitlab).to receive(:client)
+ .with(endpoint: options[:endpoint], private_token: options[:api_token])
+ .and_return(client)
+
+ expect(client).to receive(:pipeline_bridges).with(
+ project, pipeline_id, scope: 'failed', per_page: 100
+ ).and_return(client_response)
+
+ expect(client_response).to receive(:auto_paginate)
+ .and_yield(client_result[0])
+ .and_yield(client_result[1])
+ .and_yield(client_result[2])
+
+ expect(subject).to eq(client_result[1])
+ end
+ end
+end
diff --git a/spec/scripts/generate_failed_package_and_test_mr_message_spec.rb b/spec/scripts/generate_failed_package_and_test_mr_message_spec.rb
new file mode 100644
index 00000000000..79e63c95f65
--- /dev/null
+++ b/spec/scripts/generate_failed_package_and_test_mr_message_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../scripts/generate-failed-package-and-test-mr-message'
+require_relative '../support/helpers/stub_env'
+
+RSpec.describe GenerateFailedPackageAndTestMrMessage, feature_category: :tooling do
+ include StubENV
+
+ describe '#execute' do
+ let(:options) do
+ {
+ project: 1234,
+ api_token: 'asdf1234'
+ }
+ end
+
+ let(:commit_merge_request) do
+ {
+ 'author' => {
+ 'id' => '2',
+ 'username' => 'test_user'
+ }
+ }
+ end
+
+ let(:package_and_test_job) do
+ { 'web_url' => 'http://example.com' }
+ end
+
+ let(:merge_request) { instance_double(CommitMergeRequests, execute: [commit_merge_request]) }
+ let(:content) { /The `e2e:package-and-test-ee` job has failed./ }
+ let(:merge_request_discussion_client) { instance_double(CreateMergeRequestDiscussion, execute: true) }
+ let(:package_and_test_job_client) { instance_double(GetPackageAndTestJob, execute: package_and_test_job) }
+
+ subject { described_class.new(options).execute }
+
+ before do
+ stub_env(
+ 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA' => 'bfcd2b9b5cad0b889494ce830697392c8ca11257',
+ 'CI_PROJECT_ID' => '13083',
+ 'CI_PIPELINE_ID' => '1234567',
+ 'CI_PIPELINE_URL' => 'https://gitlab.com/gitlab-org/gitlab/-/pipelines/1234567',
+ 'PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE' => 'asdf1234'
+ )
+
+ allow(GetPackageAndTestJob).to receive(:new)
+ .with(API::DEFAULT_OPTIONS)
+ .and_return(package_and_test_job_client)
+ end
+
+ context 'when package-and-test fails' do
+ before do
+ allow(CommitMergeRequests).to receive(:new)
+ .with(API::DEFAULT_OPTIONS.merge(sha: ENV['CI_MERGE_REQUEST_SOURCE_BRANCH_SHA']))
+ .and_return(merge_request)
+ end
+
+ it 'successfully creates a discussion' do
+ expect(CreateMergeRequestDiscussion).to receive(:new)
+ .with(API::DEFAULT_OPTIONS.merge(merge_request: commit_merge_request))
+ .and_return(merge_request_discussion_client)
+
+ expect(merge_request_discussion_client).to receive(:execute).with(content)
+
+ expect(subject).to eq(true)
+ end
+ end
+
+ context 'when package-and-test is did not fail' do
+ let(:package_and_test_job_client) { instance_double(GetPackageAndTestJob, execute: nil) }
+
+ it 'does not add a discussion' do
+ expect(CreateMergeRequestDiscussion).not_to receive(:new)
+ expect(subject).to eq(nil)
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/stable_branch_spec.rb b/spec/tooling/danger/stable_branch_spec.rb
index b6ec4ad8895..b0a8ab3c132 100644
--- a/spec/tooling/danger/stable_branch_spec.rb
+++ b/spec/tooling/danger/stable_branch_spec.rb
@@ -197,7 +197,7 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do
let(:pipeline_bridges_response) do
[
{
- 'name' => 'e2e:package-and-test',
+ 'name' => 'e2e:package-and-test-ee',
'status' => pipeline_bridge_state,
'downstream_pipeline' => nil
}
diff --git a/tooling/danger/stable_branch.rb b/tooling/danger/stable_branch.rb
index be668731cb4..2751a6f0191 100644
--- a/tooling/danger/stable_branch.rb
+++ b/tooling/danger/stable_branch.rb
@@ -42,18 +42,18 @@ module Tooling
MSG
PIPELINE_EXPEDITE_ERROR_MESSAGE = <<~MSG
- ~"pipeline:expedite" is not allowed on stable branches because it causes the `e2e:package-and-test` job to be skipped.
+ ~"pipeline:expedite" is not allowed on stable branches because it causes the `e2e:package-and-test-ee` job to be skipped.
MSG
NEEDS_PACKAGE_AND_TEST_MESSAGE = <<~MSG
- The `e2e:package-and-test` job is not present, has been canceled, or needs to be automatically triggered.
+ The `e2e:package-and-test-ee` job is not present, has been canceled, or needs to be automatically triggered.
Please ensure the job is present in the latest pipeline, if necessary, retry the `danger-review` job.
- Read the "QA e2e:package-and-test" section for more details.
+ Read the "QA e2e:package-and-test-ee" section for more details.
MSG
WARN_PACKAGE_AND_TEST_MESSAGE = <<~MSG
- **The `e2e:package-and-test` job needs to succeed or have approval from a Software Engineer in Test.**
- Read the "QA e2e:package-and-test" section for more details.
+ **The `e2e:package-and-test-ee` job needs to succeed or have approval from a Software Engineer in Test.**
+ Read the "QA e2e:package-and-test-ee" section for more details.
MSG
# rubocop:disable Style/SignalException