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
154 changes: 154 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: Publish Extensions

on:
workflow_dispatch: # Manual trigger
push:
tags:
- 'v*' # Trigger on version tags like v1.0.4

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'pnpm'

- name: Install dependencies
run: pnpm install

- name: Build extensions
run: pnpm run build

- name: Get local versions
id: versions
run: |
CHROME_VERSION=$(jq -r '.version' extension-chrome/manifest.json)
FIREFOX_VERSION=$(jq -r '.version' extension-firefox/manifest.json)
echo "chrome=$CHROME_VERSION" >> $GITHUB_OUTPUT
echo "firefox=$FIREFOX_VERSION" >> $GITHUB_OUTPUT

# Chrome Web Store
- name: Check Chrome Web Store version
id: chrome-check
continue-on-error: true
run: |
STORE_VERSION=$(curl -s "https://chromewebstore.google.com/detail/pfplfifdaaaalkefgnknfgoiabegcbmf" | grep -oP '"version":"[^"]*"' | head -1 | cut -d'"' -f4)
echo "Current Chrome version: $STORE_VERSION"
echo "Local Chrome version: ${{ steps.versions.outputs.chrome }}"
if [ "$STORE_VERSION" != "${{ steps.versions.outputs.chrome }}" ]; then
echo "needs_publish=true" >> $GITHUB_OUTPUT
else
echo "needs_publish=false" >> $GITHUB_OUTPUT
fi

- name: Publish to Chrome Web Store
if: steps.chrome-check.outputs.needs_publish == 'true'
run: |
cd dist/chrome
zip -r ../../chrome-extension.zip .
cd ../..
npx publish-browser-extension \
--chrome-zip chrome-extension.zip \
--chrome-extension-id pfplfifdaaaalkefgnknfgoiabegcbmf \
--chrome-client-id "${{ vars.CHROME_CLIENT_ID }}" \
--chrome-client-secret "${{ secrets.CHROME_CLIENT_SECRET }}" \
--chrome-refresh-token "${{ secrets.CHROME_REFRESH_TOKEN }}"

- name: Skip Chrome publish
if: steps.chrome-check.outputs.needs_publish != 'true'
run: echo "✓ Chrome Web Store is already up to date"

# Firefox Add-ons
- name: Check Firefox Add-ons version
id: firefox-check
continue-on-error: true
run: |
STORE_VERSION=$(curl -s "https://addons.mozilla.org/api/v5/addons/addon/markdown-printer/" | jq -r '.current_version.version')
echo "Current Firefox version: $STORE_VERSION"
echo "Local Firefox version: ${{ steps.versions.outputs.firefox }}"
if [ "$STORE_VERSION" != "${{ steps.versions.outputs.firefox }}" ]; then
echo "needs_publish=true" >> $GITHUB_OUTPUT
else
echo "needs_publish=false" >> $GITHUB_OUTPUT
fi

- name: Publish to Firefox Add-ons
if: steps.firefox-check.outputs.needs_publish == 'true'
run: |
cd dist/firefox
zip -r ../../firefox-extension.zip .
cd ../..
zip -r firefox-sources.zip . -x "node_modules/*" -x "dist/*" -x ".git/*"
npx publish-browser-extension \
--firefox-zip firefox-extension.zip \
--firefox-sources-zip firefox-sources.zip \
--firefox-extension-id markdown-printer \
--firefox-jwt-issuer "${{ vars.FIREFOX_ISSUER }}" \
--firefox-jwt-secret "${{ secrets.FIREFOX_SECRET }}"

- name: Skip Firefox publish
if: steps.firefox-check.outputs.needs_publish != 'true'
run: echo "✓ Firefox Add-ons is already up to date"

# Microsoft Edge Add-ons
- name: Check Edge Add-ons version
id: edge-check
continue-on-error: true
env:
EDGE_PRODUCT_ID: ${{ vars.EDGE_PRODUCT_ID }}
EDGE_CLIENT_ID: ${{ vars.EDGE_CLIENT_ID }}
EDGE_CLIENT_SECRET: ${{ secrets.EDGE_CLIENT_SECRET }}
run: |
# Get access token
TOKEN_RESPONSE=$(curl -s -X POST "https://login.microsoftonline.com/5c9eedce-81bc-42f3-8823-48ba6258b391/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=$EDGE_CLIENT_ID&scope=https://api.addons.microsoftedge.microsoft.com/.default&client_secret=$EDGE_CLIENT_SECRET&grant_type=client_credentials")
ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')

