chore: prepare verified CRX uploads and release 0.15.4
Testing / remote-protocol-compat (0.9.5) (push) Successful in 36s
Package Extension / package-extension (push) Successful in 33s
Build & Publish Package / publish (push) Successful in 31s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 32s
Testing / test (push) Successful in 36s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 36s
Package Extension / package-extension (push) Successful in 33s
Build & Publish Package / publish (push) Successful in 31s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 32s
Testing / test (push) Successful in 36s
- Add helper scripts for Chrome Web Store verified CRX uploads using a dedicated RSA upload key protected by GPG. - Document the verified upload packaging flow and ignore local signing secrets. - Add npm packaging entry point for signed webstore CRX artifacts. - Chunk large SDK tab close batches to avoid native-host response timeouts. - Bump project and extension versions to 0.15.4 with matching tests.
This commit is contained in:
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: scripts/package_verified_crx.sh [--key FILE.gpg] [--browser COMMAND] [--out FILE.crx]
|
||||
|
||||
Builds the Chrome Web Store package and creates a CRX signed with the dedicated
|
||||
verified-upload RSA key. The RSA private key is expected to be GPG-encrypted.
|
||||
|
||||
Environment alternatives:
|
||||
VERIFIED_CRX_KEY_GPG Path to encrypted RSA private key
|
||||
CHROME_FOR_PACKING Browser command with --pack-extension support
|
||||
EOF
|
||||
}
|
||||
|
||||
key_gpg="${VERIFIED_CRX_KEY_GPG:-secrets/verified-crx/chrome-webstore-verified-crx-private-key.pem.gpg}"
|
||||
browser_cmd="${CHROME_FOR_PACKING:-}"
|
||||
out=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--key)
|
||||
key_gpg="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--browser)
|
||||
browser_cmd="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--out)
|
||||
out="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -f "$key_gpg" ]]; then
|
||||
echo "Encrypted verified CRX key not found: $key_gpg" >&2
|
||||
echo "Create it with: scripts/setup_verified_crx_key.sh --recipient '<your GPG key>'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$browser_cmd" ]]; then
|
||||
for candidate in google-chrome chrome chromium chromium-browser brave-browser brave; do
|
||||
if command -v "$candidate" >/dev/null 2>&1; then
|
||||
browser_cmd="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z "$browser_cmd" ]]; then
|
||||
echo "No Chromium-based browser with --pack-extension found. Pass --browser or set CHROME_FOR_PACKING." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
version="$(python - <<'PY'
|
||||
import json
|
||||
from pathlib import Path
|
||||
print(json.loads(Path('extension/manifest.json').read_text())['version'])
|
||||
PY
|
||||
)"
|
||||
out="${out:-dist/browser-cli-extension-webstore-verified-v${version}.crx}"
|
||||
|
||||
npm run build:extension
|
||||
python scripts/package_extension.py --webstore --out "dist/browser-cli-extension-webstore-v${version}.zip" >/dev/null
|
||||
|
||||
staging="$PWD/dist/extension-package-webstore"
|
||||
if [[ ! -d "$staging" ]]; then
|
||||
echo "Missing webstore staging directory: $staging" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_dir="$(mktemp -d)"
|
||||
private_key="$tmp_dir/verified-crx-private-key.pem"
|
||||
trap 'rm -rf "$tmp_dir"' EXIT
|
||||
|
||||
gpg --decrypt --output "$private_key" "$key_gpg"
|
||||
chmod 600 "$private_key"
|
||||
|
||||
rm -f "$staging.crx"
|
||||
"$browser_cmd" \
|
||||
--pack-extension="$staging" \
|
||||
--pack-extension-key="$private_key" \
|
||||
--no-message-box \
|
||||
--disable-gpu \
|
||||
--no-sandbox >/dev/null
|
||||
|
||||
mkdir -p "$(dirname "$out")"
|
||||
mv "$staging.crx" "$out"
|
||||
|
||||
echo "$out"
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: scripts/setup_verified_crx_key.sh [--recipient GPG_RECIPIENT] [--out-dir DIR]
|
||||
|
||||
Generates a dedicated RSA private key for Chrome Web Store verified CRX uploads,
|
||||
encrypts it to your GPG key, and writes the public key material for the Chrome
|
||||
Developer Dashboard.
|
||||
|
||||
Chrome Web Store verified uploads require an RSA CRX signing key. A GPG/OpenPGP
|
||||
key cannot be used directly for CRX signing, but it can protect the RSA private
|
||||
key at rest.
|
||||
EOF
|
||||
}
|
||||
|
||||
recipient=""
|
||||
out_dir="secrets/verified-crx"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--recipient)
|
||||
recipient="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--out-dir)
|
||||
out_dir="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$recipient" ]]; then
|
||||
recipient="$(gpg --list-secret-keys --with-colons 2>/dev/null | awk -F: '$1 == "uid" { print $10; exit }')"
|
||||
fi
|
||||
|
||||
if [[ -z "$recipient" ]]; then
|
||||
echo "No GPG recipient found. Pass --recipient '<key id or email>'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$out_dir"
|
||||
chmod 700 "$out_dir"
|
||||
|
||||
private_key="$(mktemp)"
|
||||
public_pem="$out_dir/chrome-webstore-verified-crx-public-key.pem"
|
||||
public_der_b64="$out_dir/chrome-webstore-verified-crx-public-key.der.base64.txt"
|
||||
encrypted_private="$out_dir/chrome-webstore-verified-crx-private-key.pem.gpg"
|
||||
trap 'rm -f "$private_key"' EXIT
|
||||
|
||||
if [[ -e "$encrypted_private" ]]; then
|
||||
echo "Refusing to overwrite existing encrypted private key: $encrypted_private" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
openssl genrsa -out "$private_key" 2048 >/dev/null 2>&1
|
||||
chmod 600 "$private_key"
|
||||
openssl rsa -in "$private_key" -pubout -out "$public_pem" >/dev/null 2>&1
|
||||
openssl rsa -in "$private_key" -pubout -outform DER 2>/dev/null | base64 -w0 > "$public_der_b64"
|
||||
printf '\n' >> "$public_der_b64"
|
||||
|
||||
gpg --encrypt --recipient "$recipient" --output "$encrypted_private" "$private_key"
|
||||
chmod 600 "$encrypted_private"
|
||||
|
||||
cat <<EOF
|
||||
Created verified CRX upload key material:
|
||||
encrypted private key: $encrypted_private
|
||||
public key PEM: $public_pem
|
||||
public key DER/base64: $public_der_b64
|
||||
|
||||
Use the public key in the Chrome Developer Dashboard -> Package -> Verified uploads.
|
||||
Keep the encrypted private key. Do not commit or upload the decrypted PEM.
|
||||
EOF
|
||||
Reference in New Issue
Block a user