Skip to content

Manual Package Publish #99

Manual Package Publish

Manual Package Publish #99

name: Manual Package Publish
on:
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g., 1.0.0, patch, minor, major)"
required: true
default: "patch"
type: string
npm_tag:
description: "NPM tag to publish with (e.g., latest, beta, alpha)"
required: true
default: "latest"
type: string
dry_run:
description: "Run in dry-run mode (no actual publish)"
required: false
default: false
type: boolean
notify_skills_repo:
description: "Notify the skills repo about the release"
required: false
default: true
type: boolean
env:
CLI_PACKAGE_DIR: packages/cli
# This workflow deliberately does NOT run the Wix gateway proxy: the gateway
# cannot carry `npm publish` (it rejects `PUT /<package>`), so per secplatform's
# interim policy for OSS repos this job relies on `--frozen-lockfile` plus
# bunfig.toml's minimumReleaseAge instead. It resolves nothing, so dropping the
# gateway does not widen what it can pull. Exemption lives in
# .github/scripts/check_wix_proxy_steps.py.
jobs:
publish:
runs-on: ubuntu-latest
permissions:
# contents: write for the release commit, tag, and GitHub Release.
# id-token: write for npm trusted publishing (OIDC).
contents: write
id-token: write
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.BASE44_GITHUB_ACTIONS_APP_ID }}
private-key: ${{ secrets.BASE44_GITHUB_ACTIONS_APP_PRIVATE_KEY }}
owner: base44
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.generate-token.outputs.token }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".node-version"
registry-url: "https://registry.npmjs.org"
# No `npm install -g npm@latest`: trusted publishing needs npm >= 11.5.1, and
# the npm bundled with .node-version's Node 24 is already newer.
- name: Setup Bun
id: setup-bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v5
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-version }}-${{ hashFiles('**/bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-version }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Set version
working-directory: ${{ env.CLI_PACKAGE_DIR }}
# `npm version` takes both a keyword (patch/minor/major) and an explicit
# version, so it replaces the old branch. It also replaces `bunx json-bump`,
# which fetched an undeclared package at run time, outside the cooldown.
run: |
npm version "${{ github.event.inputs.version }}" --no-git-tag-version --no-workspaces
echo "NEW_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV
- name: Build package
run: bun run build
working-directory: ${{ env.CLI_PACKAGE_DIR }}
- name: Build standalone binaries
run: bun run build:binaries
working-directory: ${{ env.CLI_PACKAGE_DIR }}
- name: Package binaries for release
run: bun run package:binaries
working-directory: ${{ env.CLI_PACKAGE_DIR }}
- name: Upload sourcemaps to PostHog
if: github.event.inputs.dry_run == 'false'
uses: PostHog/upload-source-maps@v0.4.6
with:
directory: ./${{ env.CLI_PACKAGE_DIR }}/dist/cli
env-id: ${{ vars.POSTHOG_PROJECT_ID }}
cli-token: ${{ secrets.POSTHOG_CLI_API_KEY }}
version: ${{ env.NEW_VERSION }}
- name: Show package info
working-directory: ${{ env.CLI_PACKAGE_DIR }}
run: |
echo "Package name: $(node -p "require('./package.json').name")"
echo "Version: ${{ env.NEW_VERSION }}"
echo "NPM tag: ${{ github.event.inputs.npm_tag }}"
echo "Dry run: ${{ github.event.inputs.dry_run }}"
- name: Publish to NPM
# Authenticates via npm trusted publishing (OIDC), so no NPM_TOKEN reaches
# the build. Needs a trusted publisher for `base44` on npmjs.com registered
# against this repo and this workflow filename — the registry keys on the
# filename, so each publish workflow needs its own entry.
working-directory: ${{ env.CLI_PACKAGE_DIR }}
run: |
# Remove devDependencies before publish (everything is bundled)
cp package.json package.json.bak
jq 'del(.devDependencies)' package.json > package.json.tmp && mv package.json.tmp package.json
npm publish --tag ${{ github.event.inputs.npm_tag }} ${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}
mv package.json.bak package.json
- name: Create Git tag
if: github.event.inputs.dry_run == 'false'
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
git add ${{ env.CLI_PACKAGE_DIR }}/package.json
git commit -m "chore: release v${{ env.NEW_VERSION }}"
git tag v${{ env.NEW_VERSION }}
git push origin HEAD:${{ github.ref }}
git push origin v${{ env.NEW_VERSION }}
- name: Create GitHub Release and upload binaries
if: github.event.inputs.dry_run == 'false'
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
RELEASE_URL=$(gh release create "v${{ env.NEW_VERSION }}" \
--title "Release v${{ env.NEW_VERSION }}" \
--notes "## Installation
**npm:**
\`\`\`bash
npm install -g base44@${{ github.event.inputs.npm_tag }}
\`\`\`
**Homebrew:**
\`\`\`bash
brew install base44/tap/base44
\`\`\`
**Version:** ${{ env.NEW_VERSION }}
**NPM Tag:** ${{ github.event.inputs.npm_tag }}" \
${{ env.CLI_PACKAGE_DIR }}/dist/binaries/base44-*.tar.gz)
echo "RELEASE_URL=$RELEASE_URL" >> $GITHUB_ENV
- name: Update Homebrew Tap
if: github.event.inputs.dry_run == 'false' && github.event.inputs.npm_tag == 'latest'
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: bash ${{ env.CLI_PACKAGE_DIR }}/infra/homebrew/update-tap.sh "${{ env.NEW_VERSION }}" "${{ env.CLI_PACKAGE_DIR }}/dist/binaries"
- name: Notify skills repo
if: github.event.inputs.dry_run == 'false' && github.event.inputs.notify_skills_repo == 'true'
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ steps.generate-token.outputs.token }}
repository: base44/skills
event-type: cli-release
client-payload: |
{
"version": "v${{ env.NEW_VERSION }}",
"release_url": "${{ env.RELEASE_URL }}",
"release_name": "Release v${{ env.NEW_VERSION }}"
}