65 lines
2.6 KiB
Python
65 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Validate the version and checked-in artifacts for a LinkLog release."""
|
|
|
|
import json
|
|
import re
|
|
import sys
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
MANIFEST_PATH = ROOT / 'webextension' / 'manifest.json'
|
|
FRONTEND_VERSION_PATH = ROOT / 'frontend' / 'version.json'
|
|
SETTINGS_PATH = ROOT / 'backend' / 'app' / 'core' / 'config.py'
|
|
UPDATES_PATH = ROOT / 'webextension' / 'updates.json'
|
|
SIGNED_DIR = ROOT / 'XPI' / 'signed'
|
|
|
|
|
|
def fail(message: str) -> None:
|
|
raise SystemExit(f'release validation failed: {message}')
|
|
|
|
|
|
def main() -> None:
|
|
manifest = json.loads(MANIFEST_PATH.read_text())
|
|
extension_version = manifest.get('version')
|
|
if not isinstance(extension_version, str) or not re.fullmatch(r'\d+\.\d+\.\d+', extension_version):
|
|
fail('webextension/manifest.json has no valid three-part version')
|
|
|
|
frontend_version = json.loads(FRONTEND_VERSION_PATH.read_text()).get('version')
|
|
if frontend_version != extension_version:
|
|
fail(f'frontend version {frontend_version} does not match extension version {extension_version}')
|
|
|
|
settings = SETTINGS_PATH.read_text()
|
|
match = re.search(r"version: str = os\.getenv\('LINKLOG_VERSION', '([^']+)'\)", settings)
|
|
if not match:
|
|
fail('backend version default could not be found')
|
|
backend_version = match.group(1)
|
|
if backend_version != extension_version:
|
|
fail(f'backend version {backend_version} does not match extension version {extension_version}')
|
|
|
|
xpi_path = SIGNED_DIR / f'LinkLog-{extension_version}.xpi'
|
|
if not xpi_path.is_file():
|
|
fail(f'missing manually signed artifact: {xpi_path.relative_to(ROOT)}')
|
|
with zipfile.ZipFile(xpi_path) as archive:
|
|
try:
|
|
packaged_manifest = json.loads(archive.read('manifest.json'))
|
|
except KeyError:
|
|
fail('signed XPI does not contain manifest.json')
|
|
if packaged_manifest.get('version') != extension_version:
|
|
fail('signed XPI manifest version does not match webextension/manifest.json')
|
|
if archive.testzip() is not None:
|
|
fail('signed XPI contains a corrupt member')
|
|
|
|
updates = json.loads(UPDATES_PATH.read_text())
|
|
addon_id = manifest['browser_specific_settings']['gecko']['id']
|
|
update_entries = updates.get('addons', {}).get(addon_id, {}).get('updates', [])
|
|
if not any(entry.get('version') == extension_version for entry in update_entries):
|
|
fail(f'webextension/updates.json has no update entry for {extension_version}')
|
|
|
|
print(f'validated LinkLog release {frontend_version}')
|
|
print(f'xpi={xpi_path.relative_to(ROOT)}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main() |