mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-23 20:29:06 -05:00
mkdocs was installed by the deploy alone, after the merge, and wiki/ was not a validation path: a dead link or a stray heading failed the deploy on main with nothing in front of it. The test job now runs the deploy's site build, and every site input triggers validation.
270 lines
9.5 KiB
YAML
270 lines
9.5 KiB
YAML
name: Validation
|
|
|
|
# The same checks on both roads into main. Work lands here by direct push as
|
|
# often as by pull request, and a test suite reachable only from a PR guards
|
|
# the road nobody takes.
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- "bios/**"
|
|
- "platforms/**"
|
|
- "emulators/**"
|
|
- "schemas/**"
|
|
- "scripts/**"
|
|
- "tests/**"
|
|
# The bootstraps pin install.py's SHA-256 and a test enforces the pin,
|
|
# so editing one without the other has to fail the PR.
|
|
- "install.py"
|
|
- "install.sh"
|
|
- "install.ps1"
|
|
# Every input of the site build, so a page that would fail the deploy
|
|
# fails here first (tests/test_workflow_paths.py).
|
|
- "wiki/**"
|
|
- "docs_assets/**"
|
|
- "provenance/**"
|
|
- "exports/**"
|
|
- "install/**"
|
|
- "database.json"
|
|
- "release.json"
|
|
- "derivable.json"
|
|
- "mkdocs.yml"
|
|
# Spelled out twice because the workflow parser reads no YAML anchor. A test
|
|
# holds the two lists equal.
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- "bios/**"
|
|
- "platforms/**"
|
|
- "emulators/**"
|
|
- "schemas/**"
|
|
- "scripts/**"
|
|
- "tests/**"
|
|
- "install.py"
|
|
- "install.sh"
|
|
- "install.ps1"
|
|
- "wiki/**"
|
|
- "docs_assets/**"
|
|
- "provenance/**"
|
|
- "exports/**"
|
|
- "install/**"
|
|
- "database.json"
|
|
- "release.json"
|
|
- "derivable.json"
|
|
- "mkdocs.yml"
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
|
|
concurrency:
|
|
# A push series collapses to the tip: what has to stay verified is the head
|
|
# of main, not every commit that passed under it.
|
|
group: validate-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
validate-bios:
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'pull_request'
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install dependencies
|
|
run: pip install pyyaml
|
|
|
|
- name: Get changed BIOS files
|
|
id: changed
|
|
env:
|
|
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
run: |
|
|
# NUL-separated and filtered to added/modified/renamed: a deleted
|
|
# file has no bytes left to hash, and a path with a space or a
|
|
# quote must survive the hand-off to validate_pr.py.
|
|
git diff --name-only --diff-filter=AMR -z "$BASE_SHA"..."$HEAD_SHA" \
|
|
-- bios/ > changed_files.zlist
|
|
|
|
# The report has to reach the pull request whatever the outcome, so the
|
|
# exit code is recorded here and acted on after the comment is posted.
|
|
# Swallowing it outright left the job green on a file that failed its
|
|
# hash check.
|
|
- name: Validate BIOS files
|
|
id: validate
|
|
run: |
|
|
if [ -s changed_files.zlist ]; then
|
|
set +e
|
|
xargs -0 python scripts/validate_pr.py --markdown -- \
|
|
< changed_files.zlist > report.md 2>&1
|
|
echo "rc=$?" >> "$GITHUB_OUTPUT"
|
|
set -e
|
|
else
|
|
echo "No BIOS files changed" > report.md
|
|
echo "rc=0" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
cat report.md
|
|
|
|
- name: Post validation report
|
|
if: always()
|
|
run: |
|
|
gh pr comment "${{ github.event.pull_request.number }}" --body-file report.md
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
|
|
- name: Fail when a file did not validate
|
|
if: steps.validate.outputs.rc != '0'
|
|
run: |
|
|
echo "validate_pr.py exited ${{ steps.validate.outputs.rc }}" >&2
|
|
exit 1
|
|
|
|
validate-configs:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install dependencies
|
|
run: pip install pyyaml "jsonschema[format-nongpl]==4.26.0"
|
|
|
|
- name: Validate platform configs and emulator profiles
|
|
run: python scripts/validate_schemas.py --source-only
|
|
|
|
# A profile written from a clone can cite lines that do not hold the value
|
|
# it declares, and schemas and tests pass it. Each profile a change adds is
|
|
# confronted with its upstream, both roads into main. An edited profile is
|
|
# not held to it: the backlog of older refs is reviewed by hand.
|
|
check-new-profiles:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install dependencies
|
|
run: pip install pyyaml
|
|
|
|
- name: Confront added profiles with their upstream
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
BEFORE: ${{ github.event.before }}
|
|
run: |
|
|
# A pull request is checked out as a merge commit whose first
|
|
# parent is the base, while a push names the commit it moved main from.
|
|
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
|
base=HEAD^1
|
|
elif [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
|
|
echo "first push of the branch: no base to diff against"
|
|
exit 0
|
|
else
|
|
base=$BEFORE
|
|
fi
|
|
status=0
|
|
for file in $(git diff --name-only --diff-filter=A "$base" HEAD -- 'emulators/*.yml'); do
|
|
name=$(basename "$file" .yml)
|
|
echo "::group::$name"
|
|
python scripts/profile_sync.py --emulator "$name" --strict || status=1
|
|
echo "::endgroup::"
|
|
done
|
|
exit $status
|
|
|
|
run-tests:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
# install.py stays on Python 3.8: the suite runs it end to end under a
|
|
# real 3.8 interpreter, which import-only and grammar checks miss. The
|
|
# last version listed is the default python.
|
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
with:
|
|
python-version: |
|
|
3.8
|
|
3.12
|
|
|
|
# markdown: the site validation test renders a wiki line to prove the
|
|
# heading guard's premise, and skipped on every run without it. The docs
|
|
# group builds the site as deploy-site.yml does, with the same bounds.
|
|
- name: Install dependencies
|
|
run: pip install pyyaml "jsonschema[format-nongpl]==4.26.0" "markdown==3.10.2" "mkdocs-material>=9.7.5,<10" "pymdown-extensions>=10.14"
|
|
|
|
# The exporter fidelity cases compare what we hand back against the
|
|
# file each platform publishes, so they need those files. They skip
|
|
# without them rather than fail, which is why an unreachable upstream
|
|
# must not stop the run: the rest of the suite still has to report.
|
|
- name: Fetch the platforms' own files
|
|
continue-on-error: true
|
|
run: python scripts/export_native.py --all --fetch --output-dir "$RUNNER_TEMP/native"
|
|
|
|
# A pack built without its data directories exits non-zero: it is not
|
|
# the pack a user gets. Tests that build packs need the same trees a
|
|
# release build has, as deploy-site.yml fetches them.
|
|
- name: Fetch the data directories
|
|
run: python scripts/refresh_data_dirs.py
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Run test suite
|
|
# No test downloads a release asset: 252 MB files fetched into the
|
|
# shared cache filled the runner's disk and changed what later tests
|
|
# resolved. The download tests mock the network and clear it.
|
|
env:
|
|
RETROBIOS_OFFLINE: "1"
|
|
run: python -m unittest discover -s tests -t . -v
|
|
|
|
# deploy-site.yml runs this after the merge, and a dead link or a stray
|
|
# heading failed it there with nothing in front of it. Run whatever the
|
|
# suite returned, so one red step does not hide the other. The release
|
|
# assets are not restored: they change counts, not links or headings.
|
|
- name: Build the site
|
|
if: ${{ !cancelled() }}
|
|
run: |
|
|
python scripts/generate_site.py
|
|
mkdocs build --strict
|
|
python scripts/validate_site.py
|
|
|
|
label-pr:
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'pull_request'
|
|
permissions:
|
|
pull-requests: write
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Auto-label PR
|
|
run: |
|
|
labels=""
|
|
files=$(gh pr diff "${{ github.event.pull_request.number }}" --name-only)
|
|
|
|
if echo "$files" | grep -q '^bios/'; then
|
|
labels="$labels bios"
|
|
for sys in $(echo "$files" | grep '^bios/' | cut -d/ -f2 | sort -u); do
|
|
labels="$labels system:$(echo "$sys" | tr '[:upper:]' '[:lower:]')"
|
|
done
|
|
fi
|
|
if echo "$files" | grep -q '^platforms/'; then
|
|
labels="$labels platform-config"
|
|
fi
|
|
if echo "$files" | grep -q '^scripts/'; then
|
|
labels="$labels automation"
|
|
fi
|
|
|
|
for label in $labels; do
|
|
gh pr edit "${{ github.event.pull_request.number }}" --add-label "$label" 2>/dev/null || true
|
|
done
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|