From 9e8788c0601af918d2c5fee3d21aa61b3e3abe99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Thu, 28 May 2020 16:53:45 +0200 Subject: [PATCH] Add preflight (#490) * Add preflight * fix syntax * move check * get event * print * return event * use path * tt * move to helper * add issue_comment * remove should run * check owner * add more information to the logs * test * add finished * move keys * Update errors * remove repo * fix JQ run * filter --- .github/workflows/checks.yml | 106 +++++++++++++++++----------- .github/workflows/lint.yml | 17 +++-- scripts/changed/category.py | 2 +- scripts/changed/repo.py | 2 +- scripts/check/archived.py | 2 +- scripts/check/brands.py | 2 +- scripts/check/finished.py | 14 ++++ scripts/check/fork.py | 2 +- scripts/check/hacs_manifest.py | 4 +- scripts/check/images.py | 3 +- scripts/check/info.py | 4 +- scripts/check/manifest.py | 16 +++-- scripts/check/owner.py | 21 ++---- scripts/check/repository.py | 6 +- scripts/check/wheels.py | 2 +- scripts/helpers/event.py | 9 +++ scripts/helpers/hacs_manifest.py | 6 +- scripts/helpers/info.py | 4 +- scripts/helpers/integration_path.py | 2 +- 19 files changed, 135 insertions(+), 89 deletions(-) create mode 100644 scripts/check/finished.py create mode 100644 scripts/helpers/event.py diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 2a1536f..2b1b52a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,12 +1,59 @@ name: "Checks" -on: [pull_request] - +on: + pull_request: + types: [opened, synchronize, reopened, unlabeled] + branches: + - master jobs: + preflight: + runs-on: ubuntu-latest + name: Initialize + outputs: + repository: ${{ steps.repository.outputs.repository }} + category: ${{ steps.category.outputs.category }} + steps: + - name: Check out repository + uses: actions/checkout@v2 + + - name: Clone origin + run: git clone --depth 1 https://github.com/hacs/default /tmp/repositories/default + + - name: Clone new addition + run: | + repo=$(python3 -m scripts.changed.repo) + git clone --depth 1 "https://github.com/$repo" /tmp/repositories/addition + + - name: Set category + id: category + run: echo "::set-output name=category::$(python3 -m scripts.changed.category)" + + - name: Set repository + id: repository + run: echo "::set-output name=repository::$(python3 -m scripts.changed.repo)" + + - name: Upload shared artifacts + uses: actions/upload-artifact@master + with: + name: repositories + path: /tmp/repositories + + ready: + runs-on: ubuntu-latest + name: Ready + needs: preflight + steps: + - name: Check out repository + uses: actions/checkout@v2 + + - name: Is finished + run: python3 -m scripts.check.finished + matrix: runs-on: ubuntu-latest name: ${{ matrix.checks.name }} - if: ${{ always() }} + needs: [ready, preflight] strategy: + fail-fast: False matrix: checks: - {check: "archived", name: "Check Archived", deps: True} @@ -23,13 +70,11 @@ jobs: - name: Check out repository uses: actions/checkout@v2 - - name: Clone origin - run: git clone --depth 1 https://github.com/hacs/default /tmp/default - - - name: Clone new addition - run: | - repo=$(python3 -m scripts.changed.repo) - git clone --depth 1 "https://github.com/$repo" /tmp/addition + - name: Download shared artifacts + uses: actions/download-artifact@master + with: + name: repositories + path: /tmp/repositories - name: Install dependencies if needed if: matrix.checks.deps @@ -45,29 +90,22 @@ jobs: hassfest: runs-on: ubuntu-latest name: "Check hassfest" - if: ${{ always() }} + needs: [ready, preflight] + if: needs.preflight.outputs.category == 'integration' steps: - name: Check out repository uses: actions/checkout@v2 - - name: Clone origin - run: git clone --depth 1 https://github.com/hacs/default /tmp/default - - - name: Clone new addition - run: | - repo=$(python3 -m scripts.changed.repo) - git clone --depth 1 "https://github.com/$repo" /tmp/addition - - - name: Set category - id: category - run: echo "::set-output name=category::$(python3 -m scripts.changed.category)" + - name: Download shared artifacts + uses: actions/download-artifact@v1 + with: + name: repositories + path: /tmp/repositories - name: Pull Home Assistant Container - if: steps.category.outputs.category == 'integration' run: docker pull homeassistant/home-assistant:beta - name: Run hassfest - if: steps.category.outputs.category == 'integration' run: | integration=$(python3 -m scripts.helpers.integration_path) domain=$(python3 -m scripts.helpers.domain) @@ -78,26 +116,12 @@ jobs: hacs: runs-on: ubuntu-latest name: "Check HACS" - if: ${{ always() }} + needs: [ready, preflight] steps: - - name: Check out repository - uses: actions/checkout@v2 - - - name: Clone origin - run: git clone --depth 1 https://github.com/hacs/default /tmp/default - - - name: Set category - id: category - run: echo "::set-output name=category::$(python3 -m scripts.changed.category)" - - - name: Set repository - id: repository - run: echo "::set-output name=repository::$(python3 -m scripts.changed.repo)" - - name: HACS validation uses: "hacs/integration/action@master" with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} env: - REPOSITORY: "${{ steps.repository.outputs.repository }}" - CATEGORY: "${{ steps.category.outputs.category }}" \ No newline at end of file + REPOSITORY: ${{needs.preflight.outputs.repository}} + CATEGORY: ${{needs.preflight.outputs.category}} \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d4d82be..b622c38 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,20 +4,25 @@ on: [push, pull_request] jobs: jq: name: JQ - if: ${{ always() }} runs-on: ubuntu-latest - strategy: - matrix: - checks: [appdaemon, blacklist, critical, integration, netdaemon, plugin, python_script, removed, theme] steps: - name: Check out repository uses: actions/checkout@v2 + + - name: Clone origin + run: git clone --depth 1 https://github.com/hacs/default /tmp/repositories/default + + - name: Set category + id: category + run: echo "::set-output name=category::$(python3 -m scripts.changed.category)" + - name: Validate ${{ matrix.checks }} - run: jq --raw-output "." "${{ matrix.checks }}" + if: steps.category.outputs.category != 'Bad data []' + run: + jq --raw-output "." "${{steps.category.outputs.category}}" sorted: name: Sorted - if: ${{ always() }} runs-on: ubuntu-latest steps: - name: Check out repository diff --git a/scripts/changed/category.py b/scripts/changed/category.py index 231703a..df95907 100644 --- a/scripts/changed/category.py +++ b/scripts/changed/category.py @@ -1,7 +1,7 @@ import json -DEFAULT = "/tmp/default" +DEFAULT = "/tmp/repositories/default" CATEGORIES = [ "appdaemon", diff --git a/scripts/changed/repo.py b/scripts/changed/repo.py index 1596f1c..29a228c 100644 --- a/scripts/changed/repo.py +++ b/scripts/changed/repo.py @@ -1,7 +1,7 @@ import json from scripts.changed.category import get_category -DEFAULT = "/tmp/default" +DEFAULT = "/tmp/repositories/default" def get_repo(): diff --git a/scripts/check/archived.py b/scripts/check/archived.py index 623319a..a067171 100644 --- a/scripts/check/archived.py +++ b/scripts/check/archived.py @@ -17,7 +17,7 @@ async def check(): repo = repository.attributes if repo["archived"]: - exit("Repository is archived") + exit("::error::Repository is archived") if __name__ == "__main__": diff --git a/scripts/check/brands.py b/scripts/check/brands.py index 1e93e64..aebcc17 100644 --- a/scripts/check/brands.py +++ b/scripts/check/brands.py @@ -29,7 +29,7 @@ async def check(): files = await repository.get_contents("custom_integrations") if domain not in [x.attributes["name"] for x in files]: exit( - f"{domain} is not added to https://github.com/home-assistant/brands, " + f"::error::{domain} is not added to https://github.com/home-assistant/brands, " + "this is needed to ensure the best possible experience for the user" ) else: diff --git a/scripts/check/finished.py b/scripts/check/finished.py new file mode 100644 index 0000000..3ce96ea --- /dev/null +++ b/scripts/check/finished.py @@ -0,0 +1,14 @@ +from scripts.helpers.event import get_event + + +def check(): + event = get_event() + labels = event.get("pull_request", {}).get("labels", []) + + for label in labels: + if label["name"] == "Not finished": + exit("::error::Pull request is not ready for CI runs") + + +if __name__ == "__main__": + check() diff --git a/scripts/check/fork.py b/scripts/check/fork.py index 6901b7c..6c61762 100644 --- a/scripts/check/fork.py +++ b/scripts/check/fork.py @@ -17,7 +17,7 @@ async def check(): repo = repository.attributes if repo["fork"]: - exit(78) + print("::warning:: {repo} is a fork") if __name__ == "__main__": diff --git a/scripts/check/hacs_manifest.py b/scripts/check/hacs_manifest.py index bf7ba8a..5bfeee6 100644 --- a/scripts/check/hacs_manifest.py +++ b/scripts/check/hacs_manifest.py @@ -9,10 +9,12 @@ def check(): return manifest = get_hacs_manifest() + fail = "::error::Missing required value for key '{key}' in {path}" + path = "hacs.json" issues = [] if manifest.get("name") is None: - issues.append("No name") + issues.append(fail.format(key="name", path=path)) if issues: for issue in issues: diff --git a/scripts/check/images.py b/scripts/check/images.py index e0736b4..fab5d0c 100644 --- a/scripts/check/images.py +++ b/scripts/check/images.py @@ -13,8 +13,7 @@ def check(): print("Has image(s)") return - print("There should be images to show the user what they get.") - exit(1) + exit("::error::There should be images to show the user what they get.") if __name__ == "__main__": diff --git a/scripts/check/info.py b/scripts/check/info.py index 23e302f..54408ea 100644 --- a/scripts/check/info.py +++ b/scripts/check/info.py @@ -6,9 +6,7 @@ def check(): print("Information: https://hacs.xyz/docs/publish/include#check-info") info = get_info() if not info: - print("No information provided.") - exit(1) - + exit("::error::No information provided.") if __name__ == "__main__": check() diff --git a/scripts/check/manifest.py b/scripts/check/manifest.py index 46ef480..38fdbbd 100644 --- a/scripts/check/manifest.py +++ b/scripts/check/manifest.py @@ -1,5 +1,6 @@ from scripts.changed.category import get_category from scripts.helpers.manifest import get_manifest +from scripts.helpers.integration_path import get_integration_path def check(): @@ -8,23 +9,24 @@ def check(): print("Only integrations are checked.") return + fail = "::error::Missing required value for key '{key}' in {path}" + integration = get_integration_path() + path = f"{integration.replace('/tmp/repositories/addition/', '')}/manifest.json" + manifest = get_manifest() issues = [] if manifest.get("domain") is None or manifest.get("domain") == "": - issues.append("No domain") + issues.append(fail.format(key="domain", path=path)) if manifest.get("documentation") is None or manifest.get("documentation") == "": - issues.append("No documentation") + issues.append(fail.format(key="documentation", path=path)) if manifest.get("issue_tracker") is None or manifest.get("issue_tracker") == "": - issues.append("No issue_tracker") + issues.append(fail.format(key="issue_tracker", path=path)) if manifest.get("codeowners") is None: - issues.append("No codeowners") - - if manifest.get("homeassistant"): - issues.append("homeassistant is not valid here") + issues.append(fail.format(key="codeowners", path=path)) if issues: for issue in issues: diff --git a/scripts/check/owner.py b/scripts/check/owner.py index 527eb1f..6de3512 100644 --- a/scripts/check/owner.py +++ b/scripts/check/owner.py @@ -1,30 +1,21 @@ import asyncio -import json import os -from glob import glob -from aiogithubapi import GitHub from scripts.changed.repo import get_repo - -TOKEN = os.getenv("GITHUB_TOKEN") -ACTOR = os.getenv("GITHUB_ACTOR") +from scripts.helpers.event import get_event async def check(): print("Information: https://hacs.xyz/docs/publish/include#check-owner") repo = get_repo() - async with GitHub(TOKEN) as github: - repository = await github.get_repo(repo) - repo = repository.attributes + event = get_event() + actor = event["pull_request"]["user"]["login"] - return - # Currently broken. can not use ACTOR - - if ACTOR == repo["full_name"].split("/")[0]: - print(f"{ACTOR} is the owner of the repository") + if repo.split("/")[0] == event["pull_request"]["user"]["login"]: + print(f"{actor} is the owner of the repository") return - exit(78) + print(f"::warning::{actor} is the owner of the repository") if __name__ == "__main__": diff --git a/scripts/check/repository.py b/scripts/check/repository.py index a2881e6..420e971 100644 --- a/scripts/check/repository.py +++ b/scripts/check/repository.py @@ -18,15 +18,15 @@ async def check(): repo = repository.attributes if not repo["has_issues"]: - issues.append("Issues not enabled.") + issues.append("::error::Issues not enabled.") if not repo["description"]: issues.append( - "No description. (https://hacs.xyz/docs/publish/start#description)" + "::error::No description. (https://hacs.xyz/docs/publish/start#description)" ) if not repo["topics"]: - issues.append("No topics. (https://hacs.xyz/docs/publish/start#topics)") + issues.append("::error::No topics. (https://hacs.xyz/docs/publish/start#topics)") if issues: for issue in issues: diff --git a/scripts/check/wheels.py b/scripts/check/wheels.py index 91940d0..eae47df 100644 --- a/scripts/check/wheels.py +++ b/scripts/check/wheels.py @@ -38,7 +38,7 @@ async def check(): ) return exit( - f"{domain} is not added to https://github.com/home-assistant/wheels-custom-integrations, " + f"::error::{domain} is not added to https://github.com/home-assistant/wheels-custom-integrations, " + "this is needed to ensure the best possible experience for the user" ) diff --git a/scripts/helpers/event.py b/scripts/helpers/event.py new file mode 100644 index 0000000..1fbc009 --- /dev/null +++ b/scripts/helpers/event.py @@ -0,0 +1,9 @@ +import os +import json + + +def get_event(): + with open(os.getenv("GITHUB_EVENT_PATH"), "r") as event_data: + event = json.loads(event_data.read()) + + return event diff --git a/scripts/helpers/hacs_manifest.py b/scripts/helpers/hacs_manifest.py index e7aae4e..b48df4c 100644 --- a/scripts/helpers/hacs_manifest.py +++ b/scripts/helpers/hacs_manifest.py @@ -5,7 +5,7 @@ from glob import glob def get_hacs_manifest(): files = [] - for dir, _, _ in os.walk("/tmp/addition"): + for dir, _, _ in os.walk("/tmp/repositories/addition"): files.extend(glob(os.path.join(dir, "*hacs.json"))) if len(files) != 1: @@ -13,7 +13,9 @@ def get_hacs_manifest(): exit(1) hacs_manifest = files.pop() - print(f"Found HACS manifest at {hacs_manifest.replace('/tmp/addition','')}") + print( + f"Found HACS manifest at {hacs_manifest.replace('/tmp/repositories/addition','')}" + ) with open(hacs_manifest, "r") as mf: hacs_manifest = json.loads(mf.read()) diff --git a/scripts/helpers/info.py b/scripts/helpers/info.py index 76f52d5..a2b9d72 100644 --- a/scripts/helpers/info.py +++ b/scripts/helpers/info.py @@ -14,8 +14,8 @@ def get_info(): content = "" for alternative in ALTERNATIVES[info]: - if os.path.exists(f"/tmp/addition/{alternative}"): + if os.path.exists(f"/tmp/repositories/addition/{alternative}"): print(f"Found info file at /{alternative}") - with open(f"/tmp/addition/{alternative}", "r") as alt: + with open(f"/tmp/repositories/addition/{alternative}", "r") as alt: content = alt.read() return content diff --git a/scripts/helpers/integration_path.py b/scripts/helpers/integration_path.py index 81994fb..edeb8b3 100644 --- a/scripts/helpers/integration_path.py +++ b/scripts/helpers/integration_path.py @@ -5,7 +5,7 @@ from glob import glob def get_integration_path(): files = [] - for dir, _, _ in os.walk("/tmp/addition"): + for dir, _, _ in os.walk("/tmp/repositories/addition"): files.extend(glob(os.path.join(dir, "*manifest.json"))) if len(files) != 1: