Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 45 additions & 8 deletions .github/workflows/tagged-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ on:
- "v*"

permissions:
id-token: "write"
contents: "write"
env:
GH_TOKEN: ${{ github.token }}
Expand Down Expand Up @@ -94,6 +93,15 @@ jobs:

- run: npm run release:firefox-sources

- name: Upload Chrome package artifact
if: github.event_name == 'push' || inputs.submit_stores == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: chrome-extension
path: build/chromium.zip
if-no-files-found: error
retention-days: 30

- if: github.event_name == 'push'
run: |
gh release upload ${{github.ref_name}} build/chromium.zip
Expand All @@ -115,13 +123,7 @@ jobs:
fi
npm run release:submit -- "${args[@]}"
env:
CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
CHROME_CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
CHROME_REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}
CHROME_PUBLISH_TARGET: ${{ secrets.CHROME_PUBLISH_TARGET }}
CHROME_DEPLOY_PERCENTAGE: ${{ secrets.CHROME_DEPLOY_PERCENTAGE }}
CHROME_REVIEW_EXEMPTION: ${{ secrets.CHROME_REVIEW_EXEMPTION }}
CHROME_PUBLISH_VIA_ACTION: "true"
FIREFOX_EXTENSION_ID: ${{ secrets.FIREFOX_EXTENSION_ID }}
FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }}
FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }}
Expand All @@ -134,3 +136,38 @@ jobs:
- if: github.event_name == 'push'
run: |
gh release edit ${{github.ref_name}} --draft=false

publish_chrome:
if: github.event_name == 'push' || inputs.submit_stores == 'true'
needs: build_and_release
Comment thread
coderabbitai[bot] marked this conversation as resolved.
runs-on: ubuntu-latest
environment: chrome-web-store
permissions:
id-token: "write"
concurrency:
group: chrome-web-store
cancel-in-progress: false
Comment thread
coderabbitai[bot] marked this conversation as resolved.
queue: max
Comment thread
hamzahamidi marked this conversation as resolved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the unsupported concurrency queue field

On every tag push or manual dispatch, GitHub validates this file before scheduling either job, but jobs.<job_id>.concurrency only accepts group and cancel-in-progress; queue is not a recognized key. The workflow is therefore rejected with Unexpected value 'queue', so build_and_release and the new Chrome publication never run; use a supported queuing or serialization mechanism instead.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is supported by GitHub Actions since May 7, 2026. queue: max is valid for job-level concurrency when cancel-in-progress is false, as configured here.

References:

No change is needed; keeping this setting to preserve pending Chrome publishing jobs.

steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: chrome-extension
- id: auth
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
with:
workload_identity_provider: ${{ vars.CWS_WIF_PROVIDER }}
service_account: ${{ vars.CWS_SERVICE_ACCOUNT }}
token_format: access_token
access_token_scopes: https://www.googleapis.com/auth/chromewebstore
access_token_lifetime: 1800s
create_credentials_file: false
export_environment_variables: false
- uses: hamzahamidi/publish-to-chrome-web-store@c8919147f8de0d6f1129bec36345e4a9aa638af9 # v1
with:
access-token: ${{ steps.auth.outputs.access_token }}
publisher-id: ${{ vars.CWS_PUBLISHER_ID }}
item-id: ${{ secrets.CHROME_EXTENSION_ID }}
zip: chromium.zip
deploy-percentage: ${{ secrets.CHROME_DEPLOY_PERCENTAGE }}
skip-review: ${{ secrets.CHROME_REVIEW_EXEMPTION }}
dry-run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run == 'true' }}
24 changes: 18 additions & 6 deletions scripts/submit-stores.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ const REQUIRED_ENV = [
'EDGE_CLIENT_ID',
'EDGE_API_KEY',
]
const CHROME_ENV = [
'CHROME_EXTENSION_ID',
'CHROME_CLIENT_ID',
'CHROME_CLIENT_SECRET',
'CHROME_REFRESH_TOKEN',
]

export function parseArgs(args) {
return {
Expand All @@ -40,7 +46,12 @@ export function parseArgs(args) {
}

export function findMissingEnv(env = process.env) {
return REQUIRED_ENV.filter((name) => {
const requiredEnv =
env.CHROME_PUBLISH_VIA_ACTION === 'true'
Comment thread
pullfrog[bot] marked this conversation as resolved.
? REQUIRED_ENV.filter((name) => !CHROME_ENV.includes(name))
: REQUIRED_ENV
Comment thread
hamzahamidi marked this conversation as resolved.

return requiredEnv.filter((name) => {
const value = env[name]
return typeof value !== 'string' || value.trim().length === 0
})
Expand All @@ -58,11 +69,10 @@ export async function findMissingArtifacts({ exists = fs.pathExists } = {}) {
return missing
}

export function buildPublishExtensionArgs({ dryRun }) {
export function buildPublishExtensionArgs({ dryRun, skipChrome = false }) {
return [
...(dryRun ? ['--dry-run'] : []),
'--chrome-zip',
'build/chromium.zip',
...(!skipChrome ? ['--chrome-zip', 'build/chromium.zip'] : []),
Comment thread
hamzahamidi marked this conversation as resolved.
'--firefox-zip',
'build/firefox.zip',
'--firefox-sources-zip',
Expand Down Expand Up @@ -199,10 +209,12 @@ export async function submitStores({ argv = process.argv.slice(2), env = process
}

const manifest = await fs.readJson('build/firefox/manifest.json')
const args = buildPublishExtensionArgs({ dryRun })
const skipChrome = env.CHROME_PUBLISH_VIA_ACTION === 'true'
const args = buildPublishExtensionArgs({ dryRun, skipChrome })
const firefoxReleaseNotes = buildFirefoxReleaseNotes(manifest.version)
const stores = skipChrome ? 'Firefox and Edge' : 'Chrome, Firefox, and Edge'

console.log(`Submitting ChatGPTBox ${manifest.version} to Chrome, Firefox, and Edge`)
console.log(`Submitting ChatGPTBox ${manifest.version} to ${stores}`)
console.log(`Mode: ${dryRun ? 'dry-run' : 'submit'}`)
console.log(`Artifacts: ${REQUIRED_ARTIFACTS.join(', ')}`)
console.log(`Firefox version notes: ${firefoxReleaseNotes}`)
Expand Down
54 changes: 54 additions & 0 deletions tests/unit/release/submit-stores.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,47 @@ test('findMissingEnv accepts required secrets', () => {
assert.deepEqual(findMissingEnv(env), [])
})

test('findMissingEnv does not require Chrome credentials when publishing through the action', () => {
const env = {
CHROME_PUBLISH_VIA_ACTION: 'true',
FIREFOX_EXTENSION_ID: 'chatgptbox',
FIREFOX_JWT_ISSUER: 'firefox-issuer',
FIREFOX_JWT_SECRET: 'firefox-secret',
EDGE_PRODUCT_ID: 'edge-product',
EDGE_CLIENT_ID: 'edge-client',
EDGE_API_KEY: 'edge-key',
}

assert.deepEqual(findMissingEnv(env), [])
})

test('findMissingEnv requires Firefox and Edge credentials in action mode', () => {
const requiredStoreEnv = [
'FIREFOX_EXTENSION_ID',
'FIREFOX_JWT_ISSUER',
'FIREFOX_JWT_SECRET',
'EDGE_PRODUCT_ID',
'EDGE_CLIENT_ID',
'EDGE_API_KEY',
]
const env = {
CHROME_PUBLISH_VIA_ACTION: 'true',
FIREFOX_EXTENSION_ID: 'chatgptbox',
FIREFOX_JWT_ISSUER: 'firefox-issuer',
FIREFOX_JWT_SECRET: 'firefox-secret',
EDGE_PRODUCT_ID: 'edge-product',
EDGE_CLIENT_ID: 'edge-client',
EDGE_API_KEY: 'edge-key',
}

for (const name of requiredStoreEnv) {
const envWithoutStoreValue = { ...env }
delete envWithoutStoreValue[name]

assert.deepEqual(findMissingEnv(envWithoutStoreValue), [name])
}
})

test('findMissingEnv treats whitespace-only secrets as missing', () => {
const env = {
CHROME_EXTENSION_ID: 'chrome-id',
Expand Down Expand Up @@ -108,6 +149,19 @@ test('buildPublishExtensionArgs includes all stores and dry run', () => {
])
})

test('buildPublishExtensionArgs skips Chrome when it is published through the action', () => {
const args = buildPublishExtensionArgs({ dryRun: false, skipChrome: true })

assert.deepEqual(args, [
'--firefox-zip',
'build/firefox.zip',
'--firefox-sources-zip',
'build/firefox-sources.zip',
'--edge-zip',
'build/chromium.zip',
])
})

test('buildFirefoxReleaseNotes returns the fixed GitHub release URL', () => {
assert.equal(
buildFirefoxReleaseNotes('2.6.1'),
Expand Down
Loading