mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-13 21:43:55 -06:00
docs: keep the release page to packs and launchers
The release carries the packs, the handheld launchers and the signed checksum list. The installer and the file lists are pinned from the tag (installer page, For packagers), and check_release.py now refuses them as unrecorded files. The notes link each pack's files on the release itself, in a beginner's page: one idea per line. The handheld section links the latest release.
This commit is contained in:
1 parent
96ef06b9fa
commit
12daa6698f
7 files changed
+72
-101
No files matched your search
@@ -7,9 +7,9 @@ SHA256SUMS.txt lists for it, as must each handheld launcher (RetroBIOS.zip
|
|||||||
and the others build_port.py writes) the list names, the parts of a pack must add up to the download
|
and the others build_port.py writes) the list names, the parts of a pack must add up to the download
|
||||||
size the README prints, and nothing else may be attached. The record holds
|
size the README prints, and nothing else may be attached. The record holds
|
||||||
one pack for each platform the registry marks release_pack, and no other
|
one pack for each platform the registry marks release_pack, and no other
|
||||||
pack. The installer (install.py, install.sh, install.ps1) and every file
|
pack. The installer and the file lists are not release files: a package pins
|
||||||
list of install/ are listed and attached too, so a package can pin one
|
them from the tag, so a reader of the release page sees the packs and nothing
|
||||||
release. An upload that
|
to puzzle over. An upload that
|
||||||
failed in the loop, or a part re-uploaded from an older build, otherwise
|
failed in the loop, or a part re-uploaded from an older build, otherwise
|
||||||
publishes a release that `sha256sum --check` rejects for every user.
|
publishes a release that `sha256sum --check` rejects for every user.
|
||||||
|
|
||||||
@@ -39,14 +39,6 @@ from release_record import RECORD, load_record
|
|||||||
|
|
||||||
SUMS = "SHA256SUMS.txt"
|
SUMS = "SHA256SUMS.txt"
|
||||||
SIGNATURE = SUMS + ".sig"
|
SIGNATURE = SUMS + ".sig"
|
||||||
INSTALLER = ("install.py", "install.sh", "install.ps1")
|
|
||||||
|
|
||||||
|
|
||||||
def installer_files(install_dir: str | Path = "install") -> list[str]:
|
|
||||||
"""The release files a package pins: the installer and each file list."""
|
|
||||||
return [*INSTALLER, *sorted(p.name for p in Path(install_dir).glob("*.json"))]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Asset:
|
class Asset:
|
||||||
size: int
|
size: int
|
||||||
@@ -81,7 +73,6 @@ def compare_release(
|
|||||||
tag: str,
|
tag: str,
|
||||||
local_files: dict[str, str] | None = None,
|
local_files: dict[str, str] | None = None,
|
||||||
released: set[str] | None = None,
|
released: set[str] | None = None,
|
||||||
installer: list[str] | None = None,
|
|
||||||
) -> list[Finding]:
|
) -> list[Finding]:
|
||||||
"""Every way the release can differ from what was built.
|
"""Every way the release can differ from what was built.
|
||||||
|
|
||||||
@@ -89,7 +80,6 @@ def compare_release(
|
|||||||
signature) to its local sha256: the copy on the release must be that one.
|
signature) to its local sha256: the copy on the release must be that one.
|
||||||
*released* names the platforms the registry marks release_pack: each one
|
*released* names the platforms the registry marks release_pack: each one
|
||||||
has a recorded pack, and no recorded pack serves only other platforms.
|
has a recorded pack, and no recorded pack serves only other platforms.
|
||||||
*installer* names the installer files each release lists and carries.
|
|
||||||
"""
|
"""
|
||||||
findings: list[Finding] = []
|
findings: list[Finding] = []
|
||||||
if record.get("tag") != tag:
|
if record.get("tag") != tag:
|
||||||
@@ -122,11 +112,9 @@ def compare_release(
|
|||||||
findings.append(Finding("extra", name, "attached but neither recorded nor listed"))
|
findings.append(Finding("extra", name, "attached but neither recorded nor listed"))
|
||||||
for name in sorted(set(recorded) - set(sums)):
|
for name in sorted(set(recorded) - set(sums)):
|
||||||
findings.append(Finding("unlisted", name, f"absent from {SUMS}"))
|
findings.append(Finding("unlisted", name, f"absent from {SUMS}"))
|
||||||
for name in sorted(set(installer or ()) - set(sums)):
|
|
||||||
findings.append(Finding("no-installer", name, f"absent from {SUMS}"))
|
|
||||||
# The handheld launchers are release files but no packs: release.json
|
# The handheld launchers are release files but no packs: release.json
|
||||||
# records packs, and the checksum list alone vouches for the launchers.
|
# records packs, and the checksum list alone vouches for the launchers.
|
||||||
for name in sorted(set(sums) - set(recorded) - set(ARCHIVES) - set(installer or ())):
|
for name in sorted(set(sums) - set(recorded) - set(ARCHIVES)):
|
||||||
findings.append(Finding("unrecorded", name, f"listed in {SUMS}, absent from release.json"))
|
findings.append(Finding("unrecorded", name, f"listed in {SUMS}, absent from release.json"))
|
||||||
|
|
||||||
wanted = {**sums, **(local_files or {})}
|
wanted = {**sums, **(local_files or {})}
|
||||||
@@ -202,10 +190,6 @@ def main() -> int:
|
|||||||
"--platforms-dir", default="platforms",
|
"--platforms-dir", default="platforms",
|
||||||
help="registry whose release_pack platforms each need a pack (default: %(default)s)",
|
help="registry whose release_pack platforms each need a pack (default: %(default)s)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--install-dir", default="install",
|
|
||||||
help="file lists the release must carry beside the installer (default: %(default)s)",
|
|
||||||
)
|
|
||||||
parser.add_argument("--json", action="store_true", help="JSON output")
|
parser.add_argument("--json", action="store_true", help="JSON output")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
require_directory(args.platforms_dir, "--platforms-dir")
|
require_directory(args.platforms_dir, "--platforms-dir")
|
||||||
@@ -240,8 +224,7 @@ def main() -> int:
|
|||||||
return 2
|
return 2
|
||||||
|
|
||||||
released = set(list_release_pack_platforms(args.platforms_dir))
|
released = set(list_release_pack_platforms(args.platforms_dir))
|
||||||
findings = compare_release(record, sums, assets, tag, local_files, released,
|
findings = compare_release(record, sums, assets, tag, local_files, released)
|
||||||
installer_files(args.install_dir))
|
|
||||||
if args.json:
|
if args.json:
|
||||||
print(json.dumps(
|
print(json.dumps(
|
||||||
{"tag": tag, "draft": draft, "assets": len(assets),
|
{"tag": tag, "draft": draft, "assets": len(assets),
|
||||||
|
|||||||
+33
-27
@@ -4,9 +4,10 @@
|
|||||||
The notes carried the pack table, typed by hand from figures release.json
|
The notes carried the pack table, typed by hand from figures release.json
|
||||||
already held: a copied cell or an old collection total at the top is how
|
already held: a copied cell or an old collection total at the top is how
|
||||||
issue 81 happened. Install commands, the parts sentence and the table come
|
issue 81 happened. Install commands, the parts sentence and the table come
|
||||||
from the record and the registry. Each row links the platform's page under
|
from the record and the registry. Each row links the files of this release,
|
||||||
get/ on the site, which outlives the release, and the setups the registry
|
which sit right below the notes, and the setups the registry does not mark
|
||||||
does not mark release_pack are named with the command. The maintainer writes
|
release_pack are named with the command. The text is a beginner's page: one
|
||||||
|
idea per line, plain words (owner, 2026-11-10). The maintainer writes
|
||||||
what changed, and that text is appended as given once it holds none of the
|
what changed, and that text is appended as given once it holds none of the
|
||||||
REFUSED phrases.
|
REFUSED phrases.
|
||||||
|
|
||||||
@@ -84,9 +85,8 @@ def no_pack_paragraph(platforms_dir: str) -> list[str]:
|
|||||||
return []
|
return []
|
||||||
listed = ", ".join(names[:-1]) + f" and {names[-1]}" if len(names) > 1 else names[0]
|
listed = ", ".join(names[:-1]) + f" and {names[-1]}" if len(names) > 1 else names[0]
|
||||||
return [
|
return [
|
||||||
(f"No ZIP for {listed}. ZIPs are made for the setups most people download."
|
(f"No ZIP for {listed}. The command above installs them."
|
||||||
" The command above installs every file for these setups and checks each one."
|
" Add `--dry-run` to see what it would do."),
|
||||||
" Add `--dry-run` to see what it would install."),
|
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -96,11 +96,13 @@ def _match_key(value: str) -> str:
|
|||||||
return re.sub(r"[^a-z0-9]", "", value.lower())
|
return re.sub(r"[^a-z0-9]", "", value.lower())
|
||||||
|
|
||||||
|
|
||||||
def _link(name: str, pack: dict) -> str:
|
def _link(pack: dict, tag: str) -> str:
|
||||||
"""The pack's permanent page, which lists the files of the current release."""
|
"""The pack's files on this release, one link per part."""
|
||||||
parts = len(pack["assets"])
|
base = f"https://github.com/{REPO}/releases/download/{tag}"
|
||||||
label = "Download" if parts == 1 else f"Download, {parts} parts"
|
assets = pack["assets"]
|
||||||
return f"[{label}]({release_record.get_page(_owner(name, pack), SITE)})"
|
if len(assets) == 1:
|
||||||
|
return f"[Download]({base}/{assets[0]})"
|
||||||
|
return ", ".join(f"[part {i}]({base}/{name})" for i, name in enumerate(assets, 1))
|
||||||
|
|
||||||
|
|
||||||
# Words the published notes of v2026.10.10 carried by hand: "never from a
|
# Words the published notes of v2026.10.10 carried by hand: "never from a
|
||||||
@@ -120,11 +122,11 @@ def refused_words(text: str) -> list[str]:
|
|||||||
def render(record: dict, platforms_dir: str, whats_new: str) -> str:
|
def render(record: dict, platforms_dir: str, whats_new: str) -> str:
|
||||||
packs = record.get("packs", {})
|
packs = record.get("packs", {})
|
||||||
folders = _extract_folders(record, platforms_dir)
|
folders = _extract_folders(record, platforms_dir)
|
||||||
|
tag = str(record.get("tag", ""))
|
||||||
lines = [
|
lines = [
|
||||||
"### Install in one command",
|
"### Install in one command",
|
||||||
"",
|
"",
|
||||||
("The installer detects the platform and its BIOS folder, downloads only"
|
"It finds your setup and its BIOS folder, then downloads only what is missing.",
|
||||||
" what is missing and checks every file. Running it again is safe."),
|
|
||||||
"",
|
"",
|
||||||
"**Linux, macOS, Steam Deck**",
|
"**Linux, macOS, Steam Deck**",
|
||||||
"```sh",
|
"```sh",
|
||||||
@@ -136,35 +138,39 @@ def render(record: dict, platforms_dir: str, whats_new: str) -> str:
|
|||||||
install_command("powershell"),
|
install_command("powershell"),
|
||||||
"```",
|
"```",
|
||||||
"",
|
"",
|
||||||
"### Download a pack",
|
(f"**On a handheld**: copy the `RetroBIOS` file for your system to the card"
|
||||||
|
f" ([which one]({SITE}wiki/installer/#on-a-handheld-the-retrobios-port))."),
|
||||||
"",
|
"",
|
||||||
("One complete pack for each platform below: the BIOS list the platform"
|
"### Or download a pack",
|
||||||
" publishes plus the files its emulators open. Files no pack carries yet"
|
"",
|
||||||
f" are listed in the [gap analysis]({SITE}gaps/). Each link is a page"
|
"Extract it into your BIOS folder.",
|
||||||
" that keeps its address from one release to the next. Files is what the pack"
|
|
||||||
" holds once extracted, the count a file manager shows. Extracted size"
|
|
||||||
" is the space those files take, and the download is smaller."),
|
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
if any(len(pack["assets"]) > 1 for pack in packs.values()):
|
if any(len(pack["assets"]) > 1 for pack in packs.values()):
|
||||||
lines += [
|
lines += [
|
||||||
("A pack over 2 GB comes as parts that are each an ordinary ZIP of whole"
|
("A pack in parts: each part is an ordinary ZIP. Extract every part into"
|
||||||
" files (`Pack.part1of2.zip`, `Pack.part2of2.zip`). Download every part"
|
" the same folder. Nothing needs joining."),
|
||||||
" and extract them all into the same folder. Nothing needs joining."),
|
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
lines += [
|
lines += [
|
||||||
"| Platform | Download | Extracted size | Files | Extract to |",
|
"| Platform | Download | Size | Files | Extract to |",
|
||||||
"|----------|----------|---------------:|------:|-----------|",
|
"|----------|----------|-----:|------:|-----------|",
|
||||||
]
|
]
|
||||||
for name, pack in sorted(packs.items(), key=lambda item: -item[1]["extracted_size"]):
|
for name, pack in sorted(packs.items(), key=lambda item: -item[1]["extracted_size"]):
|
||||||
folder = folders.get(name)
|
folder = folders.get(name)
|
||||||
lines.append(
|
lines.append(
|
||||||
f"| {_display(name)} | {_link(name, pack)} |"
|
f"| {_display(name)} | {_link(pack, tag)} |"
|
||||||
f" {_size(pack['extracted_size'])} | {pack['files']:,} |"
|
f" {_size(pack['extracted_size'])} | {pack['files']:,} |"
|
||||||
f" {f'`{folder}`' if folder else '-'} |"
|
f" {f'`{folder}`' if folder else '-'} |"
|
||||||
)
|
)
|
||||||
lines += ["", *no_pack_paragraph(platforms_dir), whats_new.strip(), ""]
|
lines += [
|
||||||
|
"",
|
||||||
|
f"Files no pack holds yet: [gap analysis]({SITE}gaps/).",
|
||||||
|
"",
|
||||||
|
*no_pack_paragraph(platforms_dir),
|
||||||
|
whats_new.strip(),
|
||||||
|
"",
|
||||||
|
]
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -594,10 +594,12 @@ class TheReleaseNotesReadTheRecord(unittest.TestCase):
|
|||||||
text = self.render()
|
text = self.render()
|
||||||
row = next(line for line in text.splitlines() if line.startswith("| RetroArch"))
|
row = next(line for line in text.splitlines() if line.startswith("| RetroArch"))
|
||||||
self.assertIn("8,504", row)
|
self.assertIn("8,504", row)
|
||||||
self.assertIn("[Download, 2 parts](https://abdess.github.io/retrobios/get/retroarch/)", row)
|
base = "https://github.com/Abdess/retrobios/releases/download/v2026.10.10/"
|
||||||
self.assertNotIn("/releases/download/", row)
|
self.assertIn(f"[part 1]({base}RetroArch_Lakka_v1.22.2_BIOS_Pack.part1of2.zip)", row)
|
||||||
|
self.assertIn(f"[part 2]({base}RetroArch_Lakka_v1.22.2_BIOS_Pack.part2of2.zip)", row)
|
||||||
|
self.assertNotIn("retrobios/get/", row)
|
||||||
self.assertIn("`system/`", row)
|
self.assertIn("`system/`", row)
|
||||||
self.assertIn("| Platform | Download | Extracted size | Files |", text)
|
self.assertIn("| Platform | Download | Size | Files |", text)
|
||||||
|
|
||||||
def test_the_parts_sentence_sits_above_the_table_only_when_needed(self):
|
def test_the_parts_sentence_sits_above_the_table_only_when_needed(self):
|
||||||
text = self.render()
|
text = self.render()
|
||||||
|
|||||||
@@ -322,12 +322,16 @@ class TheReleaseNotesNameTheSetupsWithoutAZip(unittest.TestCase):
|
|||||||
self.assertIn("--dry-run", paragraph)
|
self.assertIn("--dry-run", paragraph)
|
||||||
self.assertLess(text.index(paragraph), text.index("### What changed"))
|
self.assertLess(text.index(paragraph), text.index("### What changed"))
|
||||||
|
|
||||||
def test_the_rows_link_get_pages(self):
|
def test_the_rows_link_this_release_files(self):
|
||||||
|
"""The files sit right below the notes: a row sends nobody to the
|
||||||
|
site to find them (owner, 2026-11-10)."""
|
||||||
import release_notes
|
import release_notes
|
||||||
|
|
||||||
text = release_notes.render(self.RECORD, PLATFORMS, "x")
|
text = release_notes.render(self.RECORD, PLATFORMS, "x")
|
||||||
self.assertIn(f"[Download]({SITE}get/romm/)", text)
|
self.assertIn(
|
||||||
self.assertNotIn("/releases/download/", text)
|
"[Download](https://github.com/Abdess/retrobios/releases/download/"
|
||||||
|
"v2026.10.24/RomM_5_BIOS_Pack.zip)", text)
|
||||||
|
self.assertNotIn(f"{SITE}get/", text)
|
||||||
|
|
||||||
|
|
||||||
class EveryPlatformHasAPermanentPage(unittest.TestCase):
|
class EveryPlatformHasAPermanentPage(unittest.TestCase):
|
||||||
|
|||||||
+13
-35
@@ -48,7 +48,7 @@ sys.path.insert(0, str(REPO_ROOT))
|
|||||||
import sitediagrams # noqa: E402
|
import sitediagrams # noqa: E402
|
||||||
from siteguides import INSTALL_SH # noqa: E402
|
from siteguides import INSTALL_SH # noqa: E402
|
||||||
from tests import sitepages # noqa: E402
|
from tests import sitepages # noqa: E402
|
||||||
from check_release import INSTALLER, SUMS, Asset, compare_release, installer_files # noqa: E402
|
from check_release import SUMS, Asset, compare_release # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
WIKI = REPO_ROOT / "wiki"
|
WIKI = REPO_ROOT / "wiki"
|
||||||
@@ -858,49 +858,27 @@ def _sums_with(names: list[str]) -> dict[str, str]:
|
|||||||
|
|
||||||
|
|
||||||
class PinnedInstaller(unittest.TestCase):
|
class PinnedInstaller(unittest.TestCase):
|
||||||
"""J9, D5: release tags are deleted and the release carried no installer."""
|
"""The release page carries the packs a beginner picks from, and no
|
||||||
|
installer or file list: a package pins those from the tag (owner,
|
||||||
|
2026-11-10, "dans release on met le minimum sans bruit")."""
|
||||||
|
|
||||||
def test_the_list_holds_the_installer_and_every_file_list(self):
|
def test_an_installer_attached_to_the_release_is_refused(self):
|
||||||
names = installer_files(REPO_ROOT / "install")
|
|
||||||
self.assertEqual(names[:3], list(INSTALLER))
|
|
||||||
self.assertIn("retroarch.json", names)
|
|
||||||
self.assertEqual(len(names), 3 + len(list((REPO_ROOT / "install").glob("*.json"))))
|
|
||||||
|
|
||||||
def test_a_release_without_the_installer_is_refused(self):
|
|
||||||
record = {"tag": "v1", "packs": {"P.zip": {"download_size": 5, "assets": ["P.zip"]}}}
|
record = {"tag": "v1", "packs": {"P.zip": {"download_size": 5, "assets": ["P.zip"]}}}
|
||||||
files = ["install.py", "install.sh", "install.ps1", "retroarch.json"]
|
sums = _sums_with(["P.zip", "install.py", "retroarch.json"])
|
||||||
sums = _sums_with(["P.zip", *files])
|
|
||||||
assets = {name: Asset(5, digest) for name, digest in sums.items()}
|
assets = {name: Asset(5, digest) for name, digest in sums.items()}
|
||||||
assets[SUMS] = Asset(1, None)
|
assets[SUMS] = Asset(1, None)
|
||||||
self.assertEqual(compare_release(record, sums, assets, "v1", installer=files), [])
|
kinds = {(f.kind, f.name) for f in compare_release(record, sums, assets, "v1")}
|
||||||
|
self.assertEqual(kinds, {("unrecorded", "install.py"), ("unrecorded", "retroarch.json")})
|
||||||
|
|
||||||
del sums["install.py"]
|
def test_the_release_steps_ship_none(self):
|
||||||
del assets["install.py"]
|
|
||||||
kinds = {(f.kind, f.name) for f in compare_release(record, sums, assets, "v1",
|
|
||||||
installer=files)}
|
|
||||||
self.assertEqual(kinds, {("no-installer", "install.py")})
|
|
||||||
|
|
||||||
def test_listed_but_not_uploaded_is_missing(self):
|
|
||||||
record = {"tag": "v1", "packs": {}}
|
|
||||||
sums = _sums_with(list(INSTALLER))
|
|
||||||
assets = {name: Asset(5, digest) for name, digest in sums.items() if name != "install.sh"}
|
|
||||||
assets[SUMS] = Asset(1, None)
|
|
||||||
kinds = {(f.kind, f.name) for f in compare_release(record, sums, assets, "v1",
|
|
||||||
installer=list(INSTALLER))}
|
|
||||||
self.assertEqual(kinds, {("missing", "install.sh")})
|
|
||||||
|
|
||||||
def test_the_release_steps_ship_them(self):
|
|
||||||
text = _wiki("release-process.md")
|
text = _wiki("release-process.md")
|
||||||
self.assertIn("cp install.py install.sh install.ps1 install/*.json dist/", text)
|
self.assertNotIn("cp install.py", text)
|
||||||
sums = re.search(r"sha256sum [^>]+> SHA256SUMS.txt", text, re.S).group(0)
|
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)
|
upload = re.search(r"for f in dist/SHA256SUMS.txt.*?; do", text, re.S).group(0)
|
||||||
for name in (*INSTALLER, "*.json"):
|
for name in ("install.py", "install.sh", "install.ps1", ".json"):
|
||||||
with self.subTest(name=name):
|
with self.subTest(name=name):
|
||||||
self.assertIn(name, sums)
|
self.assertNotIn(name, sums)
|
||||||
for name in INSTALLER:
|
self.assertNotIn(name, upload)
|
||||||
with self.subTest(upload=name):
|
|
||||||
self.assertIn(f"dist/{name}", upload)
|
|
||||||
self.assertIn("install/*.json", upload)
|
|
||||||
|
|
||||||
def test_the_installer_page_pins_one_commit(self):
|
def test_the_installer_page_pins_one_commit(self):
|
||||||
# v2026.10.10 carries no install.py: until a release does, the
|
# v2026.10.10 carries no install.py: until a release does, the
|
||||||
|
|||||||
+2
-3
@@ -1506,9 +1506,8 @@ RetroBIOS also runs on the handheld itself, in the
|
|||||||
Copy the file for the system to the SD card, then start RetroBIOS from the
|
Copy the file for the system to the SD card, then start RetroBIOS from the
|
||||||
menu.
|
menu.
|
||||||
|
|
||||||
The files below ship with the next release. Until then, build them from a
|
Download the file for your system from the
|
||||||
clone of the repository with `python scripts/build_port.py`, which writes all
|
[latest release](https://github.com/Abdess/retrobios/releases/latest).
|
||||||
four into `dist/`, or use the computer route at the end of this section.
|
|
||||||
|
|
||||||
| System | File | Copy it to | Start it from |
|
| System | File | Copy it to | Start it from |
|
||||||
|--------|------|------------|---------------|
|
|--------|------|------------|---------------|
|
||||||
|
|||||||
@@ -256,17 +256,17 @@ python scripts/split_pack.py dist/
|
|||||||
# check_release.py compares each asset with its line there.
|
# check_release.py compares each asset with its line there.
|
||||||
python scripts/build_port.py
|
python scripts/build_port.py
|
||||||
|
|
||||||
# 2c. The installer and the file lists step 1 wrote, so a package can pin
|
# 2c. The release carries the packs, the handheld launchers and the signed
|
||||||
# one release (installer page, "For packagers"). check_release.py
|
# checksum list, and nothing else: a beginner reads that page to pick one
|
||||||
# refuses a release that lacks one of them.
|
# file. A package pins install.py and its file list from the tag
|
||||||
cp install.py install.sh install.ps1 install/*.json dist/
|
# (installer page, "For packagers"), and check_release.py refuses an
|
||||||
|
# installer or a file list attached to the release.
|
||||||
|
|
||||||
# 3. Checksums of the files as published, then sign the list. The checksums
|
# 3. Checksums of the files as published, then sign the list. The checksums
|
||||||
# answer corruption, and the signature answers a rewritten release, which is
|
# answer corruption, and the signature answers a rewritten release, which is
|
||||||
# the one thing a checksum published beside its own artifacts cannot
|
# the one thing a checksum published beside its own artifacts cannot
|
||||||
# answer.
|
# answer.
|
||||||
(cd dist && sha256sum *.zip RetroBIOS.muxapp install.py install.sh install.ps1 \
|
(cd dist && sha256sum *.zip RetroBIOS.muxapp > SHA256SUMS.txt)
|
||||||
$(cd ../install && ls *.json) > SHA256SUMS.txt)
|
|
||||||
ssh-keygen -Y sign -f ~/.ssh/retrobios_signing -n file dist/SHA256SUMS.txt
|
ssh-keygen -Y sign -f ~/.ssh/retrobios_signing -n file dist/SHA256SUMS.txt
|
||||||
|
|
||||||
# 4. Record what each pack holds, read from the archives just checked:
|
# 4. Record what each pack holds, read from the archives just checked:
|
||||||
@@ -291,8 +291,7 @@ python scripts/release_notes.py --whats-new tmp/whats-new.md --output tmp/notes.
|
|||||||
# A public release with half its assets is a broken download for everyone
|
# A public release with half its assets is a broken download for everyone
|
||||||
# during the whole upload.
|
# during the whole upload.
|
||||||
gh release create "v${DATE}" --draft --title "BIOS Pack v${DATE}" --notes-file tmp/notes.md
|
gh release create "v${DATE}" --draft --title "BIOS Pack v${DATE}" --notes-file tmp/notes.md
|
||||||
for f in dist/SHA256SUMS.txt dist/SHA256SUMS.txt.sig dist/*.zip dist/RetroBIOS.muxapp \
|
for f in dist/SHA256SUMS.txt dist/SHA256SUMS.txt.sig dist/*.zip dist/RetroBIOS.muxapp; do
|
||||||
dist/install.py dist/install.sh dist/install.ps1 $(ls install/*.json | sed 's|^install/|dist/|'); do
|
|
||||||
[ -f "$f" ] && gh release upload "v${DATE}" "$f#$(basename "$f")" --clobber
|
[ -f "$f" ] && gh release upload "v${DATE}" "$f#$(basename "$f")" --clobber
|
||||||
done
|
done
|
||||||
# A count does not see a failed upload beside a stray file, nor a part
|
# A count does not see a failed upload beside a stray file, nor a part
|
||||||
|
|||||||
Reference in new issue
Block a user