gitlab-qa 6.7.0 → 6.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1615e54144d0b669245a15b6a5874efc1d00157fe859dbc6ff2e723380e9da10
4
- data.tar.gz: f3ccd0528987c838c793d1bbc2f742833584756bf7a87c58c29b60fa2f7b6ac3
3
+ metadata.gz: cb6d9e91936be3f2ffdcee43a8693171f691714e086de83065c3ef44580f095e
4
+ data.tar.gz: a154de6d77c7ffa54426282f0bee792ed13380a5bdb95534fc6bdbc50791c82c
5
5
  SHA512:
6
- metadata.gz: 47fce0af7a769ccb9dca14c87f3d1f169495324f753f3db60bb8aa10fc6e05a4612f0bc1704e884dca3d7349bd6d0972d5ca77421bba71f60fd03258e24bc52b
7
- data.tar.gz: f1d65176693a0091989392eec19425a34d2cbc1ee92cb428178ee22ca438b19e7246fd1306bfdaaa73f5d531a6c01ad5a6b2ee1324ca72ef0ba9b255ae4782f3
6
+ metadata.gz: b01ee4edc97797c0db5eeacc19dd427d7da082dcea78f7175921b17b73a128c529244aebf7129f2ff901da16496805cd9e6364fa6587db54676d10fcbc1f009d
7
+ data.tar.gz: d54a08f9c1e02c2bf16f214c3a468cf619438b4e9620cb052c0106c4a336c586218b41d3e050d5e39980d2e148f4ea77631e08b3cbe6afb25f34a1838e0281d6
@@ -2,6 +2,7 @@ stages:
2
2
  - check
3
3
  - release
4
4
  - test
5
+ - report
5
6
  - notify
6
7
 
7
8
  default:
@@ -48,6 +49,10 @@ variables:
48
49
  QA_CAN_TEST_GIT_PROTOCOL_V2: "true"
49
50
  QA_CAN_TEST_PRAEFECT: "false"
50
51
  QA_TESTCASES_REPORTING_PROJECT: "gitlab-org/quality/testcases"
52
+ QA_FAILURES_REPORTING_PROJECT: "rymai/gitlab-qa-issues"
53
+ # The --dry-run or --max-diff-ratio option can be set to modify the behavior of `exe/gitlab-qa-report --relate-failure-issue` without releasing a new gem version.
54
+ QA_FAILURES_REPORTER_OPTIONS: ""
55
+ QA_TESTCASE_SESSIONS_PROJECT: "gitlab-org/quality/testcase-sessions"
51
56
 
52
57
  .check-base:
53
58
  stage: check
@@ -95,6 +100,7 @@ release:
95
100
  - exe/gitlab-qa-report --update-screenshot-path "gitlab-qa-run-*/**/rspec-*.xml"
96
101
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
97
102
  - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
103
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --relate-failure-issue "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_FAILURES_REPORTING_PROJECT" $QA_FAILURES_REPORTER_OPTIONS || true; fi
98
104
  - exit $test_run_exit_code
99
105
 
100
106
  .ce-qa:
@@ -333,6 +339,7 @@ ce:update:
333
339
  - exe/gitlab-qa Test::Omnibus::Update ${RELEASE:=CE} ${RELEASE:=CE} -- $RSPEC_REPORT_OPTS || test_run_exit_code=$?
334
340
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
335
341
  - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
342
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --relate-failure-issue "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_FAILURES_REPORTING_PROJECT" $QA_FAILURES_REPORTER_OPTIONS || true; fi
336
343
  - exit $test_run_exit_code
337
344
  extends:
338
345
  - .test
@@ -347,6 +354,7 @@ ce:update-quarantine:
347
354
  - exe/gitlab-qa Test::Omnibus::Update ${RELEASE:=CE} ${RELEASE:=CE} -- --tag quarantine --tag ~orchestrated $RSPEC_REPORT_OPTS || test_run_exit_code=$?
348
355
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
349
356
  - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
357
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --relate-failure-issue "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_FAILURES_REPORTING_PROJECT" $QA_FAILURES_REPORTER_OPTIONS || true; fi
350
358
  - exit $test_run_exit_code
351
359
  extends:
352
360
  - .test
@@ -360,6 +368,7 @@ ee:update:
360
368
  - exe/gitlab-qa Test::Omnibus::Update ${RELEASE:=EE} ${RELEASE:=EE} -- $RSPEC_REPORT_OPTS || test_run_exit_code=$?
