Run nightly package version and status checks #100
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
| # SPDX-FileCopyrightText: 2026 The RISE Project | |
| # SPDX-License-Identifier: MIT | |
| name: Run nightly package version and status checks | |
| on: | |
| schedule: | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: | |
| pull_request: | |
| paths: | |
| - '.github/workflows/nightly.yml' | |
| - 'ci_scripts/check_versions.py' | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: write | |
| issues: read | |
| env: | |
| PIP_EXTRA_INDEX_URL: https://pypi.riseproject.dev/simple/ | |
| jobs: | |
| check_versions: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # A branch pushed or a PR opened with GITHUB_TOKEN raises no events, so | |
| # the per-package PRs would sit there with no checks at all. Push and open | |
| # them as the App instead; without its credentials, or on a pull request | |
| # (where a fork or Dependabot has none), the job still runs, it just falls | |
| # back to the checkless GITHUB_TOKEN. | |
| - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| id: app-token | |
| if: ${{ vars.RISEPROJECT_APP_CLIENT_ID != '' && github.event_name != 'pull_request' }} | |
| with: | |
| client-id: ${{ vars.RISEPROJECT_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: false | |
| # Detection only: the working tree stays clean, and every change is | |
| # declared again per package, on that package's own branch, below. | |
| - name: Check versions | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} | |
| SINCE: "2026-09-01" | |
| run: | | |
| uv run --with-requirements ci_scripts/requirements.txt python3 ci_scripts/check_versions.py \ | |
| --summary --report "$RUNNER_TEMP/report.md" --report-dir "$RUNNER_TEMP/reports" | |
| cat "$RUNNER_TEMP/report.md" >> "$GITHUB_STEP_SUMMARY" | |
| # One PR per package, so each build-<pkg>.yml runs on its own PR and a | |
| # single failing build no longer holds back every other upgrade. | |
| - name: Open or update one PR per package | |
| if: github.event_name != 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} | |
| APP_SLUG: ${{ steps.app-token.outputs.app-slug }} | |
| REPORTS: ${{ runner.temp }}/reports | |
| run: | | |
| set -euo pipefail | |
| base=$(git rev-parse HEAD) | |
| ci_scripts/git-identity.sh | |
| # Branch off main and re-declare this package alone, so the PR only | |
| # ever touches its own docs/packages/<pkg>.yaml (plus packages.txt and | |
| # deprecated.txt for a deprecation). | |
| open_pr() { | |
| local package="$1" slug="$2" title="$3" | |
| local branch="github-actions/nightly-upgrade/$slug" pr | |
| git switch --force-create "$branch" "$base" || return 1 | |
| git reset --hard --quiet "$base" || return 1 | |
| uv run --with-requirements ci_scripts/requirements.txt python3 \ | |
| ci_scripts/check_versions.py --declare "$package" || return 1 | |
| if git diff --quiet -- docs/packages ci_scripts/packages.txt ci_scripts/deprecated.txt; then | |
| echo "$package: nothing to declare" | |
| return 0 | |
| fi | |
| git add docs/packages ci_scripts/packages.txt ci_scripts/deprecated.txt || return 1 | |
| git commit -s -m "$title" || return 1 | |
| # Leave an open PR alone when it already declares the same thing: | |
| # a nightly force-push would restart its build for nothing. | |
| if git fetch --quiet origin "$branch" 2>/dev/null && | |
| git diff --quiet FETCH_HEAD HEAD -- "docs/packages/$slug.yaml"; then | |
| echo "$package: $branch is already up to date" | |
| return 0 | |
| fi | |
| git push --force origin "$branch" || return 1 | |
| pr=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$branch" --state open --json url --jq '.[0].url') || return 1 | |
| if [ -n "$pr" ]; then | |
| gh pr edit "$pr" --title "$title" --body-file "$REPORTS/$slug.md" || return 1 | |
| echo "Updated $pr" | |
| else | |
| gh pr create --draft --repo "$GITHUB_REPOSITORY" --base main --head "$branch" \ | |
| --reviewer threexc,luhenry \ | |
| --title "$title" --body-file "$REPORTS/$slug.md" || return 1 | |
| fi | |
| } | |
| if [ "$(jq length "$REPORTS/packages.json")" -eq 0 ]; then | |
| echo "Nothing to declare" | |
| exit 0 | |
| fi | |
| ret=0 | |
| while IFS=$'\t' read -r package slug title; do | |
| if ! open_pr "$package" "$slug" "$title"; then | |
| echo "::warning::$package: could not open or update its PR" | |
| ret=1 | |
| fi | |
| done < <(jq -r '.[] | [.package, .slug, .title] | @tsv' "$REPORTS/packages.json") | |
| git switch --force --detach "$base" | |
| exit $ret | |
| check_deprecated_packages: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install curl and jq | |
| run: sudo apt-get update -qq && sudo apt-get install -qq -y curl jq | |
| - name: Verify riscv64 wheels still published | |
| run: | | |
| ret=0 | |
| while IFS= read -r pkg; do | |
| [[ -z "$pkg" || "$pkg" =~ ^[[:space:]]*# ]] && continue | |
| if ! output=$(curl -sf "https://pypi.org/pypi/${pkg}/json"); then | |
| echo "Failed to fetch $pkg, skipping..." | |
| continue | |
| fi | |
| if ! filenames=$(echo "$output" | jq -r '.urls[].filename'); then | |
| echo "Failed to parse JSON for $pkg, skipping..." | |
| continue | |
| fi | |
| if ! echo "$filenames" | grep -qi riscv; then | |
| echo "$pkg does not distribute riscv64 wheel anymore!" | |
| ret=1 | |
| fi | |
| done < ci_scripts/deprecated.txt | |
| exit $ret | |
| check_installation: | |
| runs-on: ubuntu-24.04-riscv | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install packages inside riscv64 container | |
| working-directory: ci_scripts | |
| run: | | |
| sed -Ei 's/^scipy.*$//' packages.txt | |
| sed -Ei 's/^patchelf.*$//' packages.txt | |
| ./list-packages.sh python-wheels | |
| pip_audit: | |
| runs-on: ubuntu-24.04-riscv | |
| continue-on-error: true | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Run pip-audit | |
| working-directory: ci_scripts | |
| run: ./audit.sh python-wheels | |
| - name: Report vulnerabilities and open issues | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: python3 ci_scripts/audit_report.py ci_scripts/audit-report.json |