# Get current version
STORE_VERSION=$(curl -s "https://api.addons.microsoftedge.microsoft.com/v1/products/$EDGE_PRODUCT_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq -r '.lastPublishedVersion')

echo "Current Edge version: $STORE_VERSION"
echo "Local Chrome version: ${{ steps.versions.outputs.chrome }}"
if [ "$STORE_VERSION" != "${{ steps.versions.outputs.chrome }}" ]; then
echo "needs_publish=true" >> $GITHUB_OUTPUT
else
echo "needs_publish=false" >> $GITHUB_OUTPUT
fi

- name: Publish to Edge Add-ons
if: steps.edge-check.outputs.needs_publish == 'true'
run: |
cd dist/chrome
zip -r ../../edge-extension.zip .
cd ../..
npx publish-browser-extension \
--edge-zip edge-extension.zip \
--edge-product-id "${{ vars.EDGE_PRODUCT_ID }}" \
--edge-client-id "${{ vars.EDGE_CLIENT_ID }}" \
--edge-client-secret "${{ secrets.EDGE_CLIENT_SECRET }}"

- name: Skip Edge publish
if: steps.edge-check.outputs.needs_publish != 'true'
run: echo "✓ Edge Add-ons is already up to date"

# Summary
- name: Publish summary
run: |
echo "## Publication Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Chrome: ${{ steps.chrome-check.outputs.needs_publish == 'true' && '✓ Published' || '⊘ Skipped (up to date)' }}" >> $GITHUB_STEP_SUMMARY
echo "- Firefox: ${{ steps.firefox-check.outputs.needs_publish == 'true' && '✓ Published' || '⊘ Skipped (up to date)' }}" >> $GITHUB_STEP_SUMMARY
echo "- Edge: ${{ steps.edge-check.outputs.needs_publish == 'true' && '✓ Published' || '⊘ Skipped (up to date)' }}" >> $GITHUB_STEP_SUMMARY
144 changes: 144 additions & 0 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Publishing Guide

This guide explains how to automatically publish Markdown Printer to Chrome Web Store, Firefox Add-ons, and Edge Add-ons using GitHub Actions.

## How It Works

The workflow (`publish.yml`) automatically:

1. Checks the current published version on each store
2. Compares it with your local manifest version
3. **Only publishes to stores where the version is outdated**
4. Skips stores that are already up-to-date

This prevents unnecessary submissions and review delays!

## Setup

### 1. Install publish-browser-extension

```bash
pnpm add -D publish-browser-extension
```

### 2. Configure GitHub Secrets

Add these secrets to your repository at `Settings > Secrets and variables > Actions > Repository secrets`:

#### Chrome Web Store

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Enable the Chrome Web Store API
3. Create OAuth 2.0 credentials
4. Follow [this guide](https://developer.chrome.com/docs/webstore/using-api) to get:
- `CHROME_CLIENT_ID`
- `CHROME_CLIENT_SECRET`
- `CHROME_REFRESH_TOKEN`

#### Firefox Add-ons

1. Log in to [addons.mozilla.org](https://addons.mozilla.org/)
2. Go to **Tools > Manage API Keys**
3. Generate credentials:
- `FIREFOX_ISSUER`
- `FIREFOX_SECRET`

#### Microsoft Edge Add-ons

1. Sign in to [Partner Center](https://partner.microsoft.com/)
2. Visit the [Publish API page](https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi)
3. Click **Create API credentials**:
- `EDGE_PRODUCT_ID` (from your extension overview page)
- `EDGE_CLIENT_ID`
- `EDGE_CLIENT_SECRET`

## Usage

### Option 1: Manual Trigger

1. Go to `Actions` tab in GitHub
2. Select `Publish Extensions` workflow
3. Click `Run workflow`

The workflow will check all stores and only publish where needed.

### Option 2: Automatic on Tag

Create and push a version tag:

```bash
git tag v1.0.4
git push origin v1.0.4
```

The workflow will automatically run and publish to outdated stores.

## Version Management

### Update versions across all manifests

```bash
# Update version in package.json
npm version patch # or minor, or major

# Manually update the version in:
# - extension-chrome/manifest.json
# - extension-firefox/manifest.json

# Build and commit
pnpm run build
git add .
git commit -m "Bump version to 1.0.4"
git tag v1.0.4
git push origin main --tags
```

## Workflow Output

The workflow provides a summary showing which stores were published to:

```
Publication Summary
- Chrome: ✓ Published
- Firefox: ⊘ Skipped (up to date)
- Edge: ⊘ Skipped (up to date)
```

## Troubleshooting

### Chrome: "Invalid refresh token"

Wait an hour after setting up the Chrome Web Store API before generating the refresh token.

### Firefox: "Submission failed"

Ensure you've zipped the source code correctly and that your extension follows AMO guidelines.

### Edge: "Authentication failed"

Verify your Product ID is correct by checking your extension's overview page in Partner Center.

### Version check fails

If the version check step fails, the workflow will still attempt to publish (using `continue-on-error: true`). Check the logs for details.

## Manual Publishing

If you prefer to publish manually, you can use the CLI directly:

```bash
# Publish to specific stores
npx publish-browser-extension \
--chrome-zip dist/chrome.zip \
--chrome-extension-id pfplfifdaaaalkefgnknfgoiabegcbmf \
--chrome-client-id "$CHROME_CLIENT_ID" \
--chrome-client-secret "$CHROME_CLIENT_SECRET" \
--chrome-refresh-token "$CHROME_REFRESH_TOKEN"
```

## Notes

- First-time submissions must be done manually through each store's dashboard
- The workflow assumes you're using the same version for Chrome and Edge (both use extension-chrome)
- Source code is automatically zipped for Firefox submissions
- All submissions go through each store's review process before being published
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,16 @@ See [Pro Version README](extension-pro/README.md) for installation instructions.

## 🆚 Comparison

| Feature | Standard | Pro |
|---------|----------|-----|
| Installation | One-click | Requires setup script |
| Browser Support | Chrome, Edge, Firefox | Chrome, Edge, Firefox |
| Save location | Choose each time | Configurable default |
| Auto-open files | ❌ | ✅ |
| Settings | ❌ | ✅ |
| Chrome Web Store | ✅ [Available](https://chromewebstore.google.com/detail/markdown-printer/pfplfifdaaaalkefgnknfgoiabegcbmf) | ❌ Can't publish |
| Edge Add-ons | ✅ [Available](https://microsoftedge.microsoft.com/addons/detail/mlmakmhfnkbabnhhcnekleemamhpnmgk) | ❌ Can't publish |
| Firefox Add-ons | ✅ [Available](https://addons.mozilla.org/en-US/firefox/addon/markdown-printer/) | ❌ Can't publish |
| Feature | Standard | Pro |
| ---------------- | ---------------------------------------------------------------------------------------------------------- | --------------------- |
| Installation | One-click | Requires setup script |
| Browser Support | Chrome, Edge, Firefox | Chrome, Edge, Firefox |
| Save location | Choose each time | Configurable default |
| Auto-open files | ❌ | ✅ |
| Settings | ❌ | ✅ |
| Chrome Web Store | ✅ [Available](https://chromewebstore.google.com/detail/markdown-printer/pfplfifdaaaalkefgnknfgoiabegcbmf) | ❌ Can't publish |
| Edge Add-ons | ✅ [Available](https://microsoftedge.microsoft.com/addons/detail/mlmakmhfnkbabnhhcnekleemamhpnmgk) | ❌ Can't publish |
| Firefox Add-ons | ✅ [Available](https://addons.mozilla.org/en-US/firefox/addon/markdown-printer/) | ❌ Can't publish |

## 🛠️ Technical Details

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@types/jest": "^30.0.0",
"eslint": "^9.37.0",
"jest": "^30.2.0",
"prettier": "^3.6.2"
"prettier": "^3.6.2",
"publish-browser-extension": "^3.0.2"
}
}
Loading