version in extension/manifest.json and commit.git tag vX.Y.Z && git push origin vX.Y.Z.release.yml fails unless the tag (without v) equals the manifest version. It then runs scripts/check-manifest.js and scripts/package.sh (test suites, node --check, zip) and creates a GitHub Release for the tag with framestash-X.Y.Z.zip attached.ci.yml runs the same checks on every push and pull request and keeps the zip as a run artifact (framestash-zip).
publish.yml downloads a release’s zip, uploads it to the Chrome Web Store API v2 and submits it for review. It runs after each successful Release run (workflow_run), or by hand from Actions → Publish to Chrome Web Store → Run workflow, with a tag. The setup below is done for underw8/framestash; a fork needs its own.
Refresh token. Open this URL in a browser signed in as the publisher account, approve, and copy the code from the address it redirects to:
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
Exchange it for a refresh token:
curl -sS -X POST 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
The reply’s refresh_token is the one to keep. A consent screen left in Testing issues refresh tokens that expire after 7 days; publish the consent screen to keep it valid.
CWS_CLIENT_ID, CWS_CLIENT_SECRET, CWS_REFRESH_TOKEN, CWS_PUBLISHER_ID, CWS_EXTENSION_ID.Check the credentials without uploading anything. The store rejects an upload whose version isn’t higher than the published one, so a test run on an existing release would fail. This asks for the item’s status instead:
tok=$(curl -sS -X POST 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 | jq -r .access_token)
curl -sS -H "Authorization: Bearer $tok" \
https://chromewebstore.googleapis.com/v2/publishers/PUBLISHER_ID/items/EXTENSION_ID:fetchStatus
A JSON reply with the item’s status means the token and IDs are right.
Uncomment the workflow_run: block in .github/workflows/publish.yml. Each successful Release run then submits its zip to the store; the next release is the first real test.