# Publishing to the Chrome Web Store This document describes how to release a new version of the Outlook Web Inbox Count extension to the Chrome Web Store using the `publish.sh` script. ## Quick release workflow For a routine release (once the one-time setup below is done): 1. Edit `content.js` and bump the version in `manifest.json` (e.g. `1.4` -> `1.5`). 2. Add a changelog entry in the header of `content.js`. 3. Run: ```bash ./publish.sh ``` This builds `outlook_web_inbox_count_v.zip` from `manifest.json`, uploads it, and publishes it. Chrome Web Store review typically takes a few hours to a day before the new version goes live. Options: - `./publish.sh --no-publish` - upload only, leave as Draft in the dashboard. - `./publish.sh path/to/existing.zip` - upload a specific zip without rebuilding. ## How it works `publish.sh` uses the [Chrome Web Store API](https://developer.chrome.com/docs/webstore/api): 1. Exchanges the OAuth **refresh token** (from `.env`) for a short-lived **access token** via `https://oauth2.googleapis.com/token`. 2. `PUT`s the zip to `upload/chromewebstore/v1.1/items/$EXTENSION_ID`. 3. `POST`s to `chromewebstore/v1.1/items/$EXTENSION_ID/publish` to submit the uploaded draft for review. The script reads all credentials from a `.env` file in the project root (gitignored). Required variables: ``` CLIENT_ID= CLIENT_SECRET= REFRESH_TOKEN= EXTENSION_ID=<32-char chrome web store extension id> ``` The current extension ID is `mjdfjopdcoiojbjnfkpjhcnpefjknkdn`. ## One-time setup (already done, for reference) ### 1. Google Cloud OAuth project 1. Create a project at https://console.cloud.google.com/. 2. Enable the **Chrome Web Store API** under "APIs & Services". 3. Configure the OAuth consent screen: - User type: External - Add yourself as a **test user** (required while the app is in Testing mode). 4. Create OAuth credentials: - "Credentials" -> "Create Credentials" -> "OAuth client ID" - Application type: **Desktop app** - Save the `client_id` and `client_secret` to `.env`. ### 2. Obtain a refresh token Open this URL in a browser (replace `$CLIENT_ID`): ``` https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/chromewebstore&client_id=$CLIENT_ID&redirect_uri=http://localhost&access_type=offline&prompt=consent ``` After approval, the browser will attempt to redirect to `http://localhost/?code=...` and fail to connect - that is expected. **Copy the `code` value from the URL bar.** Exchange the code for a refresh token: ```bash curl "https://oauth2.googleapis.com/token" \ -d "client_id=$CLIENT_ID" \ -d "client_secret=$CLIENT_SECRET" \ -d "code=$CODE" \ -d "grant_type=authorization_code" \ -d "redirect_uri=http://localhost" ``` Save the `refresh_token` value from the JSON response into `.env`. ### 3. Find the extension ID Log into https://chrome.google.com/webstore/devconsole and open the extension's edit page. The URL contains the 32-character extension ID: `.../devconsole///edit`. ## Refreshing credentials ### If the refresh token has expired (7-day limit) While the OAuth consent screen is in **Testing** mode, refresh tokens expire after **7 days**. If `publish.sh` fails with an access-token error, redo step 2 above (obtain a new code and exchange it) and update `REFRESH_TOKEN` in `.env`. **To avoid this**, publish the OAuth app (consent screen -> "Publish App"). Since the only user is the developer and the scope (`chromewebstore`) is self-owned, verification is not strictly required for personal use - the app just needs to be in "In production" state. ### Rotating the client secret If the `client_secret` is ever exposed, rotate it in the Google Cloud console (Credentials page -> edit client -> Reset Secret) and update `.env`. You will also need to obtain a new refresh token since the old one is tied to the old secret. ## Troubleshooting - **`Error 403: access_denied` during auth** - you are not added as a test user on the OAuth consent screen. Add yourself in the console and retry. - **`uploadState: FAILURE`** - usually means the zip is malformed, or the version in `manifest.json` is not greater than the currently published version. Bump the version and rebuild. - **Publish returns `ITEM_PENDING_REVIEW`** - normal. The item has been submitted and is in the Chrome review queue. - **Refresh token suddenly invalid** - most likely the 7-day testing-mode expiry. Obtain a new one (see above). ## Files - `publish.sh` - build + upload + publish script. - `.env` - credentials (gitignored; never commit). - `.gitignore` - excludes `.env`. - `manifest.json` - source of truth for the version number. - `outlook_web_inbox_count_v.zip` - build artifact produced by `publish.sh`.