-
-
Notifications
You must be signed in to change notification settings - Fork 711
ci: add canary publish workflow using npm Trusted Publisher (OIDC) #2285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
e367178
0c99c82
afd4b84
7b71bdb
29a872c
1f1bbec
39b1949
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,232 @@ | ||||||
| name: Publish | ||||||
|
|
||||||
| # Handles two scenarios: | ||||||
| # 1. Canary publish: auto-triggered on push to master | ||||||
| # 2. PR prerelease: manually triggered by Liz for trusted testers | ||||||
| # | ||||||
| # Manual trigger (Liz uses this via gh CLI): | ||||||
| # gh workflow run publish.yml \ | ||||||
| # --repo dexie/Dexie.js \ | ||||||
| # --ref <branch-name> \ | ||||||
| # -f mode=pr \ | ||||||
| # -f pr_number=2253 \ | ||||||
| # -f packages=dexie-cloud-addon \ | ||||||
| # -f requester_discord_id=321912613246337024 \ | ||||||
| # -f build_number=1 | ||||||
|
|
||||||
| on: | ||||||
| push: | ||||||
| branches: [master] | ||||||
| workflow_dispatch: | ||||||
| inputs: | ||||||
| mode: | ||||||
| description: 'Publish mode' | ||||||
| required: true | ||||||
| default: 'pr' | ||||||
| type: choice | ||||||
| options: | ||||||
| - pr | ||||||
| - canary | ||||||
| pr_number: | ||||||
| description: 'PR number (required for mode=pr, e.g. 2253)' | ||||||
| required: false | ||||||
| type: string | ||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||
| packages: | ||||||
| description: 'Packages to publish (comma-separated or "all")' | ||||||
| required: false | ||||||
| default: 'all' | ||||||
| type: string | ||||||
| build_number: | ||||||
| description: 'Build number suffix for PR mode (increment if re-running)' | ||||||
| required: false | ||||||
| default: '1' | ||||||
| type: string | ||||||
| requester_discord_id: | ||||||
| description: 'Discord user ID of the person who requested the prerelease' | ||||||
| required: false | ||||||
| type: string | ||||||
|
|
||||||
| jobs: | ||||||
| publish: | ||||||
| name: Publish to npm | ||||||
| runs-on: ubuntu-latest | ||||||
| permissions: | ||||||
| contents: read | ||||||
| id-token: write # required for OIDC Trusted Publisher | ||||||
|
|
||||||
| steps: | ||||||
| - uses: actions/checkout@v4 | ||||||
|
|
||||||
| - uses: pnpm/action-setup@v4 | ||||||
| with: | ||||||
| version: latest | ||||||
|
|
||||||
| - uses: actions/setup-node@v4 | ||||||
| with: | ||||||
| node-version: 22 | ||||||
| registry-url: https://registry.npmjs.org | ||||||
|
|
||||||
| # npm must be upgraded for OIDC Trusted Publisher to work | ||||||
| - name: Upgrade npm | ||||||
| run: npm install -g npm@latest | ||||||
|
|
||||||
| - name: Install dependencies | ||||||
| run: pnpm install | ||||||
|
|
||||||
| # Build in dependency order | ||||||
| - name: Build dexie | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build y-dexie | ||||||
| working-directory: addons/y-dexie | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-react-hooks | ||||||
| working-directory: libs/dexie-react-hooks | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-cloud-common | ||||||
| working-directory: libs/dexie-cloud-common | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-cloud-addon | ||||||
| working-directory: addons/dexie-cloud | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-export-import | ||||||
| working-directory: addons/dexie-export-import | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-svelte-query | ||||||
| working-directory: libs/dexie-svelte-query | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-observable | ||||||
| working-directory: addons/Dexie.Observable | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Build dexie-syncable | ||||||
| working-directory: addons/Dexie.Syncable | ||||||
| run: pnpm run build | ||||||
|
|
||||||
| - name: Publish packages | ||||||
| id: publish | ||||||
| run: | | ||||||
| # Determine mode: push to master = canary, workflow_dispatch = use input | ||||||
| if [ "${{ github.event_name }}" = "push" ]; then | ||||||
| MODE="canary" | ||||||
| else | ||||||
| MODE="${{ inputs.mode }}" | ||||||
| fi | ||||||
|
|
||||||
| PR="${{ inputs.pr_number }}" | ||||||
| BUILD="${{ inputs.build_number }}" | ||||||
| PACKAGES="${{ inputs.packages }}" | ||||||
| [ -z "$PACKAGES" ] && PACKAGES="all" | ||||||
|
|
||||||
| PUBLISHED_VERSIONS="" | ||||||
|
|
||||||
| publish_pkg() { | ||||||
| local PKG_NAME="$1" | ||||||
| local PKG_DIR="$2" | ||||||
|
|
||||||
| # Check if this package should be published | ||||||
| local SHOULD_PUBLISH=false | ||||||
| if [ "$PACKAGES" = "all" ]; then | ||||||
| SHOULD_PUBLISH=true | ||||||
| else | ||||||
| IFS=',' read -ra PKG_LIST <<< "$PACKAGES" | ||||||
| for p in "${PKG_LIST[@]}"; do | ||||||
| if [ "$(echo $p | tr -d ' ')" = "$PKG_NAME" ]; then | ||||||
| SHOULD_PUBLISH=true | ||||||
| break | ||||||
| fi | ||||||
| done | ||||||
| fi | ||||||
|
|
||||||
| if [ "$SHOULD_PUBLISH" = "false" ]; then | ||||||
| echo "Skipping $PKG_NAME (not in requested packages)" | ||||||
| return | ||||||
| fi | ||||||
|
|
||||||
| local BASE_VERSION=$(node -p "require('./${PKG_DIR}/package.json').version") | ||||||
|
|
||||||
| if [ "$MODE" = "canary" ]; then | ||||||
| # Canary: publish as-is if not already published | ||||||
| local PUBLISHED=$(npm show ${PKG_NAME}@${BASE_VERSION} version 2>/dev/null || echo "") | ||||||
| if [ -n "$PUBLISHED" ]; then | ||||||
| echo "${PKG_NAME}@${BASE_VERSION} already published, skipping." | ||||||
| return | ||||||
| fi | ||||||
| local PUBLISH_VERSION="$BASE_VERSION" | ||||||
| local TAG="canary" | ||||||
| else | ||||||
| # PR prerelease: append -prNNN.K suffix | ||||||
| local PUBLISH_VERSION="${BASE_VERSION}-pr${PR}.${BUILD}" | ||||||
| local TAG="pr${PR}" | ||||||
|
|
||||||
| # Temporarily patch version | ||||||
| node -e " | ||||||
| const fs = require('fs'); | ||||||
| const pkg = JSON.parse(fs.readFileSync('./${PKG_DIR}/package.json', 'utf8')); | ||||||
| pkg.version = '${PUBLISH_VERSION}'; | ||||||
| fs.writeFileSync('./${PKG_DIR}/package.json', JSON.stringify(pkg, null, 2) + '\n'); | ||||||
| " | ||||||
| fi | ||||||
|
|
||||||
| echo "Publishing ${PKG_NAME}@${PUBLISH_VERSION} with tag ${TAG}..." | ||||||
| (cd "${PKG_DIR}" && pnpm publish --tag "${TAG}" --provenance --no-git-checks) | ||||||
|
|
||||||
| # Restore original version after PR publish | ||||||
| if [ "$MODE" = "pr" ]; then | ||||||
| node -e " | ||||||
| const fs = require('fs'); | ||||||
| const pkg = JSON.parse(fs.readFileSync('./${PKG_DIR}/package.json', 'utf8')); | ||||||
| pkg.version = '${BASE_VERSION}'; | ||||||
| fs.writeFileSync('./${PKG_DIR}/package.json', JSON.stringify(pkg, null, 2) + '\n'); | ||||||
| " | ||||||
| fi | ||||||
|
|
||||||
| PUBLISHED_VERSIONS="${PUBLISHED_VERSIONS}\n- \`npm install ${PKG_NAME}@${PUBLISH_VERSION}\`" | ||||||
| } | ||||||
|
|
||||||
| publish_pkg "dexie" "." | ||||||
| publish_pkg "dexie-cloud-common" "libs/dexie-cloud-common" | ||||||
| publish_pkg "dexie-react-hooks" "libs/dexie-react-hooks" | ||||||
| publish_pkg "dexie-svelte-query" "libs/dexie-svelte-query" | ||||||
| publish_pkg "dexie-export-import" "addons/dexie-export-import" | ||||||
| publish_pkg "dexie-observable" "addons/Dexie.Observable" | ||||||
| publish_pkg "dexie-syncable" "addons/Dexie.Syncable" | ||||||
| publish_pkg "y-dexie" "addons/y-dexie" | ||||||
| publish_pkg "dexie-cloud-addon" "addons/dexie-cloud" | ||||||
|
Comment on lines
+201
to
+207
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Publish order should follow dependency order to reduce broken partial releases. At Line 203, 🔧 Proposed fix (match topological order) publish_pkg "dexie" "."
publish_pkg "dexie-cloud-common" "libs/dexie-cloud-common"
- publish_pkg "dexie-react-hooks" "libs/dexie-react-hooks"
publish_pkg "dexie-svelte-query" "libs/dexie-svelte-query"
- publish_pkg "dexie-export-import" "addons/dexie-export-import"
publish_pkg "y-dexie" "addons/y-dexie"
+ publish_pkg "dexie-export-import" "addons/dexie-export-import"
+ publish_pkg "dexie-react-hooks" "libs/dexie-react-hooks"
publish_pkg "dexie-cloud-addon" "addons/dexie-cloud"🤖 Prompt for AI Agents |
||||||
|
|
||||||
| echo "mode=$MODE" >> $GITHUB_OUTPUT | ||||||
| echo "published_versions<<EOF" >> $GITHUB_OUTPUT | ||||||
| echo -e "$PUBLISHED_VERSIONS" >> $GITHUB_OUTPUT | ||||||
| echo "EOF" >> $GITHUB_OUTPUT | ||||||
|
|
||||||
| - name: Notify via Discord (PR mode only) | ||||||
| if: inputs.mode == 'pr' || (github.event_name == 'workflow_dispatch' && inputs.mode == 'pr') | ||||||
| env: | ||||||
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_LIZ_LEAD_DEV }} | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the documented webhook secret name to avoid notification misconfiguration. Line 223 uses 🔧 Proposed fix- DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_LIZ_LEAD_DEV }}
+ DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL }}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| run: | | ||||||
| PR="${{ inputs.pr_number }}" | ||||||
| REQUESTER="${{ inputs.requester_discord_id }}" | ||||||
| STATUS="${{ job.status }}" | ||||||
| BRANCH="${GITHUB_REF_NAME}" | ||||||
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | ||||||
|
|
||||||
| if [ "$STATUS" = "success" ]; then | ||||||
| MENTION="" | ||||||
| if [ -n "$REQUESTER" ]; then | ||||||
| MENTION=" (requested by <@${REQUESTER}>)" | ||||||
| fi | ||||||
| VERSIONS="${{ steps.publish.outputs.published_versions }}" | ||||||
| MESSAGE="✅ **PR #${PR} prerelease published**${MENTION}\n\nBranch: \`${BRANCH}\`\n\n${VERSIONS}\n\n[View run](${RUN_URL})" | ||||||
| else | ||||||
| MESSAGE="❌ **PR #${PR} prerelease FAILED** — [View run](${RUN_URL})" | ||||||
| fi | ||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||
|
|
||||||
| curl -s -X POST "$DISCORD_WEBHOOK" \ | ||||||
| -H "Content-Type: application/json" \ | ||||||
| -d "{\"content\": \"$MESSAGE\"}" | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid committing real Discord user identifiers in workflow comments.
Line 14 includes a concrete Discord ID. Use a placeholder to avoid publishing user identifiers in repo metadata.
🔧 Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 Betterleaks (1.1.1)
[high] 14-14: Identified a Discord client ID, which may lead to unauthorized integrations and data exposure in Discord applications.
(discord-client-id)
🤖 Prompt for AI Agents