Skip to content

Commit

Permalink
Create PR comments with images for changes to G code (#428)
Browse files Browse the repository at this point in the history
Create PR comments with images for changes to G code.
- G Diff continues to be opt-in, by specifying RUN_G_DIFF_CHECK in the respective PR description text.
- G Diff can also be run to compare local commits against remote main by running `run_diff.bat` from the `Source\Tools` working directory.
  • Loading branch information
aepete authored Dec 5, 2023
1 parent 0577695 commit c80a473
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run_pr_commenter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ jobs:
- name: Run G Diff
id: run-diff
run: |
python ${{runner.workspace}}/measurementlink-labview/Source/Tools/run_diff.py --token ${{secrets.GITHUB_TOKEN}} --pull-req ${{github.event.pull_request.number}}
python ${{runner.workspace}}/measurementlink-labview/Source/Tools/run_diff.py --token ${{secrets.GITHUB_TOKEN}} --pull-req ${{github.event.pull_request.number}} --commit-id ${{github.event.pull_request.head.sha}}
4 changes: 4 additions & 0 deletions Source/Tools/Graphical Diff.lvlib
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
<Property Name="NI.Lib.SourceVersion" Type="Int">536903680</Property>
<Property Name="NI.Lib.Version" Type="Str">1.0.0.0</Property>
<Item Name="subVIs" Type="Folder">
<Item Name="Bucket Similar Diff Images.vi" Type="VI" URL="../subVIs/Bucket Similar Diff Images.vi"/>
<Item Name="Change Type.ctl" Type="VI" URL="../subVIs/Change Type.ctl"/>
<Item Name="Collate Diff Images.vi" Type="VI" URL="../subVIs/Collate Diff Images.vi"/>
<Item Name="Merge Diff Images.vi" Type="VI" URL="../subVIs/Merge Diff Images.vi"/>
<Item Name="Parse Diff Report to Text.vi" Type="VI" URL="../subVIs/Parse Diff Report to Text.vi"/>
<Item Name="Process Diff Images.vi" Type="VI" URL="../subVIs/Process Diff Images.vi"/>
</Item>
<Item Name="run_diff.vi" Type="VI" URL="../run_diff.vi"/>
</Library>
70 changes: 67 additions & 3 deletions Source/Tools/run_diff.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import base64
import click
import json
import logging
Expand All @@ -8,6 +9,7 @@
import subprocess
import sys
import tempfile
import uuid
from pathlib import Path

_logger = logging.getLogger(__name__)
Expand All @@ -18,7 +20,7 @@
_logger.addHandler(handler)


def run_full_diff(pr_number, token):
def run_full_diff(pr_number, token, commit_id):
tools_directory = Path(os.path.dirname(__file__))
source_directory = tools_directory.parent
repo_root_directory = source_directory.parent
Expand Down Expand Up @@ -51,7 +53,15 @@ def run_full_diff(pr_number, token):
# Substitution using &nbsp preserves indentation
diff_summary = re.sub(" ", "&nbsp;&nbsp;", diff_summary)
if pr_number is not None and token is not None:
# Add PR-scoped comment for the summary
post_github_pr_text_comment(diff_summary, pr_number, token)

# Add file-scoped comments for provided imagery
# The string formatted by LV is: Diff images generated for `%s`.<!--%s-->
matches = re.findall(r'Diff images generated for `(.*)`\.<!--(.*)-->', diff_summary)
for file_id, image_dir in matches:
_logger.debug(f"Diff images for `{file_id}` retrieved from path `{image_dir}`")
post_github_pr_file_scoped_comment_with_images(file_id, image_dir, pr_number, token, commit_id)
else:
_logger.debug(diff_summary)
return
Expand Down Expand Up @@ -118,6 +128,10 @@ def create_github_request_header(token):
return {"Authorization": "token %s" % token.strip()}


def create_github_request_header_png_upload(token):
return {"Authorization": "token %s" % token.strip(), "Content-Type": "image/png"}


def post_github_pr_text_comment(text, pr_number, token):
# Using "issues" in this url allows for providing a pr-scoped comment.
# If using "pulls" instead, subschema information (e.g. file or line) is required in the data.
Expand All @@ -135,6 +149,51 @@ def post_github_pr_text_comment(text, pr_number, token):
return response.status_code


def post_github_pr_file_scoped_comment_with_images(file_id, directory_with_images, pr_number, token, commit_id):
# First, upload all the images. Since PRs do not support assets, this code uploads images
# as assets within an obsolete release, an apparent best-available option at time of writing.
upload_header = create_github_request_header_png_upload(token)
images_to_upload = [f for f in os.listdir(directory_with_images) if f.endswith(".png")]
uploaded_image_urls = []
text = f"Diff Image Data for {file_id} as follows<br><br>"
for image_filename in images_to_upload:
_logger.debug(f" - Posting image `{image_filename}`...")
image_local_path = os.path.join(directory_with_images, image_filename)
raw_binary_data = bytearray()
with open(image_local_path, "rb") as image_binary_data:
raw_binary_data = image_binary_data.read()

random_guid_filename = f"{str(uuid.uuid4())}.png"
upload_url = f"https://uploads.github.com/repos/ni/measurementlink-labview/releases/90459463/assets?name={random_guid_filename}"

_logger.debug(f" - Posting image to {upload_url}")

response = requests.post(upload_url, data=raw_binary_data, headers=upload_header)
if response.ok:
_logger.debug(f"Response code: {response.status_code}")
if "before" in image_filename:
text = text + "<i>Before</i>:<br>"
else:
text = text + "<i>After</i>:<br>"
text = text + f"<img title=\"{image_filename}\" src=\"https://github.com/ni/measurementlink-labview/releases/download/v0.12.1/{random_guid_filename}\"/><br>"
else:
_logger.error(f"Bad response. url:{upload_url}, code:{response.status_code}, text:{response.text}")
text = text + f"Failed to upload image `{image_filename}` as `{random_guid_filename}`<br><br>"

url = f"https://api.github.com/repos/ni/measurementlink-labview/pulls/{pr_number}/comments"
data = json.dumps({"body": text, "subject_type": "file", "path": file_id, "commit_id": commit_id})
header = create_github_request_header(token)

_logger.debug(f"Posting pr text comment to {url} (file {file_id})")
response = requests.post(url, data=data, headers=header)
if response.ok:
_logger.debug(f"Response code: {response.status_code}")
else:
_logger.error(f"Bad response. url:{url}, code:{response.status_code}, text:{response.text}")

return response.status_code


def get_github_pr_changed_files(pr_number, token):
url = f"https://api.github.com/repos/ni/measurementlink-labview/pulls/{pr_number}/files"
header = create_github_request_header(token)
Expand Down Expand Up @@ -163,13 +222,18 @@ def get_github_pr_changed_files(pr_number, token):
"--token",
help="Github Access token needed to perform write operations",
)
def main(pull_req, token):
@click.option(
"-c",
"--commit-id",
help="Commit SHA being diffed against",
)
def main(pull_req, token, commit_id):
pr_number = pull_req

if pr_number is not None and token is not None:
_logger.debug(f"Running for pull request #{pr_number} with provided token.")

run_full_diff(pr_number, token)
run_full_diff(pr_number, token, commit_id)

sys.exit(0)

Expand Down
Binary file modified Source/Tools/run_diff.vi
Binary file not shown.
Binary file added Source/Tools/subVIs/Bucket Similar Diff Images.vi
Binary file not shown.
Binary file added Source/Tools/subVIs/Collate Diff Images.vi
Binary file not shown.
Binary file added Source/Tools/subVIs/Merge Diff Images.vi
Binary file not shown.
Binary file modified Source/Tools/subVIs/Parse Diff Report to Text.vi
Binary file not shown.
Binary file added Source/Tools/subVIs/Process Diff Images.vi
Binary file not shown.

0 comments on commit c80a473

Please sign in to comment.