| # issue_on_error_post.py |
| # Requires python 3.6+ and GitHub CLI in the environment. |
| # |
| # Creates or updates an issue on action failure related to a workflow. |
| # |
| # Looks though REPO for open issues with FLAG_LABEL. If none, |
| # creates a new issue. If there is an open issue with FLAG_LABEL, |
| # looks for WORKFLOW in body. If none, creates an issue. If an |
| # issue for WORKFLOW exists, makes adds a comment. |
| # |
| # Requires the environment provide the variables in the block below. |
| # TOKEN must have access to update issues. |
| # |
| # If called with an optional PR_NUMBER and PR_LINK the issue will |
| # include a link to the PR. |
| |
| |
| from datetime import datetime |
| import os |
| import json |
| import subprocess |
| |
| REPO_NAME = os.environ['REPO'] |
| WORKFLOW = os.environ['WORKFLOW'] |
| FLAG_LABEL = os.environ['FLAG_LABEL'] |
| RUN_NUMBER = os.environ['RUN_NUMBER'] |
| RUN_ID = os.environ['RUN_ID'] |
| # optional variables |
| PR_NUMBER = os.getenv('PR_NUMBER') |
| PR_LINK = os.getenv('PR_LINK') |
| |
| def get_tagged_issues(flag_label, workflow): |
| issues = subprocess.check_output(["gh", "issue", "list", |
| "--state", "open", |
| "--label", flag_label, |
| "--json", "title,number,body"], |
| encoding="utf-8") |
| issues = json.loads(issues) |
| tagged_issues =[] |
| for issue in issues: |
| if workflow in issue["body"]: |
| tagged_issues.append(issue) |
| return(tagged_issues) |
| |
| def create_issue(flag_label, workflow, run_number, run_id, repo_name, pr_number, pr_link): |
| |
| run_link = f"http://github.com/{repo_name}/actions/runs/{run_id}" |
| body_string = "" |
| title_string = f"{workflow} CI Run Failed" |
| if pr_number: |
| body_string = f"PR {pr_number} ({pr_link}) had a CI failure: \n" |
| title_string = f"PR #{pr_number} CI Run Failed" |
| body_string += f"{workflow} [run number {run_number}]({run_link}) failed. \n\n" |
| body_string += "This issue has been automatically generated for " |
| body_string += "notification purposes." |
| |
| new_issue = subprocess.check_output(["gh", "issue", "create", |
| "--title", title_string, |
| "--body", body_string, |
| "--label", flag_label], |
| encoding="utf-8") |
| return(new_issue) |
| |
| |
| def add_comment(issue_number, run_number, run_id, repo_name): |
| dt_string = datetime.now().strftime("%d/%m/%Y %H:%M:%S") |
| run_link = f"http://github.com/{repo_name}/actions/runs/{run_id}" |
| msg_string = f"Error reoccurred: {dt_string}\n" |
| msg_string += f"[Run number: {run_number}]({run_link})\n" |
| subprocess.run(["gh", "issue", "comment", issue_number, |
| "--body", msg_string]) |
| return() |
| |
| if __name__ == "__main__": |
| tagged_issues = get_tagged_issues(FLAG_LABEL, WORKFLOW) |
| |
| # The logic catches the case where an issue exists for the workflow |
| # but we are testing against a PR and want a created issue to link to the PR. |
| # Otherwise, we just add a comment to the existing issue. |
| if not tagged_issues: |
| create_issue(FLAG_LABEL, WORKFLOW, RUN_NUMBER, RUN_ID, REPO_NAME, PR_NUMBER, PR_LINK) |
| else: |
| for issue in tagged_issues: |
| if PR_NUMBER: |
| if PR_LINK in issue["body"]: |
| add_comment(str(issue["number"]), RUN_NUMBER, RUN_ID, REPO_NAME) |
| else: |
| create_issue(FLAG_LABEL, WORKFLOW, RUN_NUMBER, RUN_ID, REPO_NAME, |
| PR_NUMBER, PR_LINK) |
| else: |
| add_comment(str(issue["number"]), RUN_NUMBER, RUN_ID, REPO_NAME) |
| for issue in tagged_issues: |
| print(issue["number"]) |
| |
| |
| |
| |
| |