Files
browser-cli/scripts/package_extension.py
T
daniel156161 65a032f961
Testing / remote-protocol-compat (0.9.3) (push) Successful in 49s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 53s
Testing / test (push) Successful in 36s
Package Extension / package-extension (push) Successful in 31s
Build & Publish Package / publish (push) Successful in 37s
ci: publish separate extension archives
- Rename the keyed extension package to a testing archive to make its purpose explicit.
- Keep the webstore archive as a separate keyless package for Chrome Web Store upload.
- Upload both extension archives to tagged releases instead of only publishing one ambiguous asset.
- Update the package helper's default suffix and documentation to match the release asset names.
2026-06-14 15:20:48 +02:00

79 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""Package the Chrome extension.
Default builds a testing/unpacked-style archive that keeps manifest.key so the
extension ID stays stable for native messaging. ``--webstore`` writes the same
runtime files but strips ``key`` from manifest.json because the Chrome Web Store
rejects that field.
"""
from __future__ import annotations
import argparse
import json
import shutil
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
EXTENSION_DIR = ROOT / "extension"
DIST_DIR = ROOT / "dist"
RUNTIME_FILES = (
"manifest.json",
"background.js",
"content-dispatch.js",
"content.js",
"icon.svg",
)
RUNTIME_DIRS = ("icons",)
def _read_manifest(webstore: bool) -> dict:
manifest = json.loads((EXTENSION_DIR / "manifest.json").read_text(encoding="utf-8"))
if webstore:
manifest.pop("key", None)
return manifest
def _copy_tree(src: Path, dst: Path) -> None:
if dst.exists():
shutil.rmtree(dst)
shutil.copytree(src, dst)
def package_extension(*, webstore: bool = False, out: Path | None = None) -> Path:
manifest = _read_manifest(webstore)
version = manifest["version"]
suffix = "webstore" if webstore else "testing"
out = out or DIST_DIR / f"browser-cli-extension-{suffix}-v{version}.zip"
staging = DIST_DIR / f"extension-package-{suffix}"
if staging.exists():
shutil.rmtree(staging)
staging.mkdir(parents=True)
out.parent.mkdir(parents=True, exist_ok=True)
for file_name in RUNTIME_FILES:
source = EXTENSION_DIR / file_name
if file_name == "manifest.json":
(staging / file_name).write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
else:
shutil.copy2(source, staging / file_name)
for dir_name in RUNTIME_DIRS:
_copy_tree(EXTENSION_DIR / dir_name, staging / dir_name)
if out.exists():
out.unlink()
with zipfile.ZipFile(out, "w", compression=zipfile.ZIP_DEFLATED) as zf:
for path in sorted(staging.rglob("*")):
if path.is_file():
zf.write(path, path.relative_to(staging).as_posix())
return out
def main() -> None:
parser = argparse.ArgumentParser(description="Package browser-cli extension")
parser.add_argument("--webstore", action="store_true", help="strip manifest.key for Chrome Web Store upload")
parser.add_argument("--out", type=Path, default=None, help="output zip path")
args = parser.parse_args()
print(package_extension(webstore=args.webstore, out=args.out))
if __name__ == "__main__":
main()