Offer exact latest bootloader files only for selected nRF52 hardware

This commit is contained in:
mikecarper
2026-09-29 17:00:19 -07:00
parent af82010752
commit aeccd3b692
8 changed files with 948 additions and 23 deletions
+4 -2
View File
@@ -8,7 +8,7 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def package(releases, controls):
def package(releases, controls, bootloaders=None):
if not any(r['tag_name'] == controls['familyTag'] for r in releases):
raise ValueError('Controls must match the supplied release family')
# Retain only data used by the picker; never embed authentication or API metadata.
@@ -21,7 +21,9 @@ def package(releases, controls):
markdown = (ROOT / 'docs/firmware_picker.md').read_text()
form = markdown[markdown.index('<div class="firmware-picker"'):markdown.index('\n## What the choices mean')]
form = form.replace('Loading release information...', 'Loading embedded release information...')
payload = json.dumps({'releases': compact, 'controls': controls}).replace('<', '\\u003c')
if bootloaders is None:
bootloaders = json.loads((ROOT / 'docs/_data/bootloader_manifest.json').read_text(encoding='ascii'))
payload = json.dumps({'releases': compact, 'controls': controls, 'bootloaders': bootloaders}).replace('<', '\\u003c')
css = (ROOT / 'docs/_stylesheets/firmware_picker.css').read_text()
js = (ROOT / 'docs/_javascript/firmware_picker.js').read_text()
title = html.escape('MeshCore firmware picker - ' + controls['familyTag'])
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
"""Refresh the web/offline picker snapshot from the published OTAFIX manifest."""
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import tempfile
REPO = "mikecarper/Adafruit_nRF52_Bootloader_OTAFIX"
ROOT = Path(__file__).resolve().parents[1]
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--output", type=Path, default=ROOT / "docs/_data/bootloader_manifest.json")
args = parser.parse_args()
release = json.loads(subprocess.check_output(["gh", "api", f"repos/{REPO}/releases/latest"]))
assets = [asset for asset in release["assets"] if asset["name"] == "bootloader-manifest.json"]
if len(assets) != 1 or release.get("draft") or release.get("prerelease"):
raise ValueError("latest stable bootloader release has no unique download manifest")
with tempfile.TemporaryDirectory(prefix="otafix-picker-") as directory:
subprocess.run(["gh", "release", "download", release["tag_name"], "--repo", REPO,
"--pattern", "bootloader-manifest.json", "--dir", directory], check=True)
data = (Path(directory) / "bootloader-manifest.json").read_bytes()
if assets[0].get("digest") != "sha256:" + hashlib.sha256(data).hexdigest():
raise ValueError("bootloader download manifest checksum mismatch")
manifest = json.loads(data.decode("ascii"))
if (manifest.get("schemaVersion") != 1 or manifest.get("repository") != REPO or
manifest.get("tag") != release["tag_name"] or
manifest.get("releaseUrl") != release["html_url"] or manifest.get("prerelease")):
raise ValueError("bootloader download manifest does not match the latest stable release")
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_bytes(data)
print(f"Synced OTAFIX {manifest['version']} ({len(manifest['profiles'])} bootloader profiles)")
if __name__ == "__main__":
main()