Print service update reports in job logs #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Service Update Report Dry Run | ||
|
Check failure on line 1 in .github/workflows/service-update-report-dry-run.yml
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| repo_filter: | ||
| description: Optional regex to limit which README-listed repos are inspected | ||
| required: false | ||
| default: "" | ||
| type: string | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| discover-repos: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| repos: ${{ steps.discover.outputs.repos }} | ||
| repo_count: ${{ steps.discover.outputs.repo_count }} | ||
| steps: | ||
| - name: Check Out Repository | ||
| uses: actions/checkout@v4 | ||
| - name: Build Service Matrix | ||
| id: discover | ||
| env: | ||
| OWNER: wodby | ||
| REPO_FILTER: ${{ inputs.repo_filter }} | ||
| run: | | ||
| python - <<'PY' | ||
| import json | ||
| import os | ||
| import re | ||
| from pathlib import Path | ||
| owner = os.environ["OWNER"] | ||
| repo_filter = os.environ.get("REPO_FILTER", "") | ||
| readme_text = Path("README.md").read_text() | ||
| pattern = re.compile(rf"https://github.com/{re.escape(owner)}/([^)]+)") | ||
| repos = sorted(set(pattern.findall(readme_text))) | ||
| if repo_filter: | ||
| matcher = re.compile(repo_filter) | ||
| repos = [repo for repo in repos if matcher.search(repo)] | ||
| if not repos: | ||
| raise SystemExit(f"No README-listed repos matched repo_filter={repo_filter!r}") | ||
| repos_json = json.dumps(repos, separators=(",", ":")) | ||
| with Path(os.environ["GITHUB_OUTPUT"]).open("a") as fh: | ||
| fh.write(f"repo_count={len(repos)}\n") | ||
| fh.write(f"repos={repos_json}\n") | ||
| print(f"Selected {len(repos)} repo(s):") | ||
| for repo in repos: | ||
| print(f"- {repo}") | ||
| PY | ||
| - name: Publish Discovery Summary | ||
| env: | ||
| REPOS_JSON: ${{ steps.discover.outputs.repos }} | ||
| REPO_COUNT: ${{ steps.discover.outputs.repo_count }} | ||
| run: | | ||
| python - <<'PY' >> "$GITHUB_STEP_SUMMARY" | ||
| import json | ||
| import os | ||
| repos = json.loads(os.environ["REPOS_JSON"]) | ||
| print("## Dry Run Scope") | ||
| print("") | ||
| print(f"- Selected repos: {os.environ['REPO_COUNT']}") | ||
| for repo in repos: | ||
| print(f" - `{repo}`") | ||
| PY | ||
| dry-run-report: | ||
| name: Dry Run Report / ${{ matrix.repo }} | ||
| needs: discover-repos | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 30 | ||
| env: | ||
| SERVICE_REPO: ${{ matrix.repo }} | ||
| REPORT_DIR: ${{ runner.temp }}/service-update-report/${{ matrix.repo }} | ||
| strategy: | ||
| fail-fast: false | ||
| max-parallel: 6 | ||
| matrix: | ||
| repo: ${{ fromJSON(needs.discover-repos.outputs.repos) }} | ||
| steps: | ||
| - name: Check Out Repository | ||
| uses: actions/checkout@v4 | ||
| - name: Set Up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.11" | ||
| - name: Install Dependencies | ||
| run: python -m pip install --upgrade pip packaging pyyaml requests | ||
| - name: Generate Dry-Run Report | ||
| env: | ||
| WODBOT_GITHUB_PAT: ${{ secrets.WODBOT_GITHUB_PAT }} | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
| WODBY_GITHUB_TOKEN: ${{ secrets.WODBY_GITHUB_TOKEN }} | ||
| run: | | ||
| python scripts/service_update_report.py \ | ||
| --readme README.md \ | ||
| --owner wodby \ | ||
| --repo-filter "^${SERVICE_REPO}$" \ | ||
| --output-dir "${REPORT_DIR}" | ||
| - name: Print Full Report | ||
| run: | | ||
| python - <<'PY' | ||
| import os | ||
| from pathlib import Path | ||
| report_path = Path(os.environ["REPORT_DIR"]) / "service-update-report.md" | ||
| print(report_path.read_text()) | ||
| PY | ||
| - name: Publish Step Summary | ||
| run: | | ||
| python - <<'PY' >> "$GITHUB_STEP_SUMMARY" | ||
| import json | ||
| import os | ||
| from pathlib import Path | ||
| repo = os.environ["SERVICE_REPO"] | ||
| report_dir = Path(os.environ["REPORT_DIR"]) | ||
| report = json.loads((report_dir / "service-update-report.json").read_text()) | ||
| details = next((item for item in report["per_repo"] if item["repo"] == repo), None) | ||
| print(f"## Dry Run Result: `{repo}`") | ||
| print("") | ||
| print("- No service repos were modified by this workflow.") | ||
| print("- Scope: single service repo") | ||
| print("- Full report: printed in the `Print Full Report` step log") | ||
| print("") | ||
| if repo in report["missing_service_yml"]: | ||
| print("- Status: missing `service.yml`") | ||
| elif details and details["updates"]: | ||
| print("- Status: update candidate") | ||
| elif details and (details["warnings"] or not details["has_image"] or not details["has_helm"] or not details["has_options"]): | ||
| print("- Status: special case") | ||
| else: | ||
| print("- Status: no changes") | ||
| print("") | ||
| if details and details["updates"]: | ||
| print("### Updates Needed") | ||
| for message in details["updates"]: | ||
| print(f"- {message}") | ||
| print("") | ||
| if details and details["current"]: | ||
| print("### Current State") | ||
| for message in details["current"]: | ||
| print(f"- {message}") | ||
| print("") | ||
| if details and details["warnings"]: | ||
| print("### Warnings") | ||
| for message in details["warnings"]: | ||
| print(f"- {message}") | ||
| print("") | ||
| if repo in report["missing_service_yml"]: | ||
| print("### Missing or Unreadable `service.yml`") | ||
| print(f"- `{repo}`") | ||
| print("") | ||
| if details and (not details["has_image"] or not details["has_helm"] or not details["has_options"]): | ||
| print("### Missing Comparison Inputs") | ||
| if not details["has_image"]: | ||
| print("- No `containers[0].image`") | ||
| if not details["has_helm"]: | ||
| print("- No `helm`") | ||
| if not details["has_options"]: | ||
| print("- No `options`") | ||
| print("") | ||
| if not report["updates"] and not (details and details["warnings"]) and repo not in report["missing_service_yml"]: | ||
| print("No update candidates were found.") | ||
| print("") | ||
| print("The full markdown report is printed in the job log above.") | ||
| PY | ||