Compare commits
2
Commits
d0c5fc5679
...
2f5568fb37
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f5568fb37 | ||
|
|
1926ac166b |
No files matched your search
@@ -0,0 +1,196 @@
|
||||
name: Build and publish extension
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version to validate (for example 1.0.1)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build extension packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.release.tag_name || github.ref }}
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Validate release version
|
||||
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
|
||||
env:
|
||||
RELEASE_VERSION: ${{ github.event.release.tag_name || inputs.version }}
|
||||
run: |
|
||||
python - <<'PY'
|
||||
import json, os, re
|
||||
expected = os.environ["RELEASE_VERSION"].removeprefix("v")
|
||||
for path in ("manifest.json", "manifest.chrome.json"):
|
||||
actual = json.load(open(path, encoding="utf-8"))["version"]
|
||||
if actual != expected:
|
||||
raise SystemExit(f"{path}: version {actual!r} does not match release {expected!r}")
|
||||
if not re.fullmatch(r"\d+(\.\d+){1,3}", expected):
|
||||
raise SystemExit(f"Release version must be numeric, got {expected!r}")
|
||||
PY
|
||||
|
||||
- name: Install web-ext
|
||||
run: npm install --global web-ext
|
||||
|
||||
- name: Prepare Firefox source
|
||||
run: |
|
||||
mkdir -p dist/firefox-source
|
||||
rsync -a \
|
||||
--exclude '.git/' \
|
||||
--exclude '.github/' \
|
||||
--exclude 'web-ext-artifacts/' \
|
||||
--exclude 'manifest.chrome.json' \
|
||||
--exclude 'background-chrome.js' \
|
||||
--exclude 'background-service-worker.js' \
|
||||
--exclude 'browser-api.js' \
|
||||
--exclude 'scripts/' \
|
||||
./ dist/firefox-source/
|
||||
|
||||
- name: Build Firefox package
|
||||
run: |
|
||||
web-ext build \
|
||||
--source-dir dist/firefox-source \
|
||||
--artifacts-dir dist/firefox \
|
||||
--filename proxyswitcherforkbywt-firefox.xpi \
|
||||
--overwrite-dest
|
||||
|
||||
- name: Build Chrome package
|
||||
run: python scripts/build-chrome.py
|
||||
|
||||
- name: Upload packages for this push
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: extension-packages-${{ github.sha }}
|
||||
if-no-files-found: error
|
||||
path: |
|
||||
dist/firefox/proxyswitcherforkbywt-firefox.xpi
|
||||
web-ext-artifacts/proxyswitcherforkbywt-chrome.zip
|
||||
|
||||
publish:
|
||||
name: Publish stores and attach release assets
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }}
|
||||
AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }}
|
||||
CWS_PUBLISHER_ID: ${{ secrets.CWS_PUBLISHER_ID }}
|
||||
CWS_EXTENSION_ID: ${{ secrets.CWS_EXTENSION_ID }}
|
||||
CWS_CLIENT_ID: ${{ secrets.CWS_CLIENT_ID }}
|
||||
CWS_CLIENT_SECRET: ${{ secrets.CWS_CLIENT_SECRET }}
|
||||
CWS_REFRESH_TOKEN: ${{ secrets.CWS_REFRESH_TOKEN }}
|
||||
steps:
|
||||
- name: Check out release source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.release.tag_name }}
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Download build packages
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: extension-packages-${{ github.sha }}
|
||||
path: dist/packages
|
||||
|
||||
- name: Set up Firefox signing tools
|
||||
run: |
|
||||
npm install --global web-ext
|
||||
mkdir -p dist/firefox-source
|
||||
rsync -a \
|
||||
--exclude '.git/' \
|
||||
--exclude '.github/' \
|
||||
--exclude 'web-ext-artifacts/' \
|
||||
--exclude 'manifest.chrome.json' \
|
||||
--exclude 'background-chrome.js' \
|
||||
--exclude 'background-service-worker.js' \
|
||||
--exclude 'browser-api.js' \
|
||||
--exclude 'scripts/' \
|
||||
./ dist/firefox-source/
|
||||
|
||||
- name: Sign and submit Firefox package to AMO
|
||||
run: |
|
||||
test -n "$AMO_JWT_ISSUER" || { echo 'Missing AMO_JWT_ISSUER secret'; exit 1; }
|
||||
test -n "$AMO_JWT_SECRET" || { echo 'Missing AMO_JWT_SECRET secret'; exit 1; }
|
||||
web-ext sign \
|
||||
--source-dir dist/firefox-source \
|
||||
--artifacts-dir dist/firefox-signed \
|
||||
--api-key "$AMO_JWT_ISSUER" \
|
||||
--api-secret "$AMO_JWT_SECRET" \
|
||||
--channel listed \
|
||||
--approval-timeout 900000 \
|
||||
--no-input
|
||||
firefox_xpi=$(find dist/firefox-signed -maxdepth 1 -name '*.xpi' -print -quit)
|
||||
test -n "$firefox_xpi" || { echo 'AMO did not return a signed XPI'; exit 1; }
|
||||
cp "$firefox_xpi" dist/packages/proxyswitcherforkbywt-firefox-signed.xpi
|
||||
|
||||
- name: Upload Chrome package to Chrome Web Store
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for name in CWS_PUBLISHER_ID CWS_EXTENSION_ID CWS_CLIENT_ID CWS_CLIENT_SECRET CWS_REFRESH_TOKEN; do
|
||||
test -n "${!name}" || { echo "Missing $name secret"; exit 1; }
|
||||
done
|
||||
token=$(curl --fail --silent --show-error \
|
||||
--data-urlencode "client_id=$CWS_CLIENT_ID" \
|
||||
--data-urlencode "client_secret=$CWS_CLIENT_SECRET" \
|
||||
--data-urlencode "refresh_token=$CWS_REFRESH_TOKEN" \
|
||||
--data-urlencode 'grant_type=refresh_token' \
|
||||
https://oauth2.googleapis.com/token | python -c 'import json,sys; print(json.load(sys.stdin)["access_token"])')
|
||||
chrome_zip=$(find dist/packages -name 'proxyswitcherforkbywt-chrome.zip' -print -quit)
|
||||
test -f "$chrome_zip" || { echo "Missing Chrome package: $chrome_zip"; exit 1; }
|
||||
curl --fail --silent --show-error \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'Content-Type: application/zip' \
|
||||
--data-binary "@$chrome_zip" \
|
||||
"https://chromewebstore.googleapis.com/upload/v2/publishers/$CWS_PUBLISHER_ID/items/$CWS_EXTENSION_ID:upload"
|
||||
curl --fail --silent --show-error \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $token" \
|
||||
"https://chromewebstore.googleapis.com/v2/publishers/$CWS_PUBLISHER_ID/items/$CWS_EXTENSION_ID:publish"
|
||||
|
||||
- name: Attach signed Firefox and Chrome packages to release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh release upload "${{ github.event.release.tag_name }}" \
|
||||
dist/packages/proxyswitcherforkbywt-firefox-signed.xpi \
|
||||
"$chrome_zip" \
|
||||
--clobber
|
||||
|
||||
- name: Upload signed packages as workflow artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: signed-extension-packages-${{ github.event.release.tag_name }}
|
||||
if-no-files-found: error
|
||||
path: |
|
||||
dist/packages/proxyswitcherforkbywt-firefox-signed.xpi
|
||||
dist/packages/**/proxyswitcherforkbywt-chrome.zip
|
||||
@@ -16,6 +16,7 @@ This repository contains the Firefox WebExtension **Proxy Switcher Fork By WT**.
|
||||
- `options.html`, `options.js`, `options.css` — profiles, domains, management actions, and Advanced Settings.
|
||||
- `icons/` — extension icon sizes referenced by `manifest.json`.
|
||||
- `Makefile` — build and cleanup commands.
|
||||
- `.github/workflows/release.yml` — per-push package builds, workflow artifacts, and release-triggered AMO/Chrome Web Store publishing.
|
||||
|
||||
## Development rules
|
||||
|
||||
@@ -28,6 +29,7 @@ This repository contains the Firefox WebExtension **Proxy Switcher Fork By WT**.
|
||||
- When changing an icon, update every size referenced by the manifest and verify the XPI contains the new paths.
|
||||
- Never hand-edit or retain stale `META-INF` signatures after changing files. Build artifacts must be signed again before distribution.
|
||||
- Do not commit generated `web-ext-artifacts/` packages unless explicitly requested.
|
||||
- Keep publishing credentials only in GitHub Secrets. The release workflow expects AMO JWT credentials and Chrome Web Store OAuth credentials.
|
||||
|
||||
## Validation
|
||||
|
||||
|
||||
@@ -94,6 +94,18 @@ The package is created at `web-ext-artifacts/proxyswitcherforkbywt.xpi`. This lo
|
||||
|
||||
For Chrome/Chromium, run `make build-chrome`. That creates `web-ext-artifacts/proxyswitcherforkbywt-chrome.zip` from `manifest.chrome.json` and the shared UI files.
|
||||
|
||||
## GitHub Actions release publishing
|
||||
|
||||
`.github/workflows/release.yml` builds both packages on every push. The run exposes a downloadable `extension-packages-<commit>` artifact containing the Firefox XPI and Chrome ZIP. When a GitHub Release is published, it checks that both manifests match the release tag, submits the Firefox package to AMO for signing and review, uploads and submits the Chrome package through the Chrome Web Store API v2, and attaches the signed Firefox XPI and Chrome ZIP to the release card.
|
||||
|
||||
Configure these repository or environment secrets before publishing:
|
||||
|
||||
- `AMO_JWT_ISSUER` and `AMO_JWT_SECRET` — AMO API credentials for `web-ext sign`.
|
||||
- `CWS_PUBLISHER_ID` and `CWS_EXTENSION_ID` — Chrome Web Store publisher and existing item IDs.
|
||||
- `CWS_CLIENT_ID`, `CWS_CLIENT_SECRET`, and `CWS_REFRESH_TOKEN` — Google OAuth credentials with Chrome Web Store API access.
|
||||
|
||||
The stores must already contain their initial listings and required privacy information. Store review still applies; the workflow submits the update and does not bypass review. Never commit any of these credentials.
|
||||
|
||||
To remove generated packages:
|
||||
|
||||
```sh
|
||||
|
||||
Reference in new issue
Block a user