From efcd0f93ed277bcafd2c541e60a71ba011f1c279 Mon Sep 17 00:00:00 2001 From: Nicholas Tindle Date: Thu, 22 Aug 2024 05:06:15 -0700 Subject: [PATCH] ci(all): take two on the global status checker (#7849) * ci(all): fundamentally change how we do this * Update workflow-checker.yml * ci: dupe and move file in attempt to figure out why its not accessible * Update workflow-checker.yml * fix: sleep before checking, move files, improve code * Update workflow-checker.yml * Update check_actions_status.py * Update check_actions_status.py * Update workflow-checker.yml * Update workflow-checker.yml * ci: remove debug, add more * Update check_actions_status.py * Update check_actions_status.py * Update check_actions_status.py * Revert "Update check_actions_status.py" This reverts commit 36134527af385399c610b9fee27b2d9d2106d94d. * Revert "Update check_actions_status.py" This reverts commit 828aabf532c550dc67f3005e719c2ca7ff3dde78. * Update check_actions_status.py * Update check_actions_status.py * Update check_actions_status.py * Update check_actions_status.py --- .../workflows/scripts/check_actions_status.py | 55 --------- .github/workflows/workflow-checker.yml | 80 ++++++------- check_actions_status.py | 109 ++++++++++++++++++ 3 files changed, 145 insertions(+), 99 deletions(-) delete mode 100644 .github/workflows/scripts/check_actions_status.py create mode 100644 check_actions_status.py diff --git a/.github/workflows/scripts/check_actions_status.py b/.github/workflows/scripts/check_actions_status.py deleted file mode 100644 index ad6a1f4b31..0000000000 --- a/.github/workflows/scripts/check_actions_status.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -import requests -import sys - -# GitHub API endpoint -api_url = os.environ["GITHUB_API_URL"] -repo = os.environ["GITHUB_REPOSITORY"] -sha = os.environ["GITHUB_SHA"] - -# GitHub token for authentication -github_token = os.environ["GITHUB_TOKEN"] - -# API endpoint for check runs for the specific SHA -endpoint = f"{api_url}/repos/{repo}/commits/{sha}/check-runs" - -# Set up headers for authentication -headers = { - "Authorization": f"token {github_token}", - "Accept": "application/vnd.github.v3+json" -} - -# Make the API request -response = requests.get(endpoint, headers=headers) - -if response.status_code != 200: - print(f"Error: Unable to fetch check runs data. Status code: {response.status_code}") - sys.exit(1) - -check_runs = response.json()["check_runs"] - -# Flag to track if all other check runs have passed -all_others_passed = True - -# Current run id -current_run_id = os.environ["GITHUB_RUN_ID"] - -for run in check_runs: - if str(run["id"]) != current_run_id: - status = run["status"] - conclusion = run["conclusion"] - - if status == "completed": - if conclusion not in ["success", "skipped", "neutral"]: - all_others_passed = False - print(f"Check run {run['name']} (ID: {run['id']}) has conclusion: {conclusion}") - else: - print(f"Check run {run['name']} (ID: {run['id']}) is still {status}.") - all_others_passed = False - -if all_others_passed: - print("All other completed check runs have passed. This check passes.") - sys.exit(0) -else: - print("Some check runs have failed or have not completed. This check fails.") - sys.exit(1) \ No newline at end of file diff --git a/.github/workflows/workflow-checker.yml b/.github/workflows/workflow-checker.yml index 2f5d55bdef..3d541a0798 100644 --- a/.github/workflows/workflow-checker.yml +++ b/.github/workflows/workflow-checker.yml @@ -1,51 +1,43 @@ name: PR Status Checker on: - workflow_run: - workflows: ["*"] - types: - - completed + pull_request: + types: [opened, synchronize, reopened] jobs: status-check: - name: Check Actions Status + name: Check PR Status runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.10" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install requests - - name: Debug Information - run: | - echo "Event name: ${{ github.event_name }}" - echo "Workflow: ${{ github.workflow }}" - echo "Action: ${{ github.action }}" - echo "Actor: ${{ github.actor }}" - echo "Repository: ${{ github.repository }}" - echo "Ref: ${{ github.ref }}" - echo "Head ref: ${{ github.head_ref }}" - echo "Base ref: ${{ github.base_ref }}" - echo "Event payload:" - cat $GITHUB_EVENT_PATH - - name: Debug File Structure - run: | - echo "Current directory:" - pwd - echo "Directory contents:" - ls -R - echo "GitHub workspace:" - echo $GITHUB_WORKSPACE - echo "GitHub workspace contents:" - ls -R $GITHUB_WORKSPACE - - name: Check Actions Status - run: | - echo "Current directory before running Python script:" - pwd - echo "Attempting to run Python script:" - python .github/scripts/check_actions_status.py - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # - name: Wait some time for all actions to start + # run: sleep 30 + - uses: actions/checkout@v4 + # with: + # fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install requests + - name: Debug Information + run: | + echo "Event name: ${{ github.event_name }}" + echo "Workflow: ${{ github.workflow }}" + echo "Action: ${{ github.action }}" + echo "Actor: ${{ github.actor }}" + echo "Repository: ${{ github.repository }}" + echo "Ref: ${{ github.ref }}" + echo "Head ref: ${{ github.head_ref }}" + echo "Base ref: ${{ github.base_ref }}" + echo "Event payload:" + cat $GITHUB_EVENT_PATH + - name: Check PR Status + run: | + echo "Current directory before running Python script:" + pwd + echo "Attempting to run Python script:" + python check_actions_status.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/check_actions_status.py b/check_actions_status.py new file mode 100644 index 0000000000..373d1c9414 --- /dev/null +++ b/check_actions_status.py @@ -0,0 +1,109 @@ +import json +import os +import requests +import sys +import time +from typing import Dict, List, Tuple + + +def get_environment_variables() -> Tuple[str, str, str, str, str]: + """Retrieve and return necessary environment variables.""" + try: + with open(os.environ["GITHUB_EVENT_PATH"]) as f: + event = json.load(f) + + sha = event["pull_request"]["head"]["sha"] + + return ( + os.environ["GITHUB_API_URL"], + os.environ["GITHUB_REPOSITORY"], + sha, + os.environ["GITHUB_TOKEN"], + os.environ["GITHUB_RUN_ID"], + ) + except KeyError as e: + print(f"Error: Missing required environment variable or event data: {e}") + sys.exit(1) + + +def make_api_request(url: str, headers: Dict[str, str]) -> Dict: + """Make an API request and return the JSON response.""" + try: + print("Making API request to:", url) + response = requests.get(url, headers=headers, timeout=10) + response.raise_for_status() + return response.json() + except requests.RequestException as e: + print(f"Error: API request failed. {e}") + sys.exit(1) + + +def process_check_runs(check_runs: List[Dict]) -> Tuple[bool, bool]: + """Process check runs and return their status.""" + runs_in_progress = False + all_others_passed = True + + for run in check_runs: + if str(run["name"]) != "Check PR Status": + status = run["status"] + conclusion = run["conclusion"] + + if status == "completed": + if conclusion not in ["success", "skipped", "neutral"]: + all_others_passed = False + print( + f"Check run {run['name']} (ID: {run['id']}) has conclusion: {conclusion}" + ) + else: + runs_in_progress = True + print(f"Check run {run['name']} (ID: {run['id']}) is still {status}.") + all_others_passed = False + else: + print( + f"Skipping check run {run['name']} (ID: {run['id']}) as it is the current run." + ) + + return runs_in_progress, all_others_passed + + +def main(): + api_url, repo, sha, github_token, current_run_id = get_environment_variables() + + endpoint = f"{api_url}/repos/{repo}/commits/{sha}/check-runs" + headers = { + "Accept": "application/vnd.github.v3+json", + } + if github_token: + headers["Authorization"] = f"token {github_token}" + + print(f"Current run ID: {current_run_id}") + + while True: + data = make_api_request(endpoint, headers) + + check_runs = data["check_runs"] + + print("Processing check runs...") + + print(check_runs) + + runs_in_progress, all_others_passed = process_check_runs(check_runs) + + if not runs_in_progress: + break + + print( + "Some check runs are still in progress. Waiting 3 minutes before checking again..." + ) + time.sleep(180) + + if all_others_passed: + print("All other completed check runs have passed. This check passes.") + sys.exit(0) + else: + print("Some check runs have failed or have not completed. This check fails.") + sys.exit(1) + + +if __name__ == "__main__": + main()