post_incremental_coverage_in_pr.rb 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. # Copyright 2021 Google LLC
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # USAGE: git diff -U0 [base_commit] HEAD | get_diff_lines.sh
  15. #
  16. # This will generate a JSON output of changed files and their newly added
  17. # lines.
  18. require 'octokit'
  19. require 'json'
  20. COMMENT_HEADER = "### Incremental code coverage report"
  21. REMOVE_PATTERN = /### Incremental code coverage report/
  22. REPO = ENV['GITHUB_REPOSITORY']
  23. GITHUB_WORKFLOW_URL = "https://github.com/#{REPO}/actions/runs/#{ENV['GITHUB_RUN_ID']}"
  24. UNCOVERED_LINE_FILE = ENV["UNCOVERED_LINE_FILE"]
  25. TESTING_COMMIT = ENV["TESTING_COMMIT"]
  26. PULL_REQUEST = ENV["PULL_REQUEST"].to_i
  27. client = Octokit::Client.new(access_token: ENV["INPUT_ACCESS_TOKEN"])
  28. uncovered_files = JSON.parse(File.read(UNCOVERED_LINE_FILE))
  29. # Clean comments matching REMOVE_PATTERN.
  30. def clean_coverage_comments(client)
  31. comment_page = 0
  32. loop do
  33. comment_page += 1
  34. cur_page_comment = client.pull_request_comments(REPO, PULL_REQUEST, { :per_page =>100, :page => comment_page })
  35. if cur_page_comment.length == 0
  36. break
  37. end
  38. for cmt in cur_page_comment do
  39. # Remove comments when the comment body meets the REMOVE_PATTERN.
  40. if cmt.body =~ REMOVE_PATTERN
  41. client.delete_pull_request_comment(REPO,cmt.id)
  42. end
  43. end
  44. end
  45. end
  46. def generate_comment(comment_header, xcresult_file)
  47. body = "Tests for New code lines are not detected in [#{xcresult_file}](#{GITHUB_WORKFLOW_URL}), please add tests on highlighted lines."
  48. return "#{comment_header} \n #{body}"
  49. end
  50. def add_coverage_comments(client, uncovered_files)
  51. for changed_file in uncovered_files do
  52. coverage_line = changed_file['coverage']
  53. xcresult_file = changed_file['xcresultBundle'].split('/').last
  54. start_line = -1
  55. coverage_line.each_with_index do |line, idx|
  56. # Init start_line to the first uncovered line of a file.
  57. if start_line == -1
  58. start_line = line
  59. end
  60. if idx < coverage_line.length() && line + 1 == coverage_line[idx+1]
  61. next
  62. else
  63. comment = generate_comment(COMMENT_HEADER, xcresult_file)
  64. if start_line == line
  65. # One line code comment will have nil in start_line and override
  66. # the position param, which is 0 here. The position param is a
  67. # relative number in the `git diff`, instead of a absolute line
  68. # index.
  69. client.create_pull_request_comment(REPO,PULL_REQUEST, comment, TESTING_COMMIT,changed_file['fileName'], 0, {:side=>"RIGHT", :line=>line})
  70. else
  71. # multiple-line code block comment needs start_line and line options,
  72. # which will override the position param.
  73. client.create_pull_request_comment(REPO,PULL_REQUEST, comment, TESTING_COMMIT,changed_file['fileName'],0, {:side=>"RIGHT", :start_line=>start_line, :line=>line})
  74. end
  75. start_line = coverage_line[idx+1]
  76. end
  77. end
  78. end
  79. end
  80. clean_coverage_comments(client)
  81. add_coverage_comments(client, uncovered_files)