Class: GitlabQuality::TestTooling::TestMeta::TestMetaUpdater
- Inherits:
-
Object
- Object
- GitlabQuality::TestTooling::TestMeta::TestMetaUpdater
- Includes:
- Concerns::FindSetDri
- Defined in:
- lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb
Instance Attribute Summary collapse
-
#dry_run ⇒ Object
readonly
Returns the value of attribute dry_run.
-
#processed_commits ⇒ Object
readonly
Returns the value of attribute processed_commits.
-
#processor ⇒ Object
readonly
Returns the value of attribute processor.
-
#project ⇒ Object
readonly
Returns the value of attribute project.
-
#ref ⇒ Object
readonly
Returns the value of attribute ref.
-
#report_issue ⇒ Object
readonly
Returns the value of attribute report_issue.
-
#specs_file ⇒ Object
readonly
Returns the value of attribute specs_file.
-
#token ⇒ Object
readonly
Returns the value of attribute token.
Instance Method Summary collapse
-
#add_processed_commit(file_path, changed_line_no, branch, spec) ⇒ Hash<String,Hash>
Add processed commits.
-
#batch_limit ⇒ Integer
Returns the number of records to process.
-
#branch_for_file_path(file_path) ⇒ <Gitlab::ObjectifiedHash>
Returns the branch for the given file_path.
-
#commit_changes(branch, message, file_path, new_content) ⇒ Gitlab::ObjectifiedHash
Commit changes to a branch.
-
#commit_processed?(file_path, changed_line_no) ⇒ Boolean
Checks if changes have already been made to given file_path and line number.
-
#create_branch(name_prefix, name, ref) ⇒ Gitlab::ObjectifiedHash
Create a branch from the ref.
-
#create_merge_request(title, branch, assignee_id = nil, reviewer_ids = [], labels = '') ⇒ Gitlab::ObjectifiedHash
Create a Merge Request with a given branch.
-
#existing_merge_requests(title:) ⇒ Array<Gitlab::ObjectifiedHash>
Returns and existing merge request with the given title.
-
#fetch_dri_id(test, devops_stage, section) ⇒ Array<Integer, String>
Fetch the id for the dri of the product group and stage The first item returned is the id of the assignee and the second item is the handle.
-
#fetch_issue(iid:) ⇒ Gitlab::ObjectifiedHash
Fetch an issue.
-
#find_example_match_lines(content, example_name) ⇒ Array<String, Integer>
Find all lines that contain any part of the example name.
-
#get_file_contents(file_path:, branch:) ⇒ String
Fetch contents of file from the repository.
-
#indentation(line) ⇒ Object
Provide indentation based on the given line.
-
#initialize(token:, project:, specs_file:, processor:, ref: 'master', dry_run: false) ⇒ TestMetaUpdater
constructor
A new instance of TestMetaUpdater.
- #invoke! ⇒ Object
-
#issue_client ⇒ GitlabIssueDryClient | GitlabIssueClient
Returns the GitlabIssueClient or GitlabIssueDryClient based on the value of dry_run.
-
#issue_is_closed?(issue) ⇒ Boolean
Check if issue is closed.
-
#issue_scoped_label(issue, scope) ⇒ String
Get scoped label from issue.
-
#label_from_feature_category(feature_category) ⇒ String
Infers the group label from the provided feature category.
-
#label_from_product_group(product_group) ⇒ String
Infers product group label from the provided product group.
-
#labels_inference ⇒ Object
Returns a cached instance of GitlabQuality::TestTooling::LabelsInference.
-
#merge_request_client ⇒ MergeRequestDryClient | MergeRequest
Returns the MergeRequestDryClient or MergeRequest based on the value of dry_run.
-
#post_message_on_slack(message) ⇒ HTTP::Response
Post a message on Slack.
-
#post_note_on_issue(note, issue_url) ⇒ Gitlab::ObjectifiedHash
Post note on isse.
-
#post_note_on_merge_request(note, merge_request_iid) ⇒ Gitlab::ObjectifiedHash
Post a note of merge reqest.
-
#quarantined?(matched_lines, file_contents) ⇒ Bolean
Scans the content from the matched line until ‘do` is found to look for quarantine token.
-
#single_spec_metrics_link(example_name) ⇒ String
Returns the link to the Grafana dashboard for single spec metrics.
-
#spec_desc_string_within_quotes(line) ⇒ String
Returns any test description string within single or double quotes.
-
#update_matched_line(matched_line, content) ⇒ Array<String, Integer>
Update the provided matched_line with content from the block if given.
-
#user_id_for_username(username) ⇒ Integer
Fetch id for the given GitLab username/handle.
Methods included from Concerns::FindSetDri
Constructor Details
#initialize(token:, project:, specs_file:, processor:, ref: 'master', dry_run: false) ⇒ TestMetaUpdater
Returns a new instance of TestMetaUpdater.
13 14 15 16 17 18 19 20 21 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 13 def initialize(token:, project:, specs_file:, processor:, ref: 'master', dry_run: false) @specs_file = specs_file @token = token @project = project @ref = ref @dry_run = dry_run @processor = processor @processed_commits = {} end |
Instance Attribute Details
#dry_run ⇒ Object (readonly)
Returns the value of attribute dry_run.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def dry_run @dry_run end |
#processed_commits ⇒ Object (readonly)
Returns the value of attribute processed_commits.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def processed_commits @processed_commits end |
#processor ⇒ Object (readonly)
Returns the value of attribute processor.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def processor @processor end |
#project ⇒ Object (readonly)
Returns the value of attribute project.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def project @project end |
#ref ⇒ Object (readonly)
Returns the value of attribute ref.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def ref @ref end |
#report_issue ⇒ Object (readonly)
Returns the value of attribute report_issue.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def report_issue @report_issue end |
#specs_file ⇒ Object (readonly)
Returns the value of attribute specs_file.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def specs_file @specs_file end |
#token ⇒ Object (readonly)
Returns the value of attribute token.
11 12 13 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 11 def token @token end |
Instance Method Details
#add_processed_commit(file_path, changed_line_no, branch, spec) ⇒ Hash<String,Hash>
Add processed commits.
processed_commits has the following form. Note that each key in the :commits hash is the changed line number and the value is the spec changed.
{
"/file/path/for/spec_1" =>
{ :commits =>
{
"34" => {"stage"=> "create", "product_group" => "source_code".. },
"38" => {"stage"=> "create", "product_group" => "source_code".. }
},
:branch => #<Gitlab::ObjectifiedHash>
},
"/file/path/for/spec_2" =>
{ :commits =>
{
"34" => {"stage"=> "create", "product_group" => "source_code".. },
"38" => {"stage"=> "create", "product_group" => "source_code".. }
},
:branch => #<Gitlab::ObjectifiedHash>
},
}
74 75 76 77 78 79 80 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 74 def add_processed_commit(file_path, changed_line_no, branch, spec) if processed_commits[file_path].nil? processed_commits[file_path] = { commits: { changed_line_no.to_s => spec }, branch: branch } elsif processed_commits[file_path][:commits][changed_line_no.to_s].nil? processed_commits[file_path][:commits].merge!({ changed_line_no.to_s => spec }) end end |
#batch_limit ⇒ Integer
Returns the number of records to process
41 42 43 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 41 def batch_limit ENV.fetch('BATCH_LIMIT', 10).to_i end |
#branch_for_file_path(file_path) ⇒ <Gitlab::ObjectifiedHash>
Returns the branch for the given file_path
95 96 97 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 95 def branch_for_file_path(file_path) processed_commits[file_path] && processed_commits[file_path][:branch] end |
#commit_changes(branch, message, file_path, new_content) ⇒ Gitlab::ObjectifiedHash
Commit changes to a branch
191 192 193 194 195 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 191 def commit_changes(branch, , file_path, new_content) @commits_client ||= (dry_run ? GitlabClient::CommitsDryClient : GitlabClient::CommitsClient) .new(token: token, project: project) @commits_client.create(branch['name'], file_path, new_content, ) end |
#commit_processed?(file_path, changed_line_no) ⇒ Boolean
Checks if changes have already been made to given file_path and line number
87 88 89 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 87 def commit_processed?(file_path, changed_line_no) processed_commits[file_path] && processed_commits[file_path][:commits][changed_line_no.to_s] end |
#create_branch(name_prefix, name, ref) ⇒ Gitlab::ObjectifiedHash
Create a branch from the ref
179 180 181 182 183 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 179 def create_branch(name_prefix, name, ref) branch_name = [name_prefix, name.gsub(/\W/, '-')] @branches_client ||= (dry_run ? GitlabClient::BranchesDryClient : GitlabClient::BranchesClient).new(token: token, project: project) @branches_client.create(branch_name.join('-'), ref) end |
#create_merge_request(title, branch, assignee_id = nil, reviewer_ids = [], labels = '') ⇒ Gitlab::ObjectifiedHash
Create a Merge Request with a given branch
206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 206 def create_merge_request(title, branch, assignee_id = nil, reviewer_ids = [], labels = '') description = yield merge_request_client.create_merge_request( title: title, source_branch: branch['name'], target_branch: ref, description: description, labels: labels, assignee_id: assignee_id, reviewer_ids: reviewer_ids) end |
#existing_merge_requests(title:) ⇒ Array<Gitlab::ObjectifiedHash>
Returns and existing merge request with the given title
325 326 327 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 325 def existing_merge_requests(title:) merge_request_client.find(options: { search: title, in: 'title', state: 'opened' }) end |
#fetch_dri_id(test, devops_stage, section) ⇒ Array<Integer, String>
Fetch the id for the dri of the product group and stage The first item returned is the id of the assignee and the second item is the handle
274 275 276 277 278 279 280 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 274 def fetch_dri_id(test, devops_stage, section) product_group = determine_product_group(test) return unless product_group assignee_handle = ENV.fetch('QA_TEST_DRI_HANDLE', nil) || test_dri(product_group, devops_stage, section) [user_id_for_username(assignee_handle), assignee_handle] end |
#fetch_issue(iid:) ⇒ Gitlab::ObjectifiedHash
Fetch an issue
240 241 242 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 240 def fetch_issue(iid:) issue_client.find_issues(iid: iid).first end |
#find_example_match_lines(content, example_name) ⇒ Array<String, Integer>
Find all lines that contain any part of the example name
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 114 def find_example_match_lines(content, example_name) lines = content.split("\n") matched_lines = [] example_name_for_parsing = example_name.dup lines.each_with_index do |line, line_index| string_within_quotes = spec_desc_string_within_quotes(line) regex = /^\s?#{Regexp.escape(string_within_quotes)}/ if string_within_quotes if !example_name_for_parsing.empty? && regex && example_name_for_parsing.match(regex) example_name_for_parsing.sub!(regex, '') matched_lines << [line, line_index] end rescue StandardError => e puts "Error: #{e}" end matched_lines end |
#get_file_contents(file_path:, branch:) ⇒ String
Fetch contents of file from the repository
104 105 106 107 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 104 def get_file_contents(file_path:, branch:) repository_files = GitlabClient::RepositoryFilesClient.new(token: token, project: project, file_path: file_path, ref: branch || ref) repository_files.file_contents end |
#indentation(line) ⇒ Object
312 313 314 315 316 317 318 319 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 312 def indentation(line) # Indent the same number of spaces as the current line no_of_spaces = line[/\A */].size # If the first char on current line is not a quote, add two more spaces no_of_spaces += /['"]/.match?(line.lstrip[0]) ? 0 : 2 " " * no_of_spaces end |
#invoke! ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 23 def invoke! JSON.parse(File.read(specs_file)).tap do |contents| @report_issue = contents['report_issue'] contents['specs'].each do |spec| processor.create_commit(spec, self) break if processed_commits.keys.count >= batch_limit end processor.create_merge_requests(self) processor.post_process(self) end end |
#issue_client ⇒ GitlabIssueDryClient | GitlabIssueClient
Returns the GitlabIssueClient or GitlabIssueDryClient based on the value of dry_run
370 371 372 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 370 def issue_client @issue_client ||= (dry_run ? GitlabClient::IssuesDryClient : GitlabClient::IssuesClient).new(token: token, project: project) end |
#issue_is_closed?(issue) ⇒ Boolean
Check if issue is closed
223 224 225 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 223 def issue_is_closed?(issue) issue['state'] == 'closed' end |
#issue_scoped_label(issue, scope) ⇒ String
Get scoped label from issue
232 233 234 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 232 def issue_scoped_label(issue, scope) issue['labels'].detect { |label| label.match(/#{scope}::/) } end |
#label_from_feature_category(feature_category) ⇒ String
Infers the group label from the provided feature category
343 344 345 346 347 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 343 def label_from_feature_category(feature_category) labels = labels_inference.infer_labels_from_feature_category(feature_category) group_label = labels.find { |label| label.start_with?('group::') } group_label ? %(/label ~"#{group_label}") : '' end |
#label_from_product_group(product_group) ⇒ String
Infers product group label from the provided product group
333 334 335 336 337 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 333 def label_from_product_group(product_group) label = labels_inference.infer_labels_from_product_group(product_group).to_a.first label ? %(/label ~"#{label}") : '' end |
#labels_inference ⇒ Object
Returns a cached instance of GitlabQuality::TestTooling::LabelsInference
@return [GitlabQuality::TestTooling::LabelsInference]
387 388 389 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 387 def labels_inference @labels_inference ||= GitlabQuality::TestTooling::LabelsInference.new end |
#merge_request_client ⇒ MergeRequestDryClient | MergeRequest
Returns the MergeRequestDryClient or MergeRequest based on the value of dry_run
377 378 379 380 381 382 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 377 def merge_request_client @merge_request_client ||= (dry_run ? GitlabClient::MergeRequestsDryClient : GitlabClient::MergeRequestsClient).new( token: token, project: project ) end |
#post_message_on_slack(message) ⇒ HTTP::Response
Post a message on Slack
294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 294 def () channel = Runtime::Env.slack_alerts_channel = { slack_webhook_url: ENV.fetch('CI_SLACK_WEBHOOK_URL', nil), channel: channel, username: "GitLab Quality Test Tooling", icon_emoji: ':warning:', message: } puts "Posting Slack message to channel: #{channel}" (dry_run ? GitlabQuality::TestTooling::Slack::PostToSlackDry : GitlabQuality::TestTooling::Slack::PostToSlack).new(**).invoke! end |
#post_note_on_issue(note, issue_url) ⇒ Gitlab::ObjectifiedHash
Post note on isse
248 249 250 251 252 253 254 255 256 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 248 def post_note_on_issue(note, issue_url) iid = issue_url&.split('/')&.last # split url segment, last segment of path is the issue id if iid issue_client.create_issue_note(iid: iid, note: note) else Runtime::Logger.info("#{self.class.name}##{__method__} Note was NOT posted on issue: #{issue_url}") nil end end |
#post_note_on_merge_request(note, merge_request_iid) ⇒ Gitlab::ObjectifiedHash
Post a note of merge reqest
263 264 265 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 263 def post_note_on_merge_request(note, merge_request_iid) merge_request_client.create_note(note: note, merge_request_iid: merge_request_iid) end |
#quarantined?(matched_lines, file_contents) ⇒ Bolean
Scans the content from the matched line until ‘do` is found to look for quarantine token
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 141 def quarantined?(matched_lines, file_contents) lines = file_contents.split("\n") matched_lines.each do |matched_line| matched_line_starting_index = matched_line[1] lines[matched_line_starting_index..].each do |line| return true if line.include?('quarantine: {') break if / do$/.match?(line) end end false end |
#single_spec_metrics_link(example_name) ⇒ String
Returns the link to the Grafana dashboard for single spec metrics
353 354 355 356 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 353 def single_spec_metrics_link(example_name) base_url = "https://dashboards.quality.gitlab.net/d/cW0UMgv7k/single-spec-metrics?orgId=1&var-run_type=All&var-name=" base_url + CGI.escape(example_name) end |
#spec_desc_string_within_quotes(line) ⇒ String
Returns any test description string within single or double quotes
362 363 364 365 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 362 def spec_desc_string_within_quotes(line) match = line.match(/(?:it|describe|context|\s)+ ['"]([^'"]*)['"]/) match ? match[1] : nil end |
#update_matched_line(matched_line, content) ⇒ Array<String, Integer>
Update the provided matched_line with content from the block if given
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 161 def update_matched_line(matched_line, content) lines = content.split("\n") begin resulting_line = block_given? ? yield(matched_line[0]) : matched_line[0] lines[matched_line[1]] = resulting_line rescue StandardError => e puts "Error: #{e}" end [lines.join("\n") << "\n", matched_line[1]] end |
#user_id_for_username(username) ⇒ Integer
Fetch id for the given GitLab username/handle
286 287 288 |
# File 'lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb', line 286 def user_id_for_username(username) issue_client.find_user_id(username: username) end |