361
369
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
362
370
  - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
371
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --relate-failure-issue "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_FAILURES_REPORTING_PROJECT" $QA_FAILURES_REPORTER_OPTIONS || true; fi
363
372
  - exit $test_run_exit_code
364
373
  extends:
365
374
  - .test
@@ -374,6 +383,7 @@ ee:update-quarantine:
374
383
  - exe/gitlab-qa Test::Omnibus::Update ${RELEASE:=EE} ${RELEASE:=EE} -- --tag quarantine --tag ~orchestrated $RSPEC_REPORT_OPTS || test_run_exit_code=$?
375
384
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
376
385
  - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
386
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --relate-failure-issue "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_FAILURES_REPORTING_PROJECT" $QA_FAILURES_REPORTER_OPTIONS || true; fi
377
387
  - exit $test_run_exit_code
378
388
  extends:
379
389
  - .test
@@ -941,6 +951,22 @@ staging:
941
951
  - .only-qa
942
952
  allow_failure: true
943
953
 
954
+ generate_test_session:
955
+ stage: report
956
+ rules:
957
+ - if: '$TOP_UPSTREAM_SOURCE_JOB && $TOP_UPSTREAM_SOURCE_REF == "master"'
958
+ when: always
959
+ - if: '$TOP_UPSTREAM_SOURCE_JOB =~ /\Ahttps:\/\/ops.gitlab.net\//'
960
+ when: always
961
+ artifacts:
962
+ when: always
963
+ expire_in: 10d
964
+ paths:
965
+ - REPORT_ISSUE_URL
966
+ script:
967
+ - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
968
+ - exe/gitlab-qa-report --generate-test-session "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASE_SESSIONS_PROJECT"
969
+
944
970
  .notify_upstream_commit:
945
971
  stage: notify
946
972
  image: ruby:2.6
@@ -966,7 +992,7 @@ notify_upstream_commit:failure:
966
992
  .notify_slack:
967
993
  image: alpine
968
994
  stage: notify
969
- dependencies: []
995
+ dependencies: ['generate_test_session']
970
996
  cache: {}
971
997
  before_script:
972
998
  - apk update && apk add git curl bash
@@ -985,4 +1011,4 @@ notify_slack:
985
1011
  - echo "RELEASE is ${RELEASE}"
986
1012
  - echo "CI_PIPELINE_URL is $CI_PIPELINE_URL"
987
1013
  - echo "TOP_UPSTREAM_SOURCE_JOB is $TOP_UPSTREAM_SOURCE_JOB"
988
- - bin/slack $NOTIFY_CHANNEL "☠️ QA against $RELEASE failed! ☠️ See $CI_PIPELINE_URL (triggered from $TOP_UPSTREAM_SOURCE_JOB)" ci_failing
1014
+ - 'bin/slack $NOTIFY_CHANNEL "☠️ QA against $RELEASE failed! ☠️ See the test session report: $(cat REPORT_ISSUE_URL), and pipeline: $CI_PIPELINE_URL (triggered from $TOP_UPSTREAM_SOURCE_JOB)" ci_failing'
@@ -4,7 +4,7 @@
4
4
 
5
5
  The [maven repository spec](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/specs/features/ee/browser_ui/5_package/maven_repository_spec.rb) creates a Maven artifact and links it to a GitLab project. The artifact is created within a [Maven docker image](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/service/docker_run/maven.rb#L8).
6
6
 
7
- Using `gitlab-qa` to run these tests reduces the liklihood of network errors between the maven container and GitLab instance.
7
+ Using `gitlab-qa` to run these tests reduces the likelihood of network errors between the maven container and GitLab instance.
8
8
 
9
9
  To run this with `gitlab-qa` you can use the `Test::Instance::Image` that is needed for your test. For example:
10
10
 
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'rubocop', '~> 0.82.0'
28
28
  spec.add_development_dependency 'rubocop-rspec', '~> 1.36'
29
29
  spec.add_development_dependency 'webmock', '3.7.0'
30
- spec.add_runtime_dependency 'activesupport', '~> 6.0.2'
31
- spec.add_runtime_dependency 'gitlab', '~> 4.11.0'
30
+ spec.add_runtime_dependency 'activesupport', '~> 6.0.2'
31
+ spec.add_runtime_dependency 'gitlab', '~> 4.16.1'
32
32
  spec.add_runtime_dependency 'http', '4.3.0'
33
33
  spec.add_runtime_dependency 'nokogiri', '~> 1.10'
34
34
  spec.add_runtime_dependency 'table_print', '1.5.6'
@@ -99,12 +99,15 @@ module Gitlab
99
99
 
100
100
  module Report
101
101
  autoload :GitlabIssueClient, 'gitlab/qa/report/gitlab_issue_client'
102
+ autoload :GitlabIssueDryClient, 'gitlab/qa/report/gitlab_issue_dry_client'
102
103
  autoload :BaseTestResults, 'gitlab/qa/report/base_test_results'
104
+ autoload :RelateFailureIssue, 'gitlab/qa/report/relate_failure_issue'
103
105
  autoload :JsonTestResults, 'gitlab/qa/report/json_test_results'
104
106
  autoload :JUnitTestResults, 'gitlab/qa/report/junit_test_results'
105
107
  autoload :PrepareStageReports, 'gitlab/qa/report/prepare_stage_reports'
106
108
  autoload :ReportAsIssue, 'gitlab/qa/report/report_as_issue'
107
109
  autoload :ResultsInIssues, 'gitlab/qa/report/results_in_issues'
110
+ autoload :GenerateTestSession, 'gitlab/qa/report/generate_test_session'
108
111
  autoload :SummaryTable, 'gitlab/qa/report/summary_table'
109
112
  autoload :TestResult, 'gitlab/qa/report/test_result'
110
113
  autoload :UpdateScreenshotPath, 'gitlab/qa/report/update_screenshot_path'
@@ -53,6 +53,7 @@ module Gitlab
53
53
 
54
54
  def prepare
55
55
  prepare_docker_image
56
+ prepare_docker_container
56
57
  prepare_network
57
58
  end
58
59
 
@@ -70,6 +71,12 @@ module Gitlab
70
71
  docker.network_create(network)
71
72
  end
72
73
 
74
+ def prepare_docker_container
75
+ return unless docker.container_exists?(name)
76
+
77
+ docker.remove(name)
78
+ end
79
+
73
80
  def start # rubocop:disable Metrics/AbcSize
74
81
  docker.run(image, tag) do |command|
75
82
  command << "-d"
@@ -63,6 +63,14 @@ module Gitlab
63
63
  Docker::Command.execute("rm -f #{name}")
64
64
  end
65
65
 
66
+ def container_exists?(name)
67
+ Docker::Command.execute("container inspect #{name}")
68
+ rescue Docker::Shellout::StatusError
69
+ false
70
+ else
71
+ true
72
+ end
73
+
66
74
  def network_exists?(name)
67
75
  Docker::Command.execute("network inspect #{name}")
68
76
  rescue Docker::Shellout::StatusError
@@ -6,8 +6,11 @@ module Gitlab
6
6
  class BaseTestResults
7
7
  include Enumerable
8
8
 
9
+ attr_reader :path
10
+
9
11
  def initialize(path)
10
- @results = parse(path)
12
+ @path = path
13
+ @results = parse
11
14
  @testcases = process
12
15
  end
13
16
 
@@ -15,7 +18,7 @@ module Gitlab
15
18
  testcases.each(&block)
16
19
  end
17
20
 
18
- def write(path)
21
+ def write
19
22
  raise NotImplementedError
20
23
  end
21
24
 
@@ -23,7 +26,7 @@ module Gitlab
23
26
 
24
27
  attr_reader :results, :testcases
25
28
 
26
- def parse(path)
29
+ def parse
27
30
  raise NotImplementedError
28
31
  end
29
32
 
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Report
6
+ class GenerateTestSession < ReportAsIssue
7
+ private
8
+
9
+ def run!
10
+ puts "Generating test results in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
11
+
12
+ tests = Dir.glob(files).flat_map do |path|
13
+ puts "Loading tests in #{path}"
14
+
15
+ Report::JsonTestResults.new(path).to_a
16
+ end
17
+
18
+ issue = gitlab.create_issue(
19
+ title: "Test session report | #{Runtime::Env.deploy_environment}",
20
+ description: generate_description(tests),
21
+ labels: ['Quality', 'QA', 'triage report']
22
+ )
23
+
24
+ File.write('REPORT_ISSUE_URL', issue.web_url)
25
+ end
26
+
27
+ def generate_description(tests)
28
+ <<~MARKDOWN
29
+ ## Session summary
30
+
31
+ * Deploy version: #{Runtime::Env.deploy_version}
32
+ * Pipeline: [#{Runtime::Env.ci_pipeline_id}](#{Runtime::Env.ci_pipeline_url})
33
+ #{generate_summary(tests: tests)}
34
+
35
+ #{generate_stages_listing(tests)}
36
+
37
+ ## Release QA issue
38
+
39
+ * #{Runtime::Env.qa_issue_url}
40
+ MARKDOWN
41
+ end
42
+
43
+ def generate_summary(tests:, tests_by_status: nil)
44
+ tests_by_status ||= tests.group_by(&:status)
45
+ total = tests.size
46
+ passed = tests_by_status['passed']&.size || 0
47
+ failed = tests_by_status['failed']&.size || 0
48
+ others = total - passed - failed
49
+
50
+ <<~MARKDOWN.chomp
51
+ * Total #{total} tests
52
+ * Passed #{passed} tests
53
+ * Failed #{failed} tests
54
+ * #{others} other tests (usually skipped)
55
+ MARKDOWN
56
+ end
57
+
58
+ def generate_stages_listing(tests)
59
+ generate_tests_by_stage(tests).map do |stage, tests_for_stage|
60
+ tests_by_status = tests_for_stage.group_by(&:status)
61
+
62
+ <<~MARKDOWN.chomp
63
+ ### #{stage&.capitalize || 'Unknown'}
64
+
65
+ #{generate_summary(
66
+ tests: tests_for_stage, tests_by_status: tests_by_status)}
67
+
68
+ #{generate_testcase_listing_by_status(
69
+ tests: tests_for_stage, tests_by_status: tests_by_status)}
70
+ MARKDOWN
71
+ end.join("\n\n")
72
+ end
73
+
74
+ def generate_tests_by_stage(tests)
75
+ # https://about.gitlab.com/handbook/product/product-categories/#devops-stages
76
+ ordering = %w[
77
+ manage
78
+ plan
79
+ create
80
+ verify
81
+ package
82
+ release
83
+ configure
84
+ monitor
85
+ secure
86
+ defend
87
+ growth
88
+ fulfillment
89
+ enablement
90
+ ]
91
+
92
+ tests.sort_by do |test|
93
+ ordering.index(test.stage) || ordering.size
94
+ end.group_by(&:stage)
95
+ end
96
+
97
+ def generate_testcase_listing_by_status(tests:, tests_by_status:)
98
+ failed_tests = tests_by_status['failed']
99
+ passed_tests = tests_by_status['passed']
100
+ other_tests = tests.reject do |test|
101
+ test.status == 'failed' || test.status == 'passed'
102
+ end
103
+
104
+ [
105
+ (failed_listings(failed_tests) if failed_tests),
106
+ (passed_listings(passed_tests) if passed_tests),
107
+ (other_listings(other_tests) if other_tests.any?)
108
+ ].compact.join("\n\n")
109
+ end
110
+
111
+ def failed_listings(failed_tests)
112
+ generate_testcase_listing(failed_tests)
113
+ end
114
+
115
+ def passed_listings(passed_tests)
116
+ <<~MARKDOWN.chomp
117
+ <details><summary>Passed tests:</summary>
118
+
119
+ #{generate_testcase_listing(passed_tests)}
120
+
121
+ </details>
122
+ MARKDOWN
123
+ end
124
+
125
+ def other_listings(other_tests)
126
+ <<~MARKDOWN.chomp
127
+ <details><summary>Other tests:</summary>
128
+
129
+ #{generate_testcase_listing(other_tests)}
130
+
131
+ </details>
132
+ MARKDOWN
133
+ end
134
+
135
+ def generate_testcase_listing(tests)
136
+ body = tests.group_by(&:testcase).map do |testcase, tests_with_same_testcase|
137
+ tests_with_same_testcase.sort_by!(&:name)
138
+ [
139
+ generate_test_text(testcase, tests_with_same_testcase),
140
+ generate_test_job(tests_with_same_testcase),
141
+ generate_test_status(tests_with_same_testcase),
142
+ generate_test_actions(tests_with_same_testcase)
143
+ ].join(' | ')
144
+ end.join("\n")
145
+
146
+ <<~MARKDOWN.chomp
147
+ | Test | Job | Status | Action |
148
+ | - | - | - | - |
149
+ #{body}
150
+ MARKDOWN
151
+ end
152
+
153
+ def generate_test_text(testcase, tests_with_same_testcase)
154
+ text = tests_with_same_testcase.map(&:name).uniq.join(', ')
155
+
156
+ if testcase
157
+ "[#{text}](#{testcase})"
158
+ else
159
+ text
160
+ end
161
+ end
162
+
163
+ def generate_test_job(tests_with_same_testcase)
164
+ tests_with_same_testcase.map do |test|
165
+ ci_job_id = test.ci_job_url[/\d+\z/]
166
+
167
+ "[#{ci_job_id}](#{test.ci_job_url})#{' ~"quarantine"' if test.quarantine?}"
168
+ end.uniq.join(', ')
169
+ end
170
+
171
+ def generate_test_status(tests_with_same_testcase)
172
+ tests_with_same_testcase.map(&:status).uniq.map do |status|
173
+ %(~"#{status}")
174
+ end.join(', ')
175
+ end
176
+
177
+ def generate_test_actions(tests_with_same_testcase)
178
+ # All failed tests would be grouped together, meaning that
179
+ # if one failed, all the tests here would be failed too.
180
+ # So this check is safe. Same applies to 'passed'.
181
+ # But all other status might be mixing together,
182
+ # we cannot assume other statuses.
183
+ if tests_with_same_testcase.first.status == 'failed'
184
+ tests_having_failure_issue =
185
+ tests_with_same_testcase.select(&:failure_issue)
186
+
187
+ if tests_having_failure_issue.any?
188
+ items = tests_having_failure_issue.map do |test|
189
+ "<li>[ ] [failure issue](#{test.failure_issue})</li>"
190
+ end.join(' ')
191
+
192
+ "<ul>#{items}</ul>"
193
+ else
194
+ '<ul><li>[ ] failure issue exists or was created</li></ul>'
195
+ end
196
+ else
197
+ '-'
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -45,7 +45,7 @@ module Gitlab
45
45
  abort_not_permitted
46
46
  end
47
47
 
48
- def find_issues(iid:, options: {}, &select)
48
+ def find_issues(iid: nil, options: {}, &select)
49
49
  select ||= :itself
50
50
 
51
51
  handle_gitlab_client_exceptions do
@@ -57,15 +57,17 @@ module Gitlab
57
57
  end
58
58
  end
59
59
 
60
+ def find_issue_discussions(iid:)
61
+ handle_gitlab_client_exceptions do
62
+ Gitlab.issue_discussions(project, iid, order_by: 'created_at', sort: 'asc').auto_paginate
63
+ end
64
+ end
65
+
60
66
  def create_issue(title:, description:, labels:)
61
- puts "Creating issue..."
67
+ attrs = { description: description, labels: labels }
62
68
 
63
69
  handle_gitlab_client_exceptions do
64
- Gitlab.create_issue(
65
- project,
66
- title,
67
- { description: description, labels: labels }
68
- )
70
+ Gitlab.create_issue(project, title, attrs)
69
71
  end
70
72
  end
71
73
 
@@ -75,6 +77,18 @@ module Gitlab
75
77
  end
76
78
  end
77
79
 
80
+ def create_issue_note(iid:, note:)
81
+ handle_gitlab_client_exceptions do
82
+ Gitlab.create_issue_note(project, iid, note)
83
+ end
84
+ end
85
+
86
+ def add_note_to_issue_discussion_as_thread(iid:, discussion_id:, body:)
87
+ handle_gitlab_client_exceptions do
88
+ Gitlab.add_note_to_issue_discussion_as_thread(project, iid, discussion_id, body: body)
89
+ end
90
+ end
91
+
78
92
  def handle_gitlab_client_exceptions
79
93
  yield
80
94
  rescue Gitlab::Error::NotFound
@@ -95,6 +109,9 @@ module Gitlab
95
109
  pipeline = QA::Runtime::Env.pipeline_from_project_name
96
110
  channel = pipeline == "canary" ? "qa-production" : "qa-#{pipeline}"
97
111
  error_msg = warn_exception(e)
112
+
113
+ return unless QA::Runtime::Env.ci_commit_ref_name == 'master'
114
+
98
115
  slack_options = {
99
116
  channel: channel,
100
117
  icon_emoji: ':ci_failing:',