Skip to content

Merge pull request #132 from richardadonnell:feat/notification-click-… #8

Merge pull request #132 from richardadonnell:feat/notification-click-…

Merge pull request #132 from richardadonnell:feat/notification-click-… #8

name: Release Publish
on:
push:
branches:
- main
permissions:
contents: write
concurrency:
group: release-main
cancel-in-progress: false
jobs:
release:
runs-on: ubuntu-latest
environment: ${{ 'production' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: app-v3/package-lock.json
- name: Install dependencies
working-directory: app-v3
run: npm ci
- name: Resolve release metadata
id: meta
shell: bash
run: |
VERSION="$(node -p "require('./app-v3/package.json').version")"
BUILD_TAG="v${VERSION}-main.${GITHUB_RUN_NUMBER}"
RELEASE_NAME="upwork-job-scraper@${VERSION}-main.${GITHUB_RUN_NUMBER}"
echo "tag=$BUILD_TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "release=$RELEASE_NAME" >> "$GITHUB_OUTPUT"
- name: Build and package
working-directory: app-v3
env:
WXT_SENTRY_DSN: ${{ vars['WXT_SENTRY_DSN'] }}
WXT_SENTRY_ENVIRONMENT: production
WXT_SENTRY_RELEASE: ${{ steps.meta.outputs.release }}
SENTRY_SOURCEMAPS: "true"
SENTRY_UPLOAD_SOURCEMAPS_VITE: "false"
run: npm run zip
- name: Verify manifest version matches package version
shell: bash
run: |
PACKAGE_VERSION="$(node -p "require('./app-v3/package.json').version")"
MANIFEST_VERSION="$(node -p "require('./app-v3/.output/chrome-mv3/manifest.json').version")"
echo "package.json version: $PACKAGE_VERSION"
echo "manifest version: $MANIFEST_VERSION"
if [[ "$PACKAGE_VERSION" != "$MANIFEST_VERSION" ]]; then
echo "Version mismatch: app-v3/package.json and built manifest.json differ."
exit 1
fi
- name: Create or update GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
TAG="${{ steps.meta.outputs.tag }}"
TITLE="Upwork Job Scraper main build v${{ steps.meta.outputs.version }} (#${{ github.run_number }})"
if gh release view "$TAG" >/dev/null 2>&1; then
gh release edit "$TAG" --title "$TITLE"
else
gh release create "$TAG" --title "$TITLE" --generate-notes
fi
- name: Locate Chrome ZIP
id: zip
shell: bash
run: |
ZIP_FILE="$(ls app-v3/.output/*-chrome.zip | head -n 1)"
if [[ -z "$ZIP_FILE" ]]; then
echo "No Chrome zip artifact found under app-v3/.output"
exit 1
fi
echo "zip_file=$ZIP_FILE" >> "$GITHUB_OUTPUT"
- name: Upload ZIP to GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
gh release upload "${{ steps.meta.outputs.tag }}" "${{ steps.zip.outputs.zip_file }}" --clobber
- name: Upload sourcemaps to Sentry
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars['SENTRY_ORG'] }}
SENTRY_PROJECT: ${{ vars['SENTRY_PROJECT'] }}
SENTRY_RELEASE: ${{ steps.meta.outputs.release }}
shell: bash
run: |
npx --yes @sentry/cli sourcemaps inject app-v3/.output/chrome-mv3
npx --yes @sentry/cli sourcemaps upload \
--release "$SENTRY_RELEASE" \
--url-prefix "~/" \
app-v3/.output/chrome-mv3
- name: Exchange refresh token for access token
id: token
env:
CWS_CLIENT_ID: ${{ secrets['CWS_CLIENT_ID'] }}
CWS_CLIENT_SECRET: ${{ secrets['CWS_CLIENT_SECRET'] }}
CWS_REFRESH_TOKEN: ${{ secrets['CWS_REFRESH_TOKEN'] }}
shell: bash
run: |
TOKEN_JSON="$(curl --fail --silent --show-error https://oauth2.googleapis.com/token \
-d client_id="$CWS_CLIENT_ID" \
-d client_secret="$CWS_CLIENT_SECRET" \
-d refresh_token="$CWS_REFRESH_TOKEN" \
-d grant_type=refresh_token)"
ACCESS_TOKEN="$(echo "$TOKEN_JSON" | python -c "import json,sys; print(json.load(sys.stdin).get('access_token',''))")"
if [[ -z "$ACCESS_TOKEN" ]]; then
echo "Failed to obtain access token from refresh token flow."
exit 1
fi
echo "::add-mask::$ACCESS_TOKEN"
echo "access_token=$ACCESS_TOKEN" >> "$GITHUB_OUTPUT"
- name: Upload to Chrome Web Store (upload-only)
env:
ACCESS_TOKEN: ${{ steps.token.outputs.access_token }}
CWS_PUBLISHER_ID: ${{ vars['CWS_PUBLISHER_ID'] }}
CWS_EXTENSION_ID: ${{ vars['CWS_EXTENSION_ID'] }}
ZIP_FILE: ${{ steps.zip.outputs.zip_file }}
shell: bash
run: |
RESPONSE="$(curl --fail --silent --show-error \
-X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/zip" \
--data-binary "@$ZIP_FILE" \
"https://chromewebstore.googleapis.com/upload/v2/publishers/$CWS_PUBLISHER_ID/items/$CWS_EXTENSION_ID:upload")"
echo "$RESPONSE"
STATE="$(echo "$RESPONSE" | python -c "import json,sys; print(json.load(sys.stdin).get('uploadState',''))")"
if [[ "$STATE" != "SUCCESS" && "$STATE" != "SUCCEEDED" ]]; then
echo "Chrome Web Store upload did not return SUCCESS/SUCCEEDED."
exit 1
fi
- name: Manual publish reminder
run: echo "Upload complete. Publish manually in the Chrome Web Store dashboard."