Files
libretro/.github/workflows/build.yml
T
Abdessamad Derraz d588ebbde4 chore: restore large files before ci coverage checks
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.
2026-08-10 14:34:27 +02:00

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 }}