mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-14 05:53:47 -06:00
chore: merge the launchers served by the site
This commit is contained in:
commit
fba9a0b511
17 files changed
+837
-80
No files matched your search
+16
-14
@@ -15,6 +15,7 @@ from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
|
||||
|
||||
import build_port # noqa: E402
|
||||
from check_release import SIGNATURE, SUMS, Asset, compare_release, parse_sums
|
||||
|
||||
A = "a" * 64
|
||||
@@ -97,20 +98,21 @@ class ReleaseMatchesWhatWasBuilt(unittest.TestCase):
|
||||
self.assertIn(("unrecorded", "Other_BIOS_Pack.zip"), kinds)
|
||||
self.assertIn(("missing", "Other_BIOS_Pack.zip"), kinds)
|
||||
|
||||
def test_the_handheld_port_is_vouched_for_by_the_checksum_list(self):
|
||||
sums = {**SUMS_LIST, "RetroBIOS.zip": A}
|
||||
assets = _assets()
|
||||
self.assertEqual(
|
||||
_kinds(compare_release(RECORD, sums, assets, "v2026.10.10")),
|
||||
{("missing", "RetroBIOS.zip")},
|
||||
)
|
||||
assets["RetroBIOS.zip"] = Asset(70, A)
|
||||
self.assertEqual(compare_release(RECORD, sums, assets, "v2026.10.10"), [])
|
||||
assets["RetroBIOS.zip"] = Asset(70, B)
|
||||
self.assertEqual(
|
||||
_kinds(compare_release(RECORD, sums, assets, "v2026.10.10")),
|
||||
{("content", "RetroBIOS.zip")},
|
||||
)
|
||||
def test_a_handheld_launcher_is_no_release_file(self):
|
||||
"""The site serves the launchers built from its own commit: one in
|
||||
the checksum list or among the assets is refused."""
|
||||
for name in build_port.ARCHIVES:
|
||||
with self.subTest(name=name):
|
||||
sums = {**SUMS_LIST, name: A}
|
||||
assets = _assets()
|
||||
assets[name] = Asset(70, A)
|
||||
self.assertEqual(_kinds(compare_release(RECORD, sums, assets, "v2026.10.10")),
|
||||
{("unrecorded", name)})
|
||||
assets = _assets()
|
||||
assets[name] = Asset(70, A)
|
||||
self.assertEqual(
|
||||
_kinds(compare_release(RECORD, SUMS_LIST, assets, "v2026.10.10")),
|
||||
{("extra", name)})
|
||||
|
||||
def test_parts_must_add_up_to_the_printed_download_size(self):
|
||||
assets = _assets()
|
||||
|
||||
@@ -374,10 +374,16 @@ class TheArchives(unittest.TestCase):
|
||||
with self.subTest(archive=name), self.assertRaises(ValueError):
|
||||
build_port.build_archive(name, self.out / name, root)
|
||||
|
||||
def test_the_release_process_attaches_each(self):
|
||||
def test_the_site_serves_each_and_the_release_none(self):
|
||||
"""Each archive carries install.py: the site serves it from its own
|
||||
commit (sitehandheld.py), and the release steps never build one."""
|
||||
text = (REPO_ROOT / "wiki" / "release-process.md").read_text(encoding="utf-8")
|
||||
self.assertNotIn("scripts/build_port.py", text)
|
||||
installer = (REPO_ROOT / "wiki" / "installer.md").read_text(encoding="utf-8")
|
||||
for name in build_port.ARCHIVES:
|
||||
self.assertIn(name, text)
|
||||
with self.subTest(archive=name):
|
||||
self.assertNotIn(name, text)
|
||||
self.assertIn(f"](../get/handheld/{name})", installer)
|
||||
|
||||
|
||||
FAKE_INSTALL = r'''
|
||||
|
||||
+139
-4
@@ -313,13 +313,14 @@ class TheReleaseNotesNameTheSetupsWithoutAZip(unittest.TestCase):
|
||||
import release_notes
|
||||
|
||||
text = release_notes.render(self.RECORD, PLATFORMS, "### What changed\n\n- x\n")
|
||||
paragraph = next(line for line in text.splitlines() if line.startswith("No ZIP for "))
|
||||
paragraph = next(line for line in text.splitlines()
|
||||
if line.startswith("Only the most used setups have a pack"))
|
||||
for name in ("KNULLI", "Recalbox", "RetroPie", "Lakka"):
|
||||
self.assertIn(name, paragraph)
|
||||
for name in ("RetroArch", "Batocera", "RomM"):
|
||||
self.assertNotIn(f" {name},", paragraph)
|
||||
self.assertIn("The command above", paragraph)
|
||||
self.assertIn("--dry-run", paragraph)
|
||||
self.assertTrue(paragraph.endswith("use the command above."))
|
||||
self.assertLess(text.index("| Platform"), text.index(paragraph))
|
||||
self.assertLess(text.index(paragraph), text.index("### What changed"))
|
||||
|
||||
def test_the_rows_link_this_release_files(self):
|
||||
@@ -331,7 +332,141 @@ class TheReleaseNotesNameTheSetupsWithoutAZip(unittest.TestCase):
|
||||
self.assertIn(
|
||||
"[Download](https://github.com/Abdess/retrobios/releases/download/"
|
||||
"v2026.10.24/RomM_5_BIOS_Pack.zip)", text)
|
||||
self.assertNotIn(f"{SITE}get/", text)
|
||||
rows = [line for line in text.splitlines() if line.startswith("| ")]
|
||||
self.assertTrue(rows)
|
||||
for row in rows:
|
||||
self.assertNotIn(f"{SITE}get/", row)
|
||||
|
||||
def test_the_command_comes_before_the_packs(self):
|
||||
"""Most readers need a few files, not a pack of several GB (owner,
|
||||
2026-11-10): the command and the handheld app open the notes."""
|
||||
import release_notes
|
||||
|
||||
text = release_notes.render(self.RECORD, PLATFORMS, "### What changed\n\n- x\n")
|
||||
command = text.index("```sh")
|
||||
# The installer's handheld section, which opens on every download.
|
||||
handheld = text.index(f"{SITE}wiki/installer/#on-a-handheld-the-retrobios-port")
|
||||
packs = text.index("### Full packs")
|
||||
self.assertLess(text.index("### Get your BIOS"), command)
|
||||
self.assertLess(command, handheld)
|
||||
self.assertLess(handheld, packs)
|
||||
self.assertLess(packs, text.index("| Platform"))
|
||||
self.assertLess(packs, text.index("### What changed"))
|
||||
self.assertNotIn("releases/download/", text[:packs])
|
||||
|
||||
|
||||
class TheReleaseNotesThankPeople(unittest.TestCase):
|
||||
"""The notes end with everyone who helped since the repository started
|
||||
and the full changelog, read from gh and git (owner, 2026-11-10).
|
||||
Fixtures stand in for both."""
|
||||
|
||||
TAGS = {"c4": "v2026.11.10", "c3": "v2026.10.10", "c2": "v2026.10.10",
|
||||
"c1": "v2026.10.10", "c0": "v2026.09.04"}
|
||||
# `gh api --paginate --jq` prints one login per line, none for a
|
||||
# commit GitHub links to no account.
|
||||
COMMIT_AUTHORS = "Abdess\nhabib256\nAbdess76\ndependabot[bot]\nzed\nhabib256\n"
|
||||
PULLS = [
|
||||
{"number": 84, "author": {"login": "dajiaohuang", "is_bot": False}},
|
||||
{"number": 86, "author": {"login": "habib256", "is_bot": False}},
|
||||
{"number": 80, "author": {"login": "app/dependabot", "is_bot": True}},
|
||||
{"number": 67, "author": {"login": "prakashmagat50-byte", "is_bot": False}},
|
||||
{"number": 70, "author": {"login": "closedwithoutmerge", "is_bot": False}},
|
||||
]
|
||||
ISSUES = [
|
||||
{"number": 87, "author": {"login": "paperweightorder", "is_bot": False}},
|
||||
{"number": 85, "author": {"login": "72374", "is_bot": False}},
|
||||
{"number": 83, "author": {"login": "72374", "is_bot": False}},
|
||||
{"number": 32, "author": {"login": "Bappo0", "is_bot": False}},
|
||||
{"number": 31, "author": {"login": "ghost", "is_bot": False}},
|
||||
{"number": 30, "author": {"login": "habib256", "is_bot": False}},
|
||||
{"number": 29, "author": {"login": "Abdess", "is_bot": False}},
|
||||
]
|
||||
ISSUE_COMMENTS = "Abdess\nhelper\n72374\ngithub-actions[bot]\nAlpha\n"
|
||||
REVIEW_COMMENTS = "reviewer\nhabib256\n"
|
||||
|
||||
def fake(self, argv):
|
||||
self.calls.append(argv)
|
||||
if argv[:2] == ["git", "log"]:
|
||||
return "\n".join(self.TAGS) + "\n"
|
||||
if argv[:2] == ["git", "show"]:
|
||||
return json.dumps({"tag": self.TAGS[argv[2].split(":")[0]]})
|
||||
if argv[:2] == ["gh", "api"]:
|
||||
path = argv[3]
|
||||
return {"repos/Abdess/retrobios/commits": self.COMMIT_AUTHORS,
|
||||
"repos/Abdess/retrobios/issues/comments": self.ISSUE_COMMENTS,
|
||||
"repos/Abdess/retrobios/pulls/comments": self.REVIEW_COMMENTS}[path]
|
||||
if argv[:3] == ["gh", "pr", "list"]:
|
||||
return json.dumps(self.PULLS)
|
||||
if argv[:3] == ["gh", "issue", "list"]:
|
||||
return json.dumps(self.ISSUES)
|
||||
raise AssertionError(argv)
|
||||
|
||||
def setUp(self):
|
||||
self.calls = []
|
||||
|
||||
def test_the_base_is_the_previous_release_record(self):
|
||||
import release_notes
|
||||
|
||||
self.assertEqual(release_notes.previous_record_commit("v2026.11.10", self.fake), "c1")
|
||||
|
||||
def test_everyone_since_the_start_is_thanked_once(self):
|
||||
import release_notes
|
||||
|
||||
lines = release_notes.gather_thanks(self.fake)
|
||||
self.assertEqual(lines, [
|
||||
"- **Code and data**: @closedwithoutmerge, @dajiaohuang, @habib256 and @zed.",
|
||||
"- **Reports**: @72374 and @paperweightorder.",
|
||||
"- **Help in issues**: @Alpha, @helper and @reviewer.",
|
||||
])
|
||||
text = "\n".join(lines)
|
||||
for left_out in ("Abdess", "bot", "dependabot", "ghost", "Bappo0", "prakashmagat50"):
|
||||
self.assertNotIn(left_out, text)
|
||||
# Every state: a pull request closed without merge still counts.
|
||||
pulls = next(argv for argv in self.calls if argv[:3] == ["gh", "pr", "list"])
|
||||
self.assertEqual(pulls[pulls.index("--state") + 1], "all")
|
||||
issues = next(argv for argv in self.calls if argv[:3] == ["gh", "issue", "list"])
|
||||
self.assertEqual(issues[issues.index("--state") + 1], "all")
|
||||
|
||||
def test_the_notes_end_with_thanks_then_the_changelog(self):
|
||||
import release_notes
|
||||
|
||||
closing = release_notes.closing_lines(
|
||||
["- **Code and data**: @habib256."],
|
||||
release_notes.changelog_url("55eb95344" + "0" * 31, "v2026.11.10"))
|
||||
text = release_notes.render(TheReleaseNotesNameTheSetupsWithoutAZip.RECORD, PLATFORMS,
|
||||
"### What changed\n\n- x\n", closing)
|
||||
self.assertLess(text.index("### What changed"), text.index("### Thanks"))
|
||||
self.assertIn("### Thanks\n\n<details>\n"
|
||||
"<summary>Everyone who helped since the start</summary>\n\n"
|
||||
"- **Code and data**: @habib256.\n\n</details>\n\n**Full changelog**",
|
||||
text)
|
||||
self.assertEqual(release_notes.refused_words(text), [])
|
||||
self.assertTrue(text.rstrip().endswith(
|
||||
"**Full changelog**: https://github.com/Abdess/retrobios/compare/"
|
||||
"55eb95344...v2026.11.10"))
|
||||
|
||||
def test_a_checked_list_replaces_the_one_gh_gives(self):
|
||||
import release_notes
|
||||
|
||||
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
|
||||
tmp = Path(tmp)
|
||||
(tmp / "whats-new.md").write_text("### What changed\n\n- x\n", encoding="utf-8")
|
||||
(tmp / "thanks.md").write_text("- **Code and data**: @habib256.\n",
|
||||
encoding="utf-8")
|
||||
(tmp / "release.json").write_text(
|
||||
json.dumps(TheReleaseNotesNameTheSetupsWithoutAZip.RECORD), encoding="utf-8")
|
||||
argv = ["release_notes.py", "--record", str(tmp / "release.json"),
|
||||
"--whats-new", str(tmp / "whats-new.md"), "--thanks", str(tmp / "thanks.md"),
|
||||
"--platforms-dir", PLATFORMS, "--output", str(tmp / "notes.md")]
|
||||
with mock.patch.object(sys, "argv", argv), \
|
||||
mock.patch.object(release_notes, "_run", self.fake), \
|
||||
mock.patch.object(release_notes, "gather_thanks",
|
||||
side_effect=AssertionError("gh read")), \
|
||||
contextlib.redirect_stdout(io.StringIO()):
|
||||
self.assertEqual(release_notes.main(), 0)
|
||||
text = (tmp / "notes.md").read_text(encoding="utf-8")
|
||||
self.assertIn("- **Code and data**: @habib256.\n", text)
|
||||
self.assertIn("/compare/c4...v2026.10.24", text)
|
||||
|
||||
|
||||
class EveryPlatformHasAPermanentPage(unittest.TestCase):
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
"""The handheld launchers the site serves.
|
||||
|
||||
The four archives build_port.py writes carry install.py pinned by SHA-256,
|
||||
so they left the release (owner, 2026-11-10): the site builds them from its
|
||||
own commit, serves them under get/handheld/, and the get/ page of each
|
||||
system names the file, its size and hash, where it goes and which menu
|
||||
starts it.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
|
||||
|
||||
import contextlib
|
||||
import hashlib
|
||||
import re
|
||||
import shutil
|
||||
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 build_port # noqa: E402
|
||||
import common # noqa: E402
|
||||
import sitehandheld # noqa: E402
|
||||
|
||||
PLATFORMS = str(REPO_ROOT / "platforms")
|
||||
|
||||
|
||||
def _pages() -> dict[str, str]:
|
||||
"""Every page that carries a launcher, by site path."""
|
||||
import generate_site # noqa: PLC0415
|
||||
|
||||
with contextlib.chdir(REPO_ROOT):
|
||||
pages = {f"get/{key}.md": generate_site.generate_get_page(key)
|
||||
for key in sorted(set(sitehandheld.PLATFORM_OF.values()))}
|
||||
pages[f"get/{sitehandheld.GROUP_PAGE}.md"] = sitehandheld.group_page(REPO_ROOT)
|
||||
return pages
|
||||
|
||||
|
||||
class TheSiteServesTheLaunchers(unittest.TestCase):
|
||||
def setUp(self):
|
||||
scratch = REPO_ROOT / "tmp"
|
||||
scratch.mkdir(exist_ok=True)
|
||||
self.tmp = Path(tempfile.mkdtemp(dir=scratch, prefix="site-handheld-"))
|
||||
self.addCleanup(shutil.rmtree, self.tmp, True)
|
||||
|
||||
def test_the_written_archives_are_the_ones_build_port_writes(self):
|
||||
written = sitehandheld.write_launchers(self.tmp / "public", REPO_ROOT)
|
||||
self.assertEqual([path.name for path in written], list(build_port.ARCHIVES))
|
||||
for path in written:
|
||||
with self.subTest(archive=path.name):
|
||||
self.assertEqual(path.parent, self.tmp / "public" / "get" / "handheld")
|
||||
built = build_port.build_archive(path.name, self.tmp / "built" / path.name)
|
||||
self.assertEqual(path.read_bytes(), built.read_bytes())
|
||||
|
||||
def test_an_unchanged_archive_is_not_rewritten(self):
|
||||
first = sitehandheld.write_launchers(self.tmp / "public", REPO_ROOT)
|
||||
stamps = {path: path.stat().st_mtime_ns for path in first}
|
||||
sitehandheld.write_launchers(self.tmp / "public", REPO_ROOT)
|
||||
self.assertEqual({path: path.stat().st_mtime_ns for path in first}, stamps)
|
||||
|
||||
def test_a_stale_pin_stops_the_build(self):
|
||||
"""build_port refuses an install.py the bootstraps do not pin: served,
|
||||
that launcher would refuse its own installer."""
|
||||
with mock.patch.dict(sitehandheld._built, clear=True), \
|
||||
mock.patch.object(build_port, "pinned_installer_sha256", return_value="0" * 64):
|
||||
with self.assertRaisesRegex(ValueError, "re-pin the bootstraps"):
|
||||
sitehandheld.write_launchers(self.tmp / "public", REPO_ROOT)
|
||||
self.assertFalse(list((self.tmp / "public").rglob("RetroBIOS*")))
|
||||
|
||||
def test_every_archive_is_on_a_page_with_its_link_and_hash(self):
|
||||
public = self.tmp / "public"
|
||||
written = {path.name: path for path in sitehandheld.write_launchers(public, REPO_ROOT)}
|
||||
pages = _pages()
|
||||
for name in build_port.ARCHIVES:
|
||||
with self.subTest(archive=name):
|
||||
data = written[name].read_bytes()
|
||||
digest = hashlib.sha256(data).hexdigest()
|
||||
holding = [page for page, text in pages.items()
|
||||
if f'href="handheld/{name}"' in text]
|
||||
self.assertTrue(holding, f"no page links {name}")
|
||||
for page in holding:
|
||||
text = pages[page]
|
||||
# The link resolves to the file written under public/.
|
||||
target = (Path(page).parent / "handheld" / name).as_posix()
|
||||
self.assertTrue((public / target).is_file(), target)
|
||||
block = text.split(f'href="handheld/{name}"', 1)[1].split("\n\n", 2)[1]
|
||||
self.assertIn(f"SHA-256: `{digest}`", block)
|
||||
self.assertIn(sitehandheld._size(len(data)), block)
|
||||
self.assertRegex(block, r"- (Copy it to|Unzip it into) .+\.")
|
||||
self.assertRegex(block, r"- Start it from .+\.")
|
||||
|
||||
|
||||
class WhereEachSystemFindsItsFile(unittest.TestCase):
|
||||
def test_each_platform_page_is_a_registered_platform(self):
|
||||
registered = set(common.list_registered_platforms(PLATFORMS))
|
||||
self.assertLessEqual(set(sitehandheld.PLATFORM_OF.values()), registered)
|
||||
self.assertNotIn(sitehandheld.GROUP_PAGE, registered)
|
||||
|
||||
def test_the_group_page_sits_with_the_handheld_guide(self):
|
||||
"""It shares the guide's name, so the sidebar files it with it, and
|
||||
the guide a muOS or ArkOS owner lands on links it."""
|
||||
import generate_site # noqa: PLC0415
|
||||
|
||||
guide = generate_site.HANDHELD_GUIDE
|
||||
self.assertEqual(sitehandheld.GROUP_PAGE, guide.page)
|
||||
with contextlib.chdir(REPO_ROOT):
|
||||
self.assertIn(f"(../get/{sitehandheld.GROUP_PAGE}.md)",
|
||||
generate_site.generate_handheld_guide(guide))
|
||||
self.assertIn(f"]({sitehandheld.GROUP_PAGE}.md)", generate_site.generate_get_index())
|
||||
|
||||
def test_every_system_has_its_launchers_on_its_page(self):
|
||||
pages = _pages()
|
||||
for system in sitehandheld.systems():
|
||||
page = sitehandheld.page_of(system)
|
||||
with self.subTest(system=system):
|
||||
self.assertIn(page, pages)
|
||||
for launcher in sitehandheld.launchers_for(system):
|
||||
self.assertIn(f'href="handheld/{launcher.archive}"', pages[page])
|
||||
self.assertIn(launcher.folder_for(system), pages[page])
|
||||
self.assertIn(launcher.start, pages[page])
|
||||
for system in sitehandheld.group_systems():
|
||||
self.assertIn(f"\n## {system}\n", pages[f"get/{sitehandheld.GROUP_PAGE}.md"])
|
||||
|
||||
def test_the_installer_table_is_written_from_the_same_rows(self):
|
||||
text = (REPO_ROOT / "wiki" / "installer.md").read_text(encoding="utf-8")
|
||||
block = re.search(r"<!-- generated: handheld -->\n(.*?)<!-- /generated: handheld -->",
|
||||
text, re.S)
|
||||
self.assertIsNotNone(block)
|
||||
self.assertEqual(block.group(1).strip(), "\n".join(sitehandheld.table_rows()))
|
||||
self.assertNotIn("releases/latest", text.split("## On a handheld", 1)[1].split("\n## ")[0])
|
||||
|
||||
def test_the_installer_section_opens_on_the_downloads(self):
|
||||
"""The section was long, with no link to click (owner, 2026-11-10):
|
||||
it opens on one row per system, each file a link to its copy on the
|
||||
site, before the detail."""
|
||||
text = (REPO_ROOT / "wiki" / "installer.md").read_text(encoding="utf-8")
|
||||
section = text.split("## On a handheld", 1)[1].split("\n## ")[0]
|
||||
block = re.search(r"<!-- generated: handheld-downloads -->\n(.*?)"
|
||||
r"<!-- /generated: handheld-downloads -->", section, re.S)
|
||||
self.assertIsNotNone(block)
|
||||
self.assertEqual(block.group(1).strip(), "\n".join(sitehandheld.download_rows()))
|
||||
self.assertLess(block.start(), section.index("### Where each file goes"))
|
||||
self.assertLess(len(section[:block.start()].split()), 40)
|
||||
for system in sitehandheld.systems():
|
||||
with self.subTest(system=system):
|
||||
row = next(line for line in block.group(1).splitlines()
|
||||
if line.startswith(f"| {system} |"))
|
||||
for launcher in sitehandheld.launchers_for(system):
|
||||
self.assertIn(f"](../{sitehandheld.SERVED_DIR}/{launcher.archive})", row)
|
||||
self.assertIn(f"](../{sitehandheld.page_of(system)}#", row)
|
||||
for name in build_port.ARCHIVES:
|
||||
self.assertIn(f"](../{sitehandheld.SERVED_DIR}/{name})", block.group(1))
|
||||
|
||||
def test_the_generator_writes_them(self):
|
||||
source = (REPO_ROOT / "scripts" / "generate_site.py").read_text(encoding="utf-8")
|
||||
self.assertIn("sitehandheld.write_launchers(public, _REPO_ROOT)", source)
|
||||
self.assertIn("sitehandheld.platform_block(platform_name, _REPO_ROOT)", source)
|
||||
self.assertIn("sitehandheld.group_page(_REPO_ROOT)", source)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+21
-1
@@ -33,6 +33,7 @@ from __future__ import annotations
|
||||
|
||||
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
|
||||
|
||||
import fnmatch
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
@@ -48,6 +49,7 @@ sys.path.insert(0, str(REPO_ROOT))
|
||||
import sitediagrams # noqa: E402
|
||||
from siteguides import INSTALL_SH # noqa: E402
|
||||
from tests import sitepages # noqa: E402
|
||||
import build_port # noqa: E402
|
||||
from check_release import SUMS, Asset, compare_release # noqa: E402
|
||||
|
||||
|
||||
@@ -870,15 +872,33 @@ class PinnedInstaller(unittest.TestCase):
|
||||
kinds = {(f.kind, f.name) for f in compare_release(record, sums, assets, "v1")}
|
||||
self.assertEqual(kinds, {("unrecorded", "install.py"), ("unrecorded", "retroarch.json")})
|
||||
|
||||
def test_a_launcher_attached_to_the_release_is_refused(self):
|
||||
"""The handheld launchers carry install.py: the site serves them
|
||||
from its own commit, the release never does."""
|
||||
record = {"tag": "v1", "packs": {"P.zip": {"download_size": 5, "assets": ["P.zip"]}}}
|
||||
sums = _sums_with(["P.zip", *build_port.ARCHIVES])
|
||||
assets = {name: Asset(5, digest) for name, digest in sums.items()}
|
||||
assets[SUMS] = Asset(1, None)
|
||||
kinds = {(f.kind, f.name) for f in compare_release(record, sums, assets, "v1")}
|
||||
self.assertEqual(kinds, {("unrecorded", name) for name in build_port.ARCHIVES})
|
||||
|
||||
def test_the_release_steps_ship_none(self):
|
||||
text = _wiki("release-process.md")
|
||||
self.assertNotIn("cp install.py", text)
|
||||
sums = re.search(r"sha256sum [^>]+> SHA256SUMS.txt", text, re.S).group(0)
|
||||
upload = re.search(r"for f in dist/SHA256SUMS.txt.*?; do", text, re.S).group(0)
|
||||
for name in ("install.py", "install.sh", "install.ps1", ".json"):
|
||||
for name in ("install.py", "install.sh", "install.ps1", ".json", "RetroBIOS",
|
||||
".muxapp", "build_port", " *.zip", "/*.zip"):
|
||||
with self.subTest(name=name):
|
||||
self.assertNotIn(name, sums)
|
||||
self.assertNotIn(name, upload)
|
||||
# A launcher built into dist/ is never caught by the glob either.
|
||||
for archive in build_port.ARCHIVES:
|
||||
with self.subTest(archive=archive):
|
||||
self.assertFalse(fnmatch.fnmatch(archive, "*_BIOS_Pack*.zip"))
|
||||
self.assertIn("*_BIOS_Pack*.zip", sums)
|
||||
self.assertIn("*_BIOS_Pack*.zip", upload)
|
||||
self.assertNotIn("scripts/build_port.py", text)
|
||||
|
||||
def test_the_installer_page_pins_one_commit(self):
|
||||
# v2026.10.10 carries no install.py: until a release does, the
|
||||
|
||||
@@ -278,7 +278,7 @@ class ReleaseProcessPublishesArchives(unittest.TestCase):
|
||||
def test_the_checksums_are_those_of_the_published_files(self):
|
||||
self.assertLess(
|
||||
self.text.index("scripts/split_pack.py"),
|
||||
self.text.index("sha256sum *.zip"),
|
||||
self.text.index("sha256sum *_BIOS_Pack*.zip"),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user