Files
archy/scripts/check-release-source-binding.py

58 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Read-only release metadata check against an explicitly reviewed source ref.
This does not sign, generate, publish, build or validate artifact bytes. Signature,
artifact provenance, mirror parity and operator acceptance gates remain mandatory.
"""
import argparse
import json
from pathlib import Path
import re
import subprocess
import tomllib
from urllib.parse import unquote, urlsplit
def validate(manifest, commit, backend_version, frontend_version):
version = manifest.get('version')
if not isinstance(version, str) or not re.fullmatch(r'\d+\.\d+\.\d+(?:-[A-Za-z0-9.]+)?', version):
raise ValueError('invalid release version')
if version != backend_version or version != frontend_version:
raise ValueError('manifest/backend/frontend versions differ from reviewed source')
if manifest.get('source_commit') != commit:
raise ValueError('manifest source_commit differs from reviewed source')
components = manifest.get('components')
if not isinstance(components, list) or not components:
raise ValueError('release has no components')
for component in components:
if component.get('new_version') != version:
raise ValueError('component version differs from reviewed release')
url = urlsplit(component.get('download_url', ''))
parts = unquote(url.path).split('/')
if (url.scheme != 'https' or not url.netloc or url.query or url.fragment
or len(parts) < 5 or parts[-4:-1] != ['releases', 'download', 'v' + version]
or not parts[-1] or parts[-1] in ('.', '..')):
raise ValueError('component URL does not bind the reviewed release version over HTTPS')
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('manifest', type=Path)
parser.add_argument('--source-ref', required=True, help='explicit reviewed full commit or tag')
args = parser.parse_args()
root = Path(__file__).resolve().parents[1]
def git(*arguments):
return subprocess.check_output(['git', '-C', str(root), *arguments], text=True).strip()
commit = git('rev-parse', '--verify', args.source_ref + '^{commit}')
backend = tomllib.loads(git('show', commit + ':core/archipelago/Cargo.toml'))['package']['version']
frontend = json.loads(git('show', commit + ':neode-ui/package.json'))['version']
validate(json.loads(args.manifest.read_text()), commit, backend, frontend)
print('Release metadata matches reviewed source ' + commit + '; artifact/signature acceptance remains separate')
if __name__ == '__main__':
try:
main()
except (ValueError, KeyError, subprocess.CalledProcessError) as error:
raise SystemExit('REFUSED: ' + str(error))