mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-11 05:53:23 -05:00
A CI checkout omits every file over 50 MB, so verify and generate_pack resolve those database entries against a disk that does not hold them and report them missing. The generated README then stops matching the committed one for a reason that has nothing to do with staleness. restore_large_files.py writes them back from the release cache, matched by SHA1 rather than by name, and only where the path is gitignored and absent. The site workflow runs it, and refreshes the data directories, before generating.
151 lines
5.4 KiB
YAML
151 lines
5.4 KiB
YAML
name: Build & Release
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths: ["bios/**", "platforms/**"]
|
|
workflow_dispatch:
|
|
inputs:
|
|
force_release:
|
|
description: "Force release even if rate limited"
|
|
type: boolean
|
|
default: false
|
|
|
|
permissions: {}
|
|
|
|
concurrency:
|
|
group: build
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
release:
|
|
if: false # disabled until pack generation is validated in production
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
|
|
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- run: pip install pyyaml
|
|
|
|
- name: Run tests
|
|
run: python -m unittest tests.test_e2e -v
|
|
|
|
- name: Rate limit
|
|
if: github.event.inputs.force_release != 'true'
|
|
id: rate
|
|
run: |
|
|
LAST=$(gh release list --repo "${{ github.repository }}" --json createdAt -q '.[0].createdAt' 2>/dev/null || echo "")
|
|
if [ -n "$LAST" ] && [ "$LAST" != "null" ]; then
|
|
LAST_TS=$(date -d "$LAST" +%s 2>/dev/null || echo 0)
|
|
DIFF=$(( ($(date +%s) - LAST_TS) / 86400 ))
|
|
if [ "$DIFF" -lt 7 ]; then
|
|
echo "Skipping: last release ${DIFF} days ago"
|
|
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
fi
|
|
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Restore large files from release
|
|
if: steps.rate.outputs.skip != 'true'
|
|
run: |
|
|
mkdir -p .cache/large
|
|
gh release download large-files -D .cache/large/ 2>/dev/null || true
|
|
python scripts/restore_large_files.py
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Refresh data directories
|
|
if: steps.rate.outputs.skip != 'true'
|
|
run: python scripts/refresh_data_dirs.py
|
|
continue-on-error: true
|
|
|
|
- name: Build packs
|
|
if: steps.rate.outputs.skip != 'true'
|
|
run: python scripts/generate_pack.py --all --output-dir dist/
|
|
|
|
- name: Split oversized packs
|
|
if: steps.rate.outputs.skip != 'true'
|
|
run: |
|
|
# GitHub releases cap assets at 2 GB. Use the .zip.001 volume
|
|
# convention: 7-Zip and PeaZip open the .001 part directly,
|
|
# unlike .partNN names which they reject as corrupt archives.
|
|
for f in dist/*.zip; do
|
|
size=$(stat -c%s "$f")
|
|
if [ "$size" -gt 2000000000 ]; then
|
|
split --bytes=1900M --numeric-suffixes=1 --suffix-length=3 "$f" "$f."
|
|
rm "$f"
|
|
echo "Split $(basename "$f") into $(ls "$f".* | wc -l) parts"
|
|
fi
|
|
done
|
|
|
|
- name: Release
|
|
if: steps.rate.outputs.skip != 'true'
|
|
run: |
|
|
DATE=$(date +%Y.%m.%d)
|
|
EXISTING=$(gh release list --repo "${{ github.repository }}" --json tagName -q ".[].tagName" | grep -c "^v${DATE}" || true)
|
|
TAG="v${DATE}"
|
|
[ "$EXISTING" -gt 0 ] && TAG="v${DATE}.$((EXISTING+1))"
|
|
|
|
CHANGES=$(git log --oneline -15 --no-merges -- bios/ platforms/ | sed 's/^/- /')
|
|
TOTAL=$(python3 -c "import json; print(json.load(open('database.json'))['total_files'])")
|
|
SIZE=$(python3 -c "import json; print(f'{json.load(open(\"database.json\"))[\"total_size\"]/1024/1024:.0f}')")
|
|
PACKS=$(ls dist/*.zip dist/*.zip.001 2>/dev/null | while read f; do echo "- **$(basename $f)** ($(du -m "$f" | cut -f1) MB)"; done)
|
|
|
|
gh release create "$TAG" dist/*.zip* \
|
|
--repo "${{ github.repository }}" \
|
|
--title "BIOS Pack $TAG" \
|
|
--notes "${TOTAL} files, ${SIZE} MB, verified checksums.
|
|
|
|
### Packs
|
|
${PACKS}
|
|
|
|
### Install
|
|
Download the pack matching your frontend, extract to the BIOS directory.
|
|
|
|
Packs over 2 GB are split into numbered volumes (.zip.001, .zip.002).
|
|
Download every part, then either open the .001 file directly with
|
|
7-Zip / PeaZip, or join the parts first:
|
|
- Linux/macOS: \`cat PackName.zip.0* > PackName.zip\`
|
|
- Windows (cmd): \`copy /b PackName.zip.001+PackName.zip.002 PackName.zip\`
|
|
|
|
| Platform | Extract to |
|
|
|----------|------------|
|
|
| RetroArch | system/ |
|
|
| Lakka | /storage/system/ |
|
|
| RetroPie | ~/RetroPie/BIOS/ |
|
|
| Batocera | /userdata/bios/ |
|
|
| Recalbox | /recalbox/share/bios/ |
|
|
| RetroBat | bios/ |
|
|
| RetroDECK | ~/retrodeck/ (the pack carries its own bios/) |
|
|
| EmuDeck | ~/Emulation/bios/ |
|
|
| ROCKNIX | /storage/roms/bios/ |
|
|
| MiSTer FPGA | /media/fat/games/ |
|
|
| BizHawk | Firmware/ |
|
|
| RomM | bios/{platform_slug}/ |
|
|
|
|
### Changes
|
|
${CHANGES}
|
|
" \
|
|
--latest
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Cleanup old releases
|
|
if: steps.rate.outputs.skip != 'true'
|
|
run: |
|
|
gh release list --repo "${{ github.repository }}" --json tagName,createdAt \
|
|
--jq 'sort_by(.createdAt) | reverse | .[].tagName' | \
|
|
grep -v "^large-files$" | tail -n +4 | while read tag; do
|
|
gh release delete "$tag" --repo "${{ github.repository }}" --yes --cleanup-tag
|
|
done
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|