Skip to content

ci: open the nightly PRs as the riseproject-dev github app #94

ci: open the nightly PRs as the riseproject-dev github app

ci: open the nightly PRs as the riseproject-dev github app #94

Workflow file for this run

# 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@fee1f7d63c2ff003460e3d139729b119787bc349 # v2.2.2
id: app-token
if: ${{ vars.RISEPROJECT_APP_ID != '' && github.event_name != 'pull_request' }}
with:
app-id: ${{ vars.RISEPROJECT_APP_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,justeph,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