#!/usr/bin/env bash # Build and publish the extension to the Chrome Web Store. # # Reads the version from manifest.json, builds outlook_web_inbox_count_v.zip # (overwriting if present), then uploads and publishes it via the Chrome Web Store API. # # Usage: # ./publish.sh # build from manifest.json, upload, and publish # ./publish.sh --no-publish # upload only (leave in Draft state in the dashboard) # ./publish.sh path/to/extension.zip # skip build, upload a specific zip # # Requires a .env file in the project root with: # CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN, EXTENSION_ID # See PUBLISHING.md for how to obtain these. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" # --- Parse arguments --- PUBLISH=true ZIP_ARG="" for arg in "$@"; do case "$arg" in --no-publish) PUBLISH=false ;; -h|--help) sed -n '2,15p' "$0" exit 0 ;; *) ZIP_ARG="$arg" ;; esac done # --- Load credentials --- if [[ ! -f .env ]]; then echo "Error: .env file not found (see PUBLISHING.md)" >&2 exit 1 fi set -a # shellcheck disable=SC1091 source .env set +a for var in CLIENT_ID CLIENT_SECRET REFRESH_TOKEN EXTENSION_ID; do if [[ -z "${!var:-}" ]]; then echo "Error: $var is not set in .env" >&2 exit 1 fi done # --- Determine / build zip --- if [[ -n "$ZIP_ARG" ]]; then ZIP="$ZIP_ARG" if [[ ! -f "$ZIP" ]]; then echo "Error: $ZIP not found" >&2 exit 1 fi else VERSION=$(python3 -c "import json; print(json.load(open('manifest.json'))['version'])") ZIP="outlook_web_inbox_count_v${VERSION}.zip" echo "Building $ZIP from manifest version $VERSION..." rm -f "$ZIP" zip -q "$ZIP" manifest.json content.js icon16.png icon64.png icon128.png fi echo "Package: $ZIP" # --- Get a fresh access token --- echo "Fetching access token..." ACCESS_TOKEN=$(curl -s "https://oauth2.googleapis.com/token" \ -d "client_id=${CLIENT_ID}" \ -d "client_secret=${CLIENT_SECRET}" \ -d "refresh_token=${REFRESH_TOKEN}" \ -d "grant_type=refresh_token" \ | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token',''))") if [[ -z "$ACCESS_TOKEN" ]]; then echo "Error: failed to obtain access token. Refresh token may have expired." >&2 echo "See PUBLISHING.md 'Refreshing credentials' section." >&2 exit 1 fi # --- Upload --- echo "Uploading to extension $EXTENSION_ID..." UPLOAD_RESPONSE=$(curl -s \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "x-goog-api-version: 2" \ -X PUT \ -T "$ZIP" \ "https://www.googleapis.com/upload/chromewebstore/v1.1/items/$EXTENSION_ID") echo "Upload response: $UPLOAD_RESPONSE" UPLOAD_STATE=$(echo "$UPLOAD_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('uploadState',''))" 2>/dev/null || echo "") if [[ "$UPLOAD_STATE" != "SUCCESS" ]]; then echo "Error: upload did not succeed (state: $UPLOAD_STATE)" >&2 exit 1 fi # --- Publish --- if [[ "$PUBLISH" == "true" ]]; then echo "Publishing..." PUBLISH_RESPONSE=$(curl -s \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "x-goog-api-version: 2" \ -H "Content-Length: 0" \ -X POST \ "https://www.googleapis.com/chromewebstore/v1.1/items/$EXTENSION_ID/publish") echo "Publish response: $PUBLISH_RESPONSE" else echo "Skipping publish step (--no-publish). The upload is in Draft state in the dashboard." fi echo "Done."