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
- 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.
79 lines
2.4 KiB
Python
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()
|