feat: hold bumps of profiles one platform ships

A bulk advance moved fheroes2, supertux and supermariowar past the
revision EmuELEC compiles, and nothing stopped it: bump_commit refused
built_by only. It now leaves a profile a single registered platform ships
until it carries pin_frozen or the new pin_follows, which says that
platform builds the branch tip.

hode, bermuda, bennugd-monolithic and ccleste are held on the
PKG_VERSION of their EmuELEC v4.8 package.mk, equal to their pins.
rigelengine was one commit past it (README.md only) and goes back to
f05996f9.
This commit is contained in:
Abdessamad Derraz committed 2026-11-05 12:23:41 +01:00
1 parent 394ef44e57
commit d5e5146819
10 files changed
+89 -2

No files matched your search

+1
View File
@@ -4,6 +4,7 @@ core_classification: game_engine
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."
core_version: "1.0.0"
version_basis:
kind: file
+1
View File
@@ -4,6 +4,7 @@ core_classification: game_engine
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."
core_version: "0.1.7"
version_basis:
kind: file
+1
View File
@@ -4,6 +4,7 @@ core_classification: game_engine
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."
core_version: "v1.4.0"
version_basis:
kind: tag
+1
View File
@@ -4,6 +4,7 @@ core_classification: game_engine
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."
core_version: "0.2.9f"
version_basis:
kind: file
+2 -1
View File
@@ -4,7 +4,8 @@ core_classification: game_engine
source: "https://github.com/lethal-guitar/RigelEngine"
upstream: "https://github.com/lethal-guitar/RigelEngine"
profiled_date: "2026-10-22"
source_commit: "30afeff8f0b105eac77ee0a2fbd54b06e1a49b60"
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."
core_version: "0.9.1"
version_basis:
kind: file
+4
View File
@@ -991,6 +991,10 @@
"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_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."
},
"data_root": {
"type": "object",
"minProperties": 1,
+46
View File
@@ -11,6 +11,7 @@ from __future__ import annotations
import argparse
import bisect
import difflib
import functools
import itertools
import json
import os
@@ -35,7 +36,10 @@ import version_basis
from common import (
_norm_system_id,
github_token,
list_registered_platforms,
load_emulator_profiles,
load_platform_config,
resolve_platform_cores,
suggest_names,
system_index,
)
@@ -3497,9 +3501,37 @@ def _needs_review(report: ProfileReport, accept_changed: bool) -> bool:
return any((report.counts or {}).get(s) for s in blocking)
@functools.lru_cache(maxsize=4)
def _platform_cores(emulators_dir: str, platforms_dir: str) -> tuple[tuple[str, frozenset[str]], ...]:
profiles = load_emulator_profiles(emulators_dir)
return tuple(
(platform, frozenset(resolve_platform_cores(
load_platform_config(platform, platforms_dir), profiles
)))
for platform in list_registered_platforms(platforms_dir, include_archived=True)
)
def shipping_platforms(
name: str, emulators_dir: str, platforms_dir: str = "platforms",
) -> list[str]:
"""The registered platforms whose cores resolve to this profile.
Archived platforms count: RetroPie still builds the packages it lists.
"""
return [
platform
for platform, cores in _platform_cores(
os.path.realpath(emulators_dir), platforms_dir
)
if name in cores
]
def bump_commit(
path: Path, report: ProfileReport, accept_changed: bool = False,
cache_dir: str = DEFAULT_CACHE, offline: bool = False,
platforms_dir: str = "platforms",
) -> bool:
"""Advance source_commit to HEAD when nothing needs a read again.
@@ -3523,6 +3555,20 @@ def bump_commit(
file=sys.stderr,
)
return False
if not (document.get("pin_frozen") or document.get("pin_follows")):
shipped = shipping_platforms(path.stem, str(path.parent), platforms_dir)
if len(shipped) == 1:
# One platform ships it, so the pin is the revision that platform
# builds: a bulk advance moved fheroes2, supertux and
# supermariowar past what EmuELEC compiles, and rigelengine is
# already one commit ahead of its package.mk.
print(
f"{path.stem}: only {shipped[0]} ships it. Read the revision its "
"build compiles and set pin_frozen, or pin_follows when it "
"builds the branch tip",
file=sys.stderr,
)
return False
if any(isinstance(document.get(f), dict) for f in ("source_commit", "upstream_commit")):
# A pin per build mode names one revision per repository, and the
# report heads only the primary one: rewriting str(dict) was a
+29
View File
@@ -3256,6 +3256,35 @@ class TestBumpCommit(unittest.TestCase):
# Nothing was compared upstream, so its pin is not written.
self.assertNotIn("uphead", text)
def test_a_profile_one_platform_ships_waits_for_its_build(self):
"""EmuELEC alone ships RigelEngine and builds its package.mk
PKG_VERSION. A bulk advance moved fheroes2 and supertux past that
build, and rigelengine is a commit ahead of it already."""
root = Path(__file__).resolve().parents[1]
path = Path(self.tmp.name) / "rigelengine.yml"
path.write_text(
SAMPLE.replace("\nnotes:", "\ntype: standalone\ncores: [rigelengine, RigelEngine]\n\nnotes:", 1),
encoding="utf-8",
)
report = ProfileReport(
name="rigelengine", repo="o/n", pin="pin", head="newhead", entries=[],
counts={}, skipped=profile_sync.NO_SOURCE_REF,
)
platforms = str(root / "platforms")
self.assertEqual(
profile_sync.shipping_platforms("rigelengine", self.tmp.name, platforms),
["emuelec"],
)
with contextlib.redirect_stderr(io.StringIO()) as err:
self.assertFalse(bump_commit(path, report, platforms_dir=platforms))
self.assertIn("only emuelec ships it", err.getvalue())
path.write_text(
path.read_text(encoding="utf-8")
+ 'pin_follows: "EmuELEC builds the branch tip"\n',
encoding="utf-8",
)
self.assertTrue(bump_commit(path, report, platforms_dir=platforms))
def test_any_other_skip_still_holds_the_pin(self):
report = ProfileReport(
name="p", repo="o/n", pin="pin", head="newhead", entries=[], counts={},
+1
View File
@@ -521,6 +521,7 @@ reports the profile as uncheckable, and the CI job that runs
| `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_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/<package>/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 |
| `prose_written_at` | no | the pin a reader confirmed the prose citations against. When the profile's history shows a text living under several pins, profile_sync takes this one as the revision the text describes, so a bump is no longer refused for a citation already reread. It never overrides a history with a single candidate |
+3 -1
View File
@@ -613,7 +613,9 @@ Writes are explicit and mechanical only. `--backfill-commits` fills a
missing `source_commit`, `--rebase-refs` recales `SHIFTED` and `RENAMED`
line ranges and moves `source_commit` to HEAD with them, all or nothing,
`--bump-commit` advances `source_commit` to HEAD only when nothing needs a
re-read. All three refuse to run on a dirty `emulators/` without `--force`,
re-read. It leaves a profile a single registered platform ships until the
profile says what that platform builds: `pin_frozen` for a fixed revision,
`pin_follows` for the branch tip. All three refuse to run on a dirty `emulators/` without `--force`,
and every write is verified by reparsing the document.
Uses `GITHUB_TOKEN` when set, which `--all` requires. Responses are cached