Skip to content

Commit 2d13baa

Browse files
committed
feat: add automatic store publishing workflow
Publishes to the Chrome Web Store and Firefox Add-ons on merge to main (or via manual dispatch). Builds the zips, runs wxt submit, then tags the version and creates a GitHub release. Idempotent: skips if the version is already tagged. Chrome activates once a refresh token secret is present; Firefox publishes independently. Closes #96
1 parent a4c74b7 commit 2d13baa

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

.github/workflows/publish.yaml

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: Publish
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths-ignore:
7+
- '**.md'
8+
- 'docs/**'
9+
- '.github/**'
10+
- '.gitignore'
11+
- '.editorconfig'
12+
- '.prettierrc'
13+
workflow_dispatch:
14+
15+
jobs:
16+
check:
17+
runs-on: ubuntu-latest
18+
outputs:
19+
should_publish: ${{ steps.check.outputs.should_publish }}
20+
version: ${{ steps.version.outputs.version }}
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Read version from package.json
27+
id: version
28+
run: echo "version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
29+
30+
# The semver workflow already enforces a version bump on every PR to
31+
# main, but guard on the tag so re-runs and non-version pushes (or a
32+
# manual dispatch) never submit the same version twice.
33+
- name: Skip if version already released
34+
id: check
35+
run: |
36+
if git rev-parse "v${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
37+
echo "Tag v${{ steps.version.outputs.version }} already exists - nothing to publish."
38+
echo "should_publish=false" >> "$GITHUB_OUTPUT"
39+
else
40+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
41+
fi
42+
43+
publish:
44+
needs: check
45+
if: needs.check.outputs.should_publish == 'true'
46+
runs-on: ubuntu-latest
47+
permissions:
48+
contents: write
49+
env:
50+
VERSION: ${{ needs.check.outputs.version }}
51+
# Chrome only runs once a refresh token secret is present. Until then
52+
# Firefox publishes on its own and the Chrome step is skipped.
53+
HAS_CHROME_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN != '' }}
54+
steps:
55+
- uses: actions/checkout@v4
56+
57+
- name: Install pnpm
58+
uses: pnpm/action-setup@v4
59+
with:
60+
version: 10
61+
62+
- name: Setup Node.js
63+
uses: actions/setup-node@v4
64+
with:
65+
node-version: lts/*
66+
cache: 'pnpm'
67+
68+
- name: Install dependencies
69+
run: pnpm install --frozen-lockfile
70+
71+
- name: Build & zip (Chrome)
72+
run: pnpm zip
73+
74+
- name: Build & zip (Firefox + sources)
75+
run: pnpm zip:firefox
76+
77+
- name: Submit to Firefox Add-ons
78+
run: |
79+
pnpm wxt submit \
80+
--firefox-zip .output/*-firefox.zip \
81+
--firefox-sources-zip .output/*-sources.zip
82+
env:
83+
FIREFOX_EXTENSION_ID: ${{ secrets.FIREFOX_EXTENSION_ID }}
84+
FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }}
85+
FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }}
86+
FIREFOX_CHANNEL: ${{ secrets.FIREFOX_CHANNEL }}
87+
88+
- name: Submit to Chrome Web Store
89+
if: env.HAS_CHROME_TOKEN == 'true'
90+
run: |
91+
pnpm wxt submit \
92+
--chrome-zip .output/*-chrome.zip
93+
env:
94+
CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
95+
CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
96+
CHROME_CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
97+
CHROME_REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}
98+
CHROME_PUBLISH_TARGET: ${{ secrets.CHROME_PUBLISH_TARGET }}
99+
CHROME_SKIP_SUBMIT_REVIEW: ${{ secrets.CHROME_SKIP_SUBMIT_REVIEW }}
100+
101+
- name: Tag and create GitHub release
102+
env:
103+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
104+
run: |
105+
git tag "v$VERSION"
106+
git push origin "v$VERSION"
107+
gh release create "v$VERSION" --title "v$VERSION" --generate-notes

0 commit comments

Comments
 (0)