Skip to content

chore(release): v0.7.6 #6

chore(release): v0.7.6

chore(release): v0.7.6 #6

Workflow file for this run

name: Extension Release Pipeline
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
publish:
description: "Publish to stores (false = build only)"
type: boolean
default: true
permissions:
contents: read
jobs:
build:
name: Build Extension
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Load environment variables
run: |
echo "${{ secrets.ENV_FILE }}" | while IFS='=' read -r key value; do
[[ -z "$key" || "$key" =~ ^# ]] && continue
echo "::add-mask::$value"
echo "${key}=${value}" >> "$GITHUB_ENV"
done
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.15.1
- uses: actions/setup-node@v4
with:
node-version: "24"
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Extract and validate version
id: version
run: |
MANIFEST_VERSION=$(node -p "JSON.parse(require('fs').readFileSync('apps/extension/src/manifest.chrome.json', 'utf-8')).version")
if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
TAG_VERSION="${GITHUB_REF_NAME#v}"
if [[ "$TAG_VERSION" != "$MANIFEST_VERSION" ]]; then
echo "::error::Tag version ($TAG_VERSION) does not match manifest version ($MANIFEST_VERSION)"
exit 1
fi
VERSION="$TAG_VERSION"
else
VERSION="$MANIFEST_VERSION"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Building version: $VERSION"
- name: Build extension
run: pnpm turbo build --filter=@marksyncr/extension...
env:
NODE_ENV: production
NEXT_PUBLIC_SUPABASE_URL: ${{ env.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ env.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
NEXT_PUBLIC_APP_URL: ${{ env.NEXT_PUBLIC_APP_URL }}
- name: Verify build output
run: |
echo "Build artifacts:"
ls -lh apps/extension/dist/*.zip
test -f apps/extension/dist/marksyncr-chrome.zip || { echo "::error::Chrome ZIP not found"; exit 1; }
test -f apps/extension/dist/marksyncr-firefox.zip || { echo "::error::Firefox ZIP not found"; exit 1; }
- name: Upload Chrome ZIP
uses: actions/upload-artifact@v4
with:
name: marksyncr-chrome
path: apps/extension/dist/marksyncr-chrome.zip
retention-days: 30
- name: Upload Firefox ZIP
uses: actions/upload-artifact@v4
with:
name: marksyncr-firefox
path: apps/extension/dist/marksyncr-firefox.zip
retention-days: 30
chrome-release:
name: Publish to Chrome Web Store
needs: build
if: |
github.ref_type == 'tag' ||
(github.event_name == 'workflow_dispatch' && inputs.publish)
runs-on: ubuntu-latest
steps:
- name: Load environment variables
run: |
echo "${{ secrets.ENV_FILE }}" | while IFS='=' read -r key value; do
[[ -z "$key" || "$key" =~ ^# ]] && continue
echo "::add-mask::$value"
echo "${key}=${value}" >> "$GITHUB_ENV"
done
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: marksyncr-chrome
- name: Authenticate with Chrome Web Store
id: auth
run: |
RESPONSE=$(curl -sS -X POST "https://oauth2.googleapis.com/token" \
-d "client_id=${{ env.CHROME_CLIENT_ID }}" \
-d "client_secret=${{ env.CHROME_CLIENT_SECRET }}" \
-d "refresh_token=${{ env.CHROME_REFRESH_TOKEN }}" \
-d "grant_type=refresh_token")
ACCESS_TOKEN=$(echo "$RESPONSE" | jq -r '.access_token // empty')
if [[ -z "$ACCESS_TOKEN" ]]; then
echo "::error::Failed to obtain Chrome Web Store access token"
echo "$RESPONSE" | jq '{error, error_description}' 2>/dev/null || echo "$RESPONSE"
exit 1
fi
echo "::add-mask::$ACCESS_TOKEN"
echo "token=$ACCESS_TOKEN" >> "$GITHUB_OUTPUT"
echo "Chrome Web Store authentication successful"
- name: Upload to Chrome Web Store
run: |
RESPONSE=$(curl -sS \
-X PUT \
-H "Authorization: Bearer ${{ steps.auth.outputs.token }}" \
-H "x-goog-api-version: 2" \
-T marksyncr-chrome.zip \
"https://www.googleapis.com/upload/chromewebstore/v1.1/items/${{ env.CHROME_EXTENSION_ID }}")
echo "Upload response:"
echo "$RESPONSE" | jq .
UPLOAD_STATE=$(echo "$RESPONSE" | jq -r '.uploadState')
if [[ "$UPLOAD_STATE" != "SUCCESS" ]]; then
echo "::error::Chrome upload failed with state: $UPLOAD_STATE"
echo "$RESPONSE" | jq '.itemError // .'
exit 1
fi
echo "Chrome extension uploaded successfully"
- name: Submit to Chrome Web Store for review
run: |
RESPONSE=$(curl -sS \
-X POST \
-H "Authorization: Bearer ${{ steps.auth.outputs.token }}" \
-H "x-goog-api-version: 2" \
-H "Content-Length: 0" \
"https://www.googleapis.com/chromewebstore/v1.1/items/${{ env.CHROME_EXTENSION_ID }}/publish")
echo "Publish response:"
echo "$RESPONSE" | jq .
STATUS=$(echo "$RESPONSE" | jq -r '.status[0] // empty')
if [[ "$STATUS" != "OK" && "$STATUS" != "PUBLISHED_WITH_FRICTION_WARNING" && "$STATUS" != "PENDING_REVIEW" ]]; then
echo "::error::Chrome publish failed with status: $STATUS"
echo "$RESPONSE" | jq '.statusDetail // .'
exit 1
fi
echo "Chrome extension v${{ needs.build.outputs.version }} submitted (status: $STATUS)"
firefox-release:
name: Publish to Firefox Add-ons
needs: build
if: |
github.ref_type == 'tag' ||
(github.event_name == 'workflow_dispatch' && inputs.publish)
runs-on: ubuntu-latest
steps:
- name: Load environment variables
run: |
echo "${{ secrets.ENV_FILE }}" | while IFS='=' read -r key value; do
[[ -z "$key" || "$key" =~ ^# ]] && continue
echo "::add-mask::$value"
echo "${key}=${value}" >> "$GITHUB_ENV"
done
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: marksyncr-firefox
- name: Unpack extension
run: |
mkdir -p extension
unzip marksyncr-firefox.zip -d extension
echo "Extension contents:"
ls -la extension/
- uses: actions/setup-node@v4
with:
node-version: "24"
- name: Install web-ext
run: npm install -g web-ext
- name: Submit to AMO
run: |
web-ext sign \
--source-dir ./extension \
--artifacts-dir ./artifacts \
--api-key "${{ env.FIREFOX_JWT_ISSUER }}" \
--api-secret "${{ env.FIREFOX_JWT_SECRET }}" \
--channel listed \
--approval-timeout 0
echo "Firefox extension v${{ needs.build.outputs.version }} submitted to AMO"