diff --git a/emulators/advanced_drastic.yml b/emulators/advanced_drastic.yml index 620b41e0a..019aa9ffa 100644 --- a/emulators/advanced_drastic.yml +++ b/emulators/advanced_drastic.yml @@ -7,6 +7,13 @@ author: "trngaje (hooks), Exophase (DraStic)" profiled_date: "2026-10-22" source_commit: "eaf41ab9bc8adcc15c010bf9517bc94c38e7bffd" pin_frozen: "KNULLI, the only platform that ships it, builds this revision (KNULLI package/emulators/advanced_drastic/advanced_drastic.mk:7 at tag 20260511). Later commits are not part of that build." +pin_build: + - platform: knulli + repo: "https://github.com/knulli-cfw/knulli-linux" + revision: "20260511" + path: "package/emulators/advanced_drastic/advanced_drastic.mk" + variable: ADVANCED_DRASTIC_VERSION + value: "eaf41ab9bc8adcc15c010bf9517bc94c38e7bffd" core_version: "r2.5.2.0" version_basis: kind: file diff --git a/emulators/advmame-1.4.yml b/emulators/advmame-1.4.yml index 490b994d7..db2d0f0d5 100644 --- a/emulators/advmame-1.4.yml +++ b/emulators/advmame-1.4.yml @@ -6,6 +6,13 @@ upstream: "https://www.mamedev.org" profiled_date: "2026-10-20" source_commit: "237ca5c898e51e1b7a70ce52bccf008aa722e924" pin_frozen: "RetroPie builds the advancemame-1.4 release tarball, whose src/ tree is this tag. Later commits are not part of that build." +pin_build: + - platform: retropie + repo: "https://github.com/RetroPie/RetroPie-Setup" + revision: "46128cd252cdecae852a4d0bafa2aaf9d03ab563" + path: "scriptmodules/emulators/advmame-1.4.sh" + variable: rp_module_repo + value: "file $__archive_url/advancemame-1.4.tar.gz" core_version: "advancemame-1.4" version_basis: kind: tag diff --git a/emulators/alephone.yml b/emulators/alephone.yml index d0dfaf1a6..6607f45e9 100644 --- a/emulators/alephone.yml +++ b/emulators/alephone.yml @@ -6,6 +6,13 @@ upstream: "https://github.com/Aleph-One-Marathon/alephone" profiled_date: "2026-10-20" source_commit: "07a9c36aff403d143a0608815f725631a01e382c" pin_frozen: "RetroPie, the only platform that ships it, builds the release-20250829 tag at this commit (scriptmodules/ports/alephone.sh, _get_branch_alephone). Debian 10 and older get release-20250302." +pin_build: + - platform: retropie + repo: "https://github.com/RetroPie/RetroPie-Setup" + revision: "46128cd252cdecae852a4d0bafa2aaf9d03ab563" + path: "scriptmodules/ports/alephone.sh" + variable: version + value: "20250829" core_version: "release-20250829" version_basis: kind: tag diff --git a/emulators/azahar-sdl.yml b/emulators/azahar-sdl.yml index 126f775b3..0673125c2 100644 --- a/emulators/azahar-sdl.yml +++ b/emulators/azahar-sdl.yml @@ -5,6 +5,13 @@ source: "https://github.com/johndoe6345789/azahar_libretro" profiled_date: "2026-10-22" source_commit: "c8d39853c1ebacc5657e51d601713a09404ca8a7" pin_frozen: "KNULLI, the only platform that ships it, builds this revision (KNULLI package/emulators/azahar/azahar.mk:7 at tag 20260511). Later commits are not part of that build." +pin_build: + - platform: knulli + repo: "https://github.com/knulli-cfw/knulli-linux" + revision: "20260511" + path: "package/emulators/azahar/azahar.mk" + variable: AZAHAR_VERSION + value: "c8d39853c1ebacc5657e51d601713a09404ca8a7" core_version: "2122-rc1-178-gc8d3985" version_basis: kind: tag diff --git a/emulators/bennugd-monolithic.yml b/emulators/bennugd-monolithic.yml index 6f4e2a688..a3c6f490b 100644 --- a/emulators/bennugd-monolithic.yml +++ b/emulators/bennugd-monolithic.yml @@ -5,6 +5,13 @@ source: "https://github.com/christianhaitian/bennugd-monolithic" profiled_date: "2026-10-22" source_commit: "60ee3389efcf9b402d66035e87f33d17d70cbd83" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/bennugd-monolithic/package.mk:5 at v4.8). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/bennugd-monolithic/package.mk" + variable: PKG_VERSION + value: "60ee3389efcf9b402d66035e87f33d17d70cbd83" core_version: "1.0.0" version_basis: kind: file diff --git a/emulators/bermuda.yml b/emulators/bermuda.yml index 130dc2538..b2354f468 100644 --- a/emulators/bermuda.yml +++ b/emulators/bermuda.yml @@ -5,6 +5,13 @@ source: "https://github.com/cyxx/bermuda" profiled_date: "2026-10-22" source_commit: "cf6bdb68d53a1618967da565a44c931b15daf791" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/bermuda/package.mk:5 at v4.8). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/bermuda/package.mk" + variable: PKG_VERSION + value: "cf6bdb68d53a1618967da565a44c931b15daf791" core_version: "0.1.7" version_basis: kind: file diff --git a/emulators/ccleste.yml b/emulators/ccleste.yml index d2848132d..351257b8f 100644 --- a/emulators/ccleste.yml +++ b/emulators/ccleste.yml @@ -5,6 +5,13 @@ source: "https://github.com/lemon32767/ccleste" profiled_date: "2026-10-22" source_commit: "261d96f15af430b8111abc7a5250229246654f52" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/ccleste/package.mk:5 at v4.8). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/ccleste/package.mk" + variable: PKG_VERSION + value: "261d96f15af430b8111abc7a5250229246654f52" core_version: "v1.4.0" version_basis: kind: tag diff --git a/emulators/chocolate-doom.yml b/emulators/chocolate-doom.yml index b3f416c2e..5fffc5fad 100644 --- a/emulators/chocolate-doom.yml +++ b/emulators/chocolate-doom.yml @@ -5,6 +5,13 @@ source: "https://github.com/chocolate-doom/chocolate-doom" profiled_date: "2026-10-22" source_commit: "72d9e9318c4ccc61dab29bb9cc30bc8a9a93266d" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/chocolate-doom/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/chocolate-doom/package.mk" + variable: PKG_VERSION + value: "72d9e9318c4ccc61dab29bb9cc30bc8a9a93266d" core_version: "3.0.0" version_basis: kind: file diff --git a/emulators/daedalusx64.yml b/emulators/daedalusx64.yml index 526976ff1..9fa26a8ae 100644 --- a/emulators/daedalusx64.yml +++ b/emulators/daedalusx64.yml @@ -5,6 +5,13 @@ source: "https://github.com/DaedalusX64/daedalus" profiled_date: "2026-10-17" source_commit: "f17e9ed86f3806fadeb69abd29c9526ab2d4bd1b" pin_frozen: "ROCKNIX 20261001 builds this revision. Later upstream commits are not part of that build." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/standalone/daedalusx64-sa/package.mk" + variable: PKG_VERSION + value: "f17e9ed86f3806fadeb69abd29c9526ab2d4bd1b" core_version: "1.1.8-837-gf17e9ed" version_basis: kind: tag diff --git a/emulators/dsperate.yml b/emulators/dsperate.yml index 9058a2dfa..f83d6f795 100644 --- a/emulators/dsperate.yml +++ b/emulators/dsperate.yml @@ -5,6 +5,13 @@ source: "https://github.com/beebono/DSperate" profiled_date: "2026-10-17" source_commit: "81b73832c2e68e2b10cb5850f0a6d393ffc6fbb7" pin_frozen: "ROCKNIX 20261001 ships the v2.0.1 release binaries, built by CI from the v2.0.1 tag at this commit." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/standalone/dsperate-sa/package.mk" + variable: PKG_VERSION + value: "2.0.1" core_version: "v2.0.1" version_basis: kind: tag diff --git a/emulators/duckstation-legacy.yml b/emulators/duckstation-legacy.yml index 35e5bf244..6c346f7f4 100644 --- a/emulators/duckstation-legacy.yml +++ b/emulators/duckstation-legacy.yml @@ -5,6 +5,13 @@ source: "https://github.com/stenzek/duckstation" profiled_date: "2026-10-22" source_commit: "56ac3d6c324ec4520dac433b071ecab6227fb459" pin_frozen: "Batocera builds this revision of 4 August 2023 as duckstation-legacy, its package marked not to be bumped, and KNULLI ships the same package." +pin_build: + - platform: batocera + repo: "https://github.com/batocera-linux/batocera.linux" + revision: "batocera-43.1" + path: "package/batocera/emulators/duckstation-legacy/duckstation-legacy.mk" + variable: DUCKSTATION_LEGACY_VERSION + value: "56ac3d6c324ec4520dac433b071ecab6227fb459" core_version: "0.1-5612-g56ac3d6" version_basis: kind: tag diff --git a/emulators/eightyone.yml b/emulators/eightyone.yml index bd2c20de4..33b94a5e9 100644 --- a/emulators/eightyone.yml +++ b/emulators/eightyone.yml @@ -11,6 +11,13 @@ version_basis: tag: "v1.2" distance: 0 pin_frozen: "Recalbox, the only platform that ships this core, builds its tag v1.2 (Recalbox package/libretro-eightyone/libretro-eightyone.mk:8 at tag 10.1.1)." +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/libretro-eightyone/libretro-eightyone.mk" + variable: LIBRETRO_EIGHTYONE_VERSION + value: "v1.2" display_name: "Sinclair - ZX81 / ZX Spectrum (EightyOne, Recalbox)" cores: ["eightyone"] built_by: [recalbox] diff --git a/emulators/exel-hence.yml b/emulators/exel-hence.yml index 84da03588..0539428f6 100644 --- a/emulators/exel-hence.yml +++ b/emulators/exel-hence.yml @@ -11,6 +11,13 @@ version_basis: tag: "v0.9" distance: 0 pin_frozen: "Recalbox, the only platform that ships this core, builds its tag v0.9 (Recalbox package/libretro-exel-hence/libretro-exel-hence.mk:9 at tag 10.1.1)." +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/libretro-exel-hence/libretro-exel-hence.mk" + variable: LIBRETRO_EXEL_HENCE_VERSION + value: "v0.9" display_name: "Exelvision - EXL 100 (Exel-Hence)" cores: - "exel-hence" diff --git a/emulators/fbalpha2019.yml b/emulators/fbalpha2019.yml index dc2100223..51d16bf37 100644 --- a/emulators/fbalpha2019.yml +++ b/emulators/fbalpha2019.yml @@ -7,6 +7,13 @@ profiled_date: "2026-10-17" source_commit: "0581797db6fdffd826086b053ced4b6b29bb6678" upstream_commit: "416948158d88ba17f87813419ddc3c1209ef68c0" pin_frozen: "ROCKNIX 20261001 builds this revision as fbalpha2019. Later commits on libretro/fbalpha are not part of that build." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/libretro/fbalpha2019-lr/package.mk" + variable: PKG_VERSION + value: "0581797db6fdffd826086b053ced4b6b29bb6678" core_version: "v0.2.97.44" version_basis: kind: file diff --git a/emulators/fheroes2.yml b/emulators/fheroes2.yml index 75f787a71..da3a3ff72 100644 --- a/emulators/fheroes2.yml +++ b/emulators/fheroes2.yml @@ -5,6 +5,13 @@ source: "https://github.com/ihhub/fheroes2" profiled_date: "2026-10-22" source_commit: "35ca4c915be00098547d5050412a325dd55cfd7f" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/fheroes2/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/fheroes2/package.mk" + variable: PKG_VERSION + value: "35ca4c915be00098547d5050412a325dd55cfd7f" core_version: "1.0.11" version_basis: kind: file diff --git a/emulators/flycast2021.yml b/emulators/flycast2021.yml index 7f6257b87..33b357aad 100644 --- a/emulators/flycast2021.yml +++ b/emulators/flycast2021.yml @@ -7,6 +7,13 @@ profiled_date: "2026-10-17" source_commit: "603814c9f73b773c455d9a497f389d2f93a257fd" upstream_commit: "4c293f306bc16a265c2d768af5d0cea138426054" pin_frozen: "ROCKNIX 20261001 builds this revision. No branch of metallic77/flycast holds it any more: master was put back on the libretro merge base 4c293f30, so HEAD is the code before the fork's own commits." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/libretro/flycast2021-lr/package.mk" + variable: PKG_VERSION + value: "603814c9f73b773c455d9a497f389d2f93a257fd" core_version: "0.1" version_basis: kind: file diff --git a/emulators/flycast2021le.yml b/emulators/flycast2021le.yml index e66242c0f..2ced2bd01 100644 --- a/emulators/flycast2021le.yml +++ b/emulators/flycast2021le.yml @@ -7,6 +7,13 @@ profiled_date: "2026-10-22" source_commit: "bf93aece5db7050667075a1107ab380856b44a23" upstream_commit: "4c293f306bc16a265c2d768af5d0cea138426054" pin_frozen: "AmberELEC, the only platform that ships it, builds this revision (AmberELEC packages/games/libretro/flycast2021le/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: amberelec + repo: "https://github.com/AmberELEC/AmberELEC" + revision: "a21975bfb1a3af68f66e07a931b994b523e1e6e2" + path: "packages/games/libretro/flycast2021le/package.mk" + variable: PKG_VERSION + value: "bf93aece5db7050667075a1107ab380856b44a23" core_version: "0.1" version_basis: kind: file diff --git a/emulators/gsplus-legacy.yml b/emulators/gsplus-legacy.yml index f63659cd7..dc3c8a6cd 100644 --- a/emulators/gsplus-legacy.yml +++ b/emulators/gsplus-legacy.yml @@ -7,6 +7,13 @@ source: "https://github.com/digarok/gsplus-legacy-archive" profiled_date: "2026-10-20" source_commit: "480572054518112647c8fae5d7ea7046a6d6ecfb" pin_frozen: "Recalbox builds this commit (Recalbox package/gsplus/gsplus.mk:8-9 at tag 10.1.1). Batocera builds the applemu fork and RetroBat its release build, as the notes say." +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/gsplus/gsplus.mk" + variable: GSPLUS_VERSION + value: "480572054518112647c8fae5d7ea7046a6d6ecfb" core_version: "0.14" version_basis: kind: file diff --git a/emulators/hode.yml b/emulators/hode.yml index 88c659e9e..a8d1ec333 100644 --- a/emulators/hode.yml +++ b/emulators/hode.yml @@ -5,6 +5,13 @@ source: "https://github.com/usineur/hode" profiled_date: "2026-10-22" source_commit: "59f3c466923c6b8d49e29176ff697a91165e7efc" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/hodesdl/package.mk:6 at v4.8). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/hodesdl/package.mk" + variable: PKG_VERSION + value: "59f3c466923c6b8d49e29176ff697a91165e7efc" core_version: "0.2.9f" version_basis: kind: file diff --git a/emulators/love-0.10.2.yml b/emulators/love-0.10.2.yml index ca41ff412..9fc298b50 100644 --- a/emulators/love-0.10.2.yml +++ b/emulators/love-0.10.2.yml @@ -6,6 +6,13 @@ upstream: "https://github.com/love2d/love" profiled_date: "2026-10-20" source_commit: "9e139779956ddba89333eece8104bd7b1b4ff2e7" pin_frozen: "RetroPie, the only platform that ships it, builds the 0.10.2 tag at this commit (RetroPie scriptmodules/ports/love-0.10.2.sh:16). Later releases are packaged separately as love." +pin_build: + - platform: retropie + repo: "https://github.com/RetroPie/RetroPie-Setup" + revision: "46128cd252cdecae852a4d0bafa2aaf9d03ab563" + path: "scriptmodules/ports/love-0.10.2.sh" + variable: rp_module_repo + value: "git https://github.com/love2d/love 0.10.2" core_version: "0.10.2" version_basis: kind: tag diff --git a/emulators/lzdoom.yml b/emulators/lzdoom.yml index 8ca3a0e57..0aa911f89 100644 --- a/emulators/lzdoom.yml +++ b/emulators/lzdoom.yml @@ -5,6 +5,19 @@ source: "https://github.com/drfrag666/lzdoom" profiled_date: "2026-10-20" source_commit: "4ce19a12164ebd6802b7fb2f94d700a6e736d0fb" pin_frozen: "The platforms that ship it run the 3.88 line: RetroPie builds tag 3.88b (RetroPie scriptmodules/ports/lzdoom.sh:15) and AmberELEC a fork of the g3.3mgw branch that still reports 3.88b (AmberELEC packages/games/emulators/lzdoom/package.mk:5). The l4.x releases are a GZDoom 4 based line that no platform ships." +pin_build: + - platform: retropie + repo: "https://github.com/RetroPie/RetroPie-Setup" + revision: "46128cd252cdecae852a4d0bafa2aaf9d03ab563" + path: "scriptmodules/ports/lzdoom.sh" + variable: rp_module_repo + value: "git https://github.com/drfrag666/gzdoom 3.88b" + - platform: amberelec + repo: "https://github.com/AmberELEC/AmberELEC" + revision: "a21975bfb1a3af68f66e07a931b994b523e1e6e2" + path: "packages/games/emulators/lzdoom/package.mk" + variable: PKG_VERSION + value: "8e12e62164ea1ba52625c63bc0f1c9e0076bff4c" core_version: "3.88b" version_basis: kind: tag diff --git a/emulators/mame0258.yml b/emulators/mame0258.yml index 76bc45c4f..3df4ed857 100644 --- a/emulators/mame0258.yml +++ b/emulators/mame0258.yml @@ -7,6 +7,13 @@ profiled_date: '2026-10-22' source_commit: dc1a96537089d6d4ecd01d9886b21061471c70c0 upstream_commit: 2e0aa823508663c4a27164be43467d1ef740cdcd pin_frozen: 'Recalbox, the only platform that ships it, builds this revision (Recalbox package/libretro-mame0258/libretro-mame0258.mk:8 at tag 10.1.1). Later commits are not part of that build.' +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/libretro-mame0258/libretro-mame0258.mk" + variable: LIBRETRO_MAME0258_VERSION + value: "dc1a96537089d6d4ecd01d9886b21061471c70c0" core_version: "0.258" version_basis: kind: file diff --git a/emulators/mame0278.yml b/emulators/mame0278.yml index 8ba5f4673..f37e94c1f 100644 --- a/emulators/mame0278.yml +++ b/emulators/mame0278.yml @@ -7,6 +7,13 @@ profiled_date: '2026-10-22' source_commit: fba50741006fa3e27e1897f589d2048a505b8fd6 upstream_commit: eb05584a2b8d98d5af5587244c9cb7dcccf660fd pin_frozen: 'Recalbox, the only platform that ships it, builds this revision (Recalbox package/libretro-mame0278/libretro-mame0278.mk:8 at tag 10.1.1). Later commits are not part of that build.' +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/libretro-mame0278/libretro-mame0278.mk" + variable: LIBRETRO_MAME0278_VERSION + value: "fba50741006fa3e27e1897f589d2048a505b8fd6" core_version: "0.278" version_basis: kind: file diff --git a/emulators/nanoboyadvance.yml b/emulators/nanoboyadvance.yml index bbd61b392..0e113e0f4 100644 --- a/emulators/nanoboyadvance.yml +++ b/emulators/nanoboyadvance.yml @@ -5,6 +5,13 @@ source: "https://github.com/nba-emu/NanoBoyAdvance" profiled_date: "2026-10-17" source_commit: "3bb6f478f977dbfd3106508536e5fbce90d1898b" pin_frozen: "ROCKNIX 20261001 builds this revision of the SDL2 frontend (v1.6 plus four commits). Later upstream work is not part of that build." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/standalone/nanoboyadvance-sa/package.mk" + variable: PKG_VERSION + value: "3bb6f478f977dbfd3106508536e5fbce90d1898b" core_version: "v1.6-4-g3bb6f47" version_basis: kind: tag diff --git a/emulators/piemu.yml b/emulators/piemu.yml index f0b5bdef3..12e1ec8b4 100644 --- a/emulators/piemu.yml +++ b/emulators/piemu.yml @@ -7,6 +7,13 @@ profiled_date: "2026-10-22" source_commit: "0785214f13746bdfd709b1909f007e213b470ba1" upstream_commit: "23208626e16e53b73fd21a2fbd0c429338625dc4" pin_frozen: "AmberELEC, the only platform that ships it, builds this revision (AmberELEC packages/games/emulators/piemu/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: amberelec + repo: "https://github.com/AmberELEC/AmberELEC" + revision: "a21975bfb1a3af68f66e07a931b994b523e1e6e2" + path: "packages/games/emulators/piemu/package.mk" + variable: PKG_VERSION + value: "0785214f13746bdfd709b1909f007e213b470ba1" core_version: "20030430" version_basis: kind: file diff --git a/emulators/ppsspp-1.5.4.yml b/emulators/ppsspp-1.5.4.yml index 1ba7ad930..d5f8a3d16 100644 --- a/emulators/ppsspp-1.5.4.yml +++ b/emulators/ppsspp-1.5.4.yml @@ -5,6 +5,13 @@ source: "https://github.com/hrydgard/ppsspp" profiled_date: "2026-10-20" source_commit: "a1e74d0d4f89ba3fa2d4fe64bac7a0fa16fc146f" pin_frozen: "RetroPie, the only platform that ships it, builds the v1.5.4 tag at this commit (RetroPie scriptmodules/emulators/ppsspp-1.5.4.sh:16). Later releases are packaged separately as ppsspp." +pin_build: + - platform: retropie + repo: "https://github.com/RetroPie/RetroPie-Setup" + revision: "46128cd252cdecae852a4d0bafa2aaf9d03ab563" + path: "scriptmodules/emulators/ppsspp-1.5.4.sh" + variable: rp_module_repo + value: "git https://github.com/hrydgard/ppsspp.git v1.5.4" core_version: "v1.5.4" version_basis: kind: tag diff --git a/emulators/rb5000.yml b/emulators/rb5000.yml index 01d9064db..637766890 100644 --- a/emulators/rb5000.yml +++ b/emulators/rb5000.yml @@ -10,6 +10,13 @@ source_commit: standalone: "8c75a4b48a5222b0332d0508600f8ddc7ac1191c" libretro: "7464996aa0cb1be77abf495dc901117e1af36e02" pin_frozen: "Recalbox, the only platform that ships the standalone build, builds its tag v1.1 at this standalone revision (Recalbox package/rb5000/rb5000.mk:7). Later commits are not part of that build. The libretro pin is the HEAD of libretro-rb5000." +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/rb5000/rb5000.mk" + variable: RB5000_VERSION + value: "v1.1" core_version: standalone: "v1.1" libretro: "v0.9" diff --git a/emulators/reicast.yml b/emulators/reicast.yml index 975bcfa4c..eb7784e7e 100644 --- a/emulators/reicast.yml +++ b/emulators/reicast.yml @@ -6,6 +6,13 @@ upstream: "https://github.com/skmp/reicast-emulator" profiled_date: "2026-10-17" source_commit: "ad61f95dd6b4c6218846a25de6194550311a5d28" pin_frozen: "Recalbox 10.1.1 builds this revision (package/reicast/reicast.mk REICAST_VERSION). Later commits on reicast-emulator are not part of that build." +pin_build: + - platform: recalbox + repo: "https://gitlab.com/recalbox/recalbox" + revision: "10.1.1" + path: "package/reicast/reicast.mk" + variable: REICAST_VERSION + value: "ad61f95dd6b4c6218846a25de6194550311a5d28" core_version: "r8.1-243-gad61f95" version_basis: kind: tag diff --git a/emulators/rigelengine.yml b/emulators/rigelengine.yml index 002d4996e..1e6996c25 100644 --- a/emulators/rigelengine.yml +++ b/emulators/rigelengine.yml @@ -6,6 +6,13 @@ upstream: "https://github.com/lethal-guitar/RigelEngine" profiled_date: "2026-10-22" source_commit: "f05996f9b3ad3b3ea5bb818e49e7977636746343" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/rigelengine/package.mk:5 at v4.8). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/rigelengine/package.mk" + variable: PKG_VERSION + value: "f05996f9b3ad3b3ea5bb818e49e7977636746343" core_version: "0.9.1" version_basis: kind: file diff --git a/emulators/supermariowar.yml b/emulators/supermariowar.yml index d2ce65c99..6f3d87b05 100644 --- a/emulators/supermariowar.yml +++ b/emulators/supermariowar.yml @@ -5,6 +5,13 @@ source: "https://github.com/mmatyas/supermariowar" profiled_date: "2026-10-22" source_commit: "ed60ed45e296ff88a8883cbc51f5bf5aed880636" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/supermariowar/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/supermariowar/package.mk" + variable: PKG_VERSION + value: "ed60ed45e296ff88a8883cbc51f5bf5aed880636" core_version: "2.0.0" version_basis: kind: file diff --git a/emulators/supermodel-legacy.yml b/emulators/supermodel-legacy.yml index a501a3883..ea183429c 100644 --- a/emulators/supermodel-legacy.yml +++ b/emulators/supermodel-legacy.yml @@ -6,6 +6,13 @@ upstream: "https://github.com/trzy/Supermodel" profiled_date: "2026-10-17" source_commit: "0eef09ba2b74e48fd5cfd388ee69a3743fd5f618" pin_frozen: "Batocera's supermodel-legacy package builds this revision, held before the renderer moved to OpenGL 4.1. Recaling would repoint these refs at code this build never had." +pin_build: + - platform: batocera + repo: "https://github.com/batocera-linux/batocera.linux" + revision: "batocera-43.1" + path: "package/batocera/emulators/supermodel-legacy/supermodel-legacy.mk" + variable: SUPERMODEL_LEGACY_VERSION + value: "0eef09ba2b74e48fd5cfd388ee69a3743fd5f618" core_version: "0.3a-WIP" version_basis: kind: file diff --git a/emulators/supersnes9x.yml b/emulators/supersnes9x.yml index bb8966d61..d6f387124 100644 --- a/emulators/supersnes9x.yml +++ b/emulators/supersnes9x.yml @@ -6,6 +6,13 @@ upstream: "https://github.com/snes9xgit/snes9x" profiled_date: "2026-10-17" source_commit: "691e47b40fb38fa522a5471462344a2f0206b7a8" pin_frozen: "ROCKNIX 20261001 builds this revision. Later commits on shanytc/snes9x rework the Super Famicom Box loader and are not part of that build." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/libretro/supersnes9x-lr/package.mk" + variable: PKG_VERSION + value: "691e47b40fb38fa522a5471462344a2f0206b7a8" core_version: "1.63.29" version_basis: kind: file diff --git a/emulators/supertux.yml b/emulators/supertux.yml index c05f1b9d6..5b086f101 100644 --- a/emulators/supertux.yml +++ b/emulators/supertux.yml @@ -5,6 +5,13 @@ source: "https://github.com/SuperTux/supertux" profiled_date: "2026-10-22" source_commit: "37cddf24a4abfdec7931a84afd9e87fb8ea18767" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision, v0.6.3 (EmuELEC packages/sx05re/emuelec-ports/supertux/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/supertux/package.mk" + variable: PKG_VERSION + value: "37cddf24a4abfdec7931a84afd9e87fb8ea18767" core_version: "v0.6.3-1020-g37cddf2" version_basis: kind: tag diff --git a/emulators/supertuxkart.yml b/emulators/supertuxkart.yml index 9fe306c0f..f2d9f99b5 100644 --- a/emulators/supertuxkart.yml +++ b/emulators/supertuxkart.yml @@ -5,6 +5,13 @@ source: "https://github.com/supertuxkart/stk-code" profiled_date: "2026-10-22" source_commit: "fab79150111944c9e33396db68eb5de84f2efeaa" pin_frozen: "EmuELEC, the only platform that ships it, builds this revision (EmuELEC packages/sx05re/emuelec-ports/supertuxkart/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: emuelec + repo: "https://github.com/EmuELEC/EmuELEC" + revision: "v4.8" + path: "packages/sx05re/emuelec-ports/supertuxkart/package.mk" + variable: PKG_VERSION + value: "fab79150111944c9e33396db68eb5de84f2efeaa" core_version: "preview-582-gfab7915" version_basis: kind: tag diff --git a/emulators/touchhle.yml b/emulators/touchhle.yml index d588e5190..442667f59 100644 --- a/emulators/touchhle.yml +++ b/emulators/touchhle.yml @@ -5,6 +5,13 @@ source: "https://github.com/touchHLE/touchHLE" profiled_date: "2026-10-17" source_commit: "3c5850585ba55615b17a58c58331b6d6f52d4a9d" pin_frozen: "ROCKNIX 20261001 builds this revision. Later upstream commits are not part of that build." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/standalone/touchhle-sa/package.mk" + variable: PKG_VERSION + value: "3c5850585ba55615b17a58c58331b6d6f52d4a9d" core_version: "0.2.3" version_basis: kind: file diff --git a/emulators/vice-standalone.yml b/emulators/vice-standalone.yml index 612ac8f1f..c4a61a000 100644 --- a/emulators/vice-standalone.yml +++ b/emulators/vice-standalone.yml @@ -7,6 +7,13 @@ logo: "https://raw.githubusercontent.com/VICE-Team/svn-mirror/main/vice/data/com profiled_date: "2026-10-24" source_commit: "81546e60c222fe4aef750b890b0dbe3a5ac280d8" pin_frozen: "ROCKNIX, the only platform that ships it, builds this revision (ROCKNIX projects/ROCKNIX/packages/emulators/standalone/vice-sa/package.mk:5). Later commits are not part of that build." +pin_build: + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261001" + path: "projects/ROCKNIX/packages/emulators/standalone/vice-sa/package.mk" + variable: PKG_VERSION + value: "3.8" core_version: "3.8" version_basis: kind: file diff --git a/schemas/emulator.schema.json b/schemas/emulator.schema.json index 661ec316b..9ca4a8418 100644 --- a/schemas/emulator.schema.json +++ b/schemas/emulator.schema.json @@ -10,6 +10,19 @@ "type" ], "allOf": [ + { + "comment": "A build reference documents why a pin is held: it never stands without the pin_frozen that says so.", + "if": { + "required": [ + "pin_build" + ] + }, + "then": { + "required": [ + "pin_frozen" + ] + } + }, { "comment": "An alias profile points at another profile and carries no files of its own.", "if": { @@ -991,6 +1004,43 @@ "type": "string", "description": "Why source_commit is held on purpose rather than followed. The profile is then judged against its own revision, like one pinned to a superseded tag: comparing it to HEAD says nothing and recaling would repoint its refs at code the build it documents never had." }, + "pin_build": { + "type": "array", + "minItems": 1, + "description": "The build file each platform that ships a pin_frozen build reads its revision from, so check_freshness can read it again where the platform's YAML now stands and say when the platform builds another revision.", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["platform", "repo", "revision", "path", "variable", "value"], + "properties": { + "platform": { + "type": "string", + "description": "Registry slug of the platform (platforms/.yml)." + }, + "repo": { + "type": "string", + "format": "uri", + "description": "The platform's own repository, the one its YAML is scraped from." + }, + "revision": { + "type": "string", + "description": "Tag or commit of that repository the build file was read at." + }, + "path": { + "type": "string", + "description": "The build file, from the repository root (package.mk, a Buildroot .mk, a RetroPie scriptmodule)." + }, + "variable": { + "type": "string", + "description": "The variable the file sets to the revision it builds (PKG_VERSION, _VERSION, rp_module_repo)." + }, + "value": { + "type": "string", + "description": "What the variable held at revision, quotes and trailing comment removed." + } + } + } + }, "pin_follows": { "type": "string", "description": "Why source_commit follows the branch tip although a single platform ships the profile: that platform builds the tip, cited by its build file. Without it or pin_frozen, a bump refuses a profile one platform ships." diff --git a/scripts/check_freshness.py b/scripts/check_freshness.py index c90ec334c..fac97bc71 100644 --- a/scripts/check_freshness.py +++ b/scripts/check_freshness.py @@ -1461,6 +1461,117 @@ def check_source_paths(profiles: dict) -> Finding: ) +def build_variable(lines: list[str], variable: str) -> str | None: + """The value the first assignment to ``variable`` gives in a build file. + + Read as a Buildroot .mk (`X_VERSION = sha`), a LibreELEC package.mk + (`PKG_VERSION="sha"`) or a RetroPie scriptmodule (`rp_module_repo="git + URL tag"`, `local version="20250829"`): quotes and a trailing comment go, + the rest is compared as written. + """ + assignment = re.compile( + rf"^\s*(?:local\s+|export\s+)?{re.escape(variable)}\s*[:?+]?=\s*(.*)$" + ) + for line in lines: + match = assignment.match(line) + if not match: + continue + value = match.group(1).strip() + if value[:1] in "\"'": + end = value.find(value[0], 1) + return value[1:end] if end > 0 else value[1:] + return value.split(" #", 1)[0].strip() + return None + + +def pin_build_revision(reference: dict, platforms_dir: Path) -> str: + """The revision of the platform repository its YAML was last scraped at, + '' when the platform is not registered or reads another repository.""" + path = platforms_dir / f"{reference.get('platform', '')}.yml" + repo = upstream.parse_repo(str(reference.get("repo") or "")) + if repo is None or not path.is_file(): + return "" + with path.open(encoding="utf-8") as fh: + source = str((yaml_load(fh) or {}).get("source") or "") + if f"/{repo.slug.lower()}/" not in source.lower() + "/": + return "" + return export_native.source_revision(source) + + +def check_pin_builds( + profiles: dict, platforms_dir: Path, cache_dir: str, offline: bool, +) -> list[Finding]: + """Each `pin_build:` read again where the platform now stands. + + A pin_frozen pin is held because one platform builds that revision, and + nothing read the build file again: Recalbox moving mame0278 to another + commit left the profile describing a build no platform ships. The file + is read at the revision the platform's own YAML was scraped at, or at + the repository's branch head for a platform this repository does not + scrape, and its variable compared with the value the profile recorded. + """ + findings: list[Finding] = [] + unreferenced = sorted( + name for name, profile in profiles.items() + if profile.get("pin_frozen") and not profile.get("pin_build") + ) + if unreferenced: + findings.append(Finding( + "profiles", "pin_frozen without pin_build", SKIPPED, + local=f"{len(unreferenced)} profiles", + detail="no platform build file names their revision: " + + ", ".join(unreferenced[:SHOWN_NAMES]) + + (", ..." if len(unreferenced) > SHOWN_NAMES else ""), + items=unreferenced, + )) + for name, profile in sorted(profiles.items()): + for reference in profile.get("pin_build") or []: + subject = f"{name} ({reference['platform']})" + recorded = str(reference["value"]) + revision = pin_build_revision(reference, platforms_dir) + if revision == str(reference["revision"]): + findings.append(Finding( + "profiles", subject, OK, local=recorded[:12], + detail=f"read where platforms/{reference['platform']}.yml is", + )) + continue + repo = upstream.parse_repo(str(reference["repo"])) + try: + at = revision or upstream.resolve_head(repo, cache_dir, offline) + lines = upstream.fetch_file(repo, at, reference["path"], cache_dir, offline) \ + if at else None + except upstream.NotCachedError: + findings.append(Finding("profiles", subject, SKIPPED, local=recorded[:12], + detail="offline, the build file is not cached")) + continue + except upstream.UpstreamError as exc: + findings.append(Finding("profiles", subject, UNKNOWN, local=recorded[:12], + detail=str(exc))) + continue + if not at: + findings.append(Finding("profiles", subject, UNKNOWN, local=recorded[:12], + detail=f"{repo.slug} answered no branch head")) + continue + current = None if lines is None else build_variable(lines, reference["variable"]) + if current == recorded: + findings.append(Finding( + "profiles", subject, OK, local=recorded[:12], remote=at[:12], + detail=f"{reference['path']} still builds it", + )) + continue + findings.append(Finding( + "profiles", subject, STALE, local=recorded[:12], + remote=(current or "gone")[:12], + detail=( + f"{reference['path']} is gone at {at[:12]}" if lines is None + else f"{reference['variable']} is no longer set there" if current is None + else f"{reference['platform']} now builds {current} " + f"({reference['path']} at {at[:12]}): the pin follows the build" + ), + )) + return findings + + def check_profiles(run: bool, offline: bool) -> list[Finding]: if not run: return [ @@ -1708,6 +1819,7 @@ def main() -> int: findings.extend(check_ci(args.cache_dir, args.offline)) if "profiles" in areas: findings.append(check_source_paths(profiles)) + findings.extend(check_pin_builds(profiles, platforms_dir, args.cache_dir, args.offline)) findings.extend(check_profiles(args.profiles, args.offline)) if args.json: diff --git a/tests/test_doc_pages.py b/tests/test_doc_pages.py index 409e80248..8b42cafaa 100644 --- a/tests/test_doc_pages.py +++ b/tests/test_doc_pages.py @@ -538,7 +538,7 @@ class ProfileFieldsRequired(unittest.TestCase): section = _section(_page("profiling.md"), "Profile fields") marked = { row[0].strip("`") for row in _table_rows(section) - if row[1].startswith(("yes", "for `type")) + if row[1].startswith(("yes", "for `type", "with `")) } self.assertEqual(marked, required) diff --git a/tests/test_pin_build.py b/tests/test_pin_build.py new file mode 100644 index 000000000..c4f7a4568 --- /dev/null +++ b/tests/test_pin_build.py @@ -0,0 +1,138 @@ +"""Held pins name the build file that holds them. + +pin_frozen was free prose and no tool read the build file it cites: a +platform moving mame0278 to another commit would have left the profile +holding a revision no platform builds, in silence. `pin_build` records the +file, and check_freshness reads it again where the platform now stands. +""" + +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path +from unittest import mock + +REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO_ROOT / "scripts")) + +import check_freshness as cf # noqa: E402 + +RECALBOX = "https://gitlab.com/recalbox/recalbox" + + +class HeldPinsReadTheirBuildFileAgain(unittest.TestCase): + REF = {"platform": "recalbox", "repo": RECALBOX, + "revision": "10.1.1", "path": "package/libretro-mame0278/libretro-mame0278.mk", + "variable": "LIBRETRO_MAME0278_VERSION", "value": "a" * 40} + + def setUp(self): + self._tmp = tempfile.TemporaryDirectory() + self.addCleanup(self._tmp.cleanup) + self.platforms = Path(self._tmp.name) + + def _platform(self, revision: str) -> None: + (self.platforms / "recalbox.yml").write_text( + f'source: "{RECALBOX}/-/raw/{revision}/board/es_bios.xml"\n' + ) + + def _check(self, lines=None, offline=False): + profiles = {"mame0278": {"pin_frozen": "Recalbox builds it.", "pin_build": [self.REF]}, + "raine": {"pin_frozen": "RetroBat installs this release."}} + with mock.patch.object(cf.upstream, "fetch_file", return_value=lines) as fetched: + findings = cf.check_pin_builds(profiles, self.platforms, "cache", offline) + return {f.subject: f for f in findings}, fetched + + def test_the_variable_forms_the_platforms_write(self): + cases = [ + (["LIBRETRO_MAME0278_VERSION = fba5074"], "LIBRETRO_MAME0278_VERSION", "fba5074"), + (['PKG_VERSION="37cddf2" #v0.6.3'], "PKG_VERSION", "37cddf2"), + (['rp_module_repo="file $__archive_url/advancemame-1.4.tar.gz"'], "rp_module_repo", + "file $__archive_url/advancemame-1.4.tar.gz"), + (["function f() {", ' local version="20250829"', ' version="20250302"'], + "version", "20250829"), + (["OTHER_VERSION = 1"], "PKG_VERSION", None), + ] + for lines, variable, expected in cases: + with self.subTest(variable=variable): + self.assertEqual(cf.build_variable(lines, variable), expected) + + def test_the_platform_read_at_the_same_revision_needs_no_network(self): + self._platform("10.1.1") + found, fetched = self._check() + fetched.assert_not_called() + self.assertEqual(found["mame0278 (recalbox)"].status, cf.OK) + + def test_a_new_revision_building_another_commit_is_stale(self): + self._platform("10.2") + found, fetched = self._check([f"LIBRETRO_MAME0278_VERSION = {'b' * 40}"]) + self.assertEqual(fetched.call_args.args[1:3], + ("10.2", "package/libretro-mame0278/libretro-mame0278.mk")) + row = found["mame0278 (recalbox)"] + self.assertEqual(row.status, cf.STALE) + self.assertIn("now builds " + "b" * 40, row.detail) + + def test_a_new_revision_building_the_same_commit_is_ok(self): + self._platform("10.2") + found, _ = self._check([f"LIBRETRO_MAME0278_VERSION = {'a' * 40}"]) + self.assertEqual(found["mame0278 (recalbox)"].status, cf.OK) + + def test_a_build_file_gone_is_stale(self): + self._platform("10.2") + found, _ = self._check(None) + self.assertEqual(found["mame0278 (recalbox)"].status, cf.STALE) + self.assertIn("is gone", found["mame0278 (recalbox)"].detail) + + def test_offline_and_uncached_is_skipped(self): + self._platform("10.2") + profiles = {"mame0278": {"pin_frozen": "x", "pin_build": [self.REF]}} + cold = cf.upstream.NotCachedError("not cached") + with mock.patch.object(cf.upstream, "fetch_file", side_effect=cold): + (row,) = cf.check_pin_builds(profiles, self.platforms, "cache", True) + self.assertEqual(row.status, cf.SKIPPED) + + def test_a_hold_with_no_build_file_is_counted(self): + self._platform("10.1.1") + found, _ = self._check() + row = found["pin_frozen without pin_build"] + self.assertEqual(row.status, cf.SKIPPED) + self.assertEqual(row.items, ["raine"]) + + +class EveryBuildReferenceNamesThePin(unittest.TestCase): + """Reads the repository: a pin_build value is what the platform builds, + so it is the profile's source_commit or names its core_version, and the + platform's own YAML was scraped from that repository.""" + + def test_the_values_agree(self): + from common import load_emulator_profiles + + disagree = [] + for name, profile in load_emulator_profiles(str(REPO_ROOT / "emulators")).items(): + references = profile.get("pin_build") or [] + if not references: + continue + pins = profile.get("source_commit") + pins = set(pins.values()) if isinstance(pins, dict) else {pins} + versions = profile.get("core_version") + versions = ( + {str(v) for v in versions.values()} if isinstance(versions, dict) + else {str(versions)} if versions else set() + ) + + def names_it(value: str) -> bool: + token = value.split()[-1].rsplit("/", 1)[-1].removesuffix(".tar.gz") + return value in pins or any(token in v or v in value for v in versions) + + if not any(names_it(str(r["value"])) for r in references): + disagree.append(name) + for reference in references: + if not cf.pin_build_revision(reference, REPO_ROOT / "platforms"): + disagree.append(f"{name}: {reference['platform']} is not read from " + f"{reference['repo']}") + self.assertEqual(disagree, []) + + +if __name__ == "__main__": + unittest.main() diff --git a/wiki/profiling.md b/wiki/profiling.md index 7a8ccc108..bd63cb157 100644 --- a/wiki/profiling.md +++ b/wiki/profiling.md @@ -522,7 +522,8 @@ reports the profile as uncheckable, and the CI job that runs | `version_basis` | every profile (`tests/test_version_basis.py`) | where `core_version` is read, by `kind`: `file` (`path`, `pattern`, optional `format`, and `url` with its `commit` for a file outside the profile's repositories, such as the package file of a build a platform ships), `tag` (the nearest `tag` in the pin's history and its `distance`, `core_version` in git describe's form, `match` the glob a tag must fit), `alias` (`of`), `package` (`artifact`, the APK or binary read, `url` where it was obtained), `none` (the code states no version: `core_version` null) or `unverified` (no reading could be made: `core_version` stays as written and is reported unconfirmed, `why` says why: `no_pin`, `host_unsupported`, `host_gone`, `host_unreachable`, `pin_off_branch`, `no_artifact`, `no_source`). `repo` names `upstream` or `source_mirror` when the version is that tree's. `profile_sync --verify-version` reads it again, and a pin advance rewrites `core_version` from it | | `source_commit` | see above | commit SHA of `source` the code was read at. Anchors every `source_ref` line number | | `upstream_commit` | no | same, for `upstream` | -| `pin_frozen` | no | why `source_commit` is held on purpose rather than followed. The profile is then judged against its own revision, like one pinned to a superseded tag | +| `pin_frozen` | with `pin_build` | why `source_commit` is held on purpose rather than followed. The profile is then judged against its own revision, like one pinned to a superseded tag | +| `pin_build` | no | the build file each platform shipping a `pin_frozen` build reads its revision from: a list of `platform` (registry slug), `repo` (the platform's own repository), `revision` (the tag or commit the file was read at), `path`, `variable` (`PKG_VERSION`, `_VERSION`, `rp_module_repo`) and `value` (what it held there). `check_freshness.py` reads the file again where the platform's YAML now stands and reports the profile `STALE` when the platform builds another revision. A hold that no build file names (a release binary, an abandoned repository) carries `pin_frozen` alone | | `pin_follows` | no | why `source_commit` follows the branch tip when a single platform ships the profile: that platform builds the tip, cited by its build file. A bump refuses a profile one platform ships until it carries `pin_frozen` or `pin_follows` | | `data_root` | no | per operating system (`android`, `ios`, `windows`, `macos`, `linux`), the folder the app reads its user data from, under which `standalone_path` destinations sit: `path` as the user finds it (`Android/data//files`, `%APPDATA%/...`), with the `source_ref` that builds it. Only the systems the app runs on are keyed | | `upstream_frozen` | no | why `upstream_commit` is held: the port vendors that upstream tree, synced to that release, or merged that commit. The upstream view is read at its own pin and a bump leaves it. Without it, a port that is a GitHub fork of its upstream follows the merge base of the two | diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md index 43640fc57..ceaa396d0 100644 --- a/wiki/testing-guide.md +++ b/wiki/testing-guide.md @@ -65,7 +65,7 @@ Every module in `tests/`, by the area it guards. | Pack probe | the cores a platform runs for a system, staging grown to a fixed point, runs mapped to pack and manifest entries, the line and its schema, the probe lock per run, that no page shows its lines. One class builds a real pack narrowed to PlayStation and lays it out both ways, from the archive and with `install.py --dest`, and skips without the collection | `test_pack_probe` | | Automation runner, disk cleanup, asset sync and bit-flip repair | fake jobs, git repositories with a bare origin and session worktrees, a committed file with one bit flipped, canned CI runs in place of `gh` | `test_autorun` | | Truth and native export | synthetic + cached originals | `test_export_counts`, `test_export_native_layer`, `test_export_report`, `test_exporters`, `test_truth_data_dir_readers`, `test_truth_diff`, `test_truth_layout` | -| Scrapers, upstream and provenance | inline sources, synthetic | `test_batocera_md5_list`, `test_check_freshness`, `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_dedup`, `test_doc_pages`, `test_doc_surfaces`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_optional_dependencies`, `test_profile_sync`, `test_prose_style`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_romset_recipes`, `test_schema_semantic_gate`, `test_scraper_contract`, `test_site_arcade_boards`, `test_site_availability`, `test_site_bootstrap`, `test_site_built_gate`, `test_site_components`, `test_site_console_folders`, `test_site_content_data`, `test_site_copy`, `test_site_cores`, `test_site_css`, `test_site_density_cards`, `test_site_emulator_page`, `test_site_emulators`, `test_site_entry`, `test_site_entry_tables`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_integration`, `test_site_nav`, `test_site_picker`, `test_site_platform_density`, `test_site_platform_hashes`, `test_site_reference`, `test_site_render`, `test_site_search`, `test_site_system_links`, `test_site_system_names`, `test_site_system_sections`, `test_site_systems`, `test_site_validation`, `test_site_weight`, `test_site_wiki`, `test_site_write`, `test_source_ref_targets`, `test_upstream`, `test_upstream_index`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_version_basis`, `test_workflow_paths` | +| Scrapers, upstream and provenance | inline sources, synthetic | `test_batocera_md5_list`, `test_check_freshness`, `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_dedup`, `test_doc_pages`, `test_doc_surfaces`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_optional_dependencies`, `test_pin_build`, `test_profile_sync`, `test_prose_style`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_romset_recipes`, `test_schema_semantic_gate`, `test_scraper_contract`, `test_site_arcade_boards`, `test_site_availability`, `test_site_bootstrap`, `test_site_built_gate`, `test_site_components`, `test_site_console_folders`, `test_site_content_data`, `test_site_copy`, `test_site_cores`, `test_site_css`, `test_site_density_cards`, `test_site_emulator_page`, `test_site_emulators`, `test_site_entry`, `test_site_entry_tables`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_integration`, `test_site_nav`, `test_site_picker`, `test_site_platform_density`, `test_site_platform_hashes`, `test_site_reference`, `test_site_render`, `test_site_search`, `test_site_system_links`, `test_site_system_names`, `test_site_system_sections`, `test_site_systems`, `test_site_validation`, `test_site_weight`, `test_site_wiki`, `test_site_write`, `test_source_ref_targets`, `test_upstream`, `test_upstream_index`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_version_basis`, `test_workflow_paths` | | Games on the card | small DATs, listxml and setup sources, a fake fetcher, fixture install lists, and the committed data against its schemas | `test_arcade_parents`, `test_game_catalogs`, `test_game_headers`, `test_game_regions`, `test_games_index`, `test_romfolders_card`, `test_romfolders_es` | ## Test architecture diff --git a/wiki/tools.md b/wiki/tools.md index f3af3ee55..5e4359e12 100644 --- a/wiki/tools.md +++ b/wiki/tools.md @@ -695,7 +695,15 @@ NAME` reads the folders again. The `profiles` area always checks `website/src/data/source-paths.json` against the profiles, offline: a recorded tree that no profile pins any more -is `STALE` until `sitesources.py --fetch` runs again. +is `STALE` until `sitesources.py --fetch` runs again. It also reads each +`pin_build` reference of a held pin: where the platform YAML was scraped at +the reference's own revision the row is `OK` without network, otherwise the +build file is fetched at the platform's new revision (or at the branch head +of a platform this repository does not scrape) and its variable compared +with the recorded value. A different value is `STALE`: the platform now +builds another revision, and the pin, the refs and `pin_build` move with it. +Profiles with `pin_frozen` and no `pin_build` are counted on one `SKIPPED` +row, since no build file names their revision. ```bash python scripts/check_freshness.py