diff --git a/.github/workflows/openclaw-npm-release.yml b/.github/workflows/openclaw-npm-release.yml index 903bba74706..eb9076f94be 100644 --- a/.github/workflows/openclaw-npm-release.yml +++ b/.github/workflows/openclaw-npm-release.yml @@ -4,9 +4,15 @@ on: push: tags: - "v*" + workflow_dispatch: + inputs: + tag: + description: Release tag to publish (for example v2026.3.14 or v2026.3.14-beta.1) + required: true + type: string concurrency: - group: openclaw-npm-release-${{ github.ref }} + group: openclaw-npm-release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }} cancel-in-progress: false env: @@ -15,8 +21,8 @@ env: PNPM_VERSION: "10.23.0" jobs: - publish_openclaw_npm: - # npm trusted publishing + provenance requires a GitHub-hosted runner. + preview_openclaw_npm: + if: github.event_name == 'push' runs-on: ubuntu-latest permissions: contents: read @@ -35,13 +41,87 @@ jobs: install-bun: "false" use-sticky-disk: "false" + - name: Print release plan + env: + RELEASE_TAG: ${{ github.ref_name }} + run: | + set -euo pipefail + echo "Release plan for ${RELEASE_TAG}:" + echo "git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main" + echo "pnpm release:openclaw:npm:check" + echo "pnpm check" + echo "pnpm build" + echo "pnpm release:check" + bash scripts/openclaw-npm-publish.sh --dry-run + - name: Validate release tag and package metadata env: - RELEASE_SHA: ${{ github.sha }} RELEASE_TAG: ${{ github.ref_name }} RELEASE_MAIN_REF: origin/main run: | set -euo pipefail + RELEASE_SHA=$(git rev-parse HEAD) + export RELEASE_SHA RELEASE_TAG RELEASE_MAIN_REF + # Fetch the full main ref so merge-base ancestry checks keep working + # for older tagged commits that are still contained in main. + git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main + pnpm release:openclaw:npm:check + + - name: Ensure version is not already published + run: | + set -euo pipefail + PACKAGE_VERSION=$(node -p "require('./package.json').version") + + if npm view "openclaw@${PACKAGE_VERSION}" version >/dev/null 2>&1; then + echo "openclaw@${PACKAGE_VERSION} is already published on npm." + exit 1 + fi + + echo "Previewing openclaw@${PACKAGE_VERSION}" + + - name: Check + run: pnpm check + + - name: Build + run: pnpm build + + - name: Verify release contents + run: pnpm release:check + + - name: Preview publish command + run: bash scripts/openclaw-npm-publish.sh --dry-run + + publish_openclaw_npm: + if: github.event_name == 'workflow_dispatch' + # npm trusted publishing + provenance requires a GitHub-hosted runner. + runs-on: ubuntu-latest + environment: npm-release + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + ref: refs/tags/${{ inputs.tag }} + fetch-depth: 0 + + - name: Setup Node environment + uses: ./.github/actions/setup-node-env + with: + node-version: ${{ env.NODE_VERSION }} + pnpm-version: ${{ env.PNPM_VERSION }} + install-bun: "false" + use-sticky-disk: "false" + + - name: Validate release tag and package metadata + env: + RELEASE_TAG: ${{ inputs.tag }} + RELEASE_MAIN_REF: origin/main + run: | + set -euo pipefail + RELEASE_SHA=$(git rev-parse HEAD) + export RELEASE_SHA RELEASE_TAG RELEASE_MAIN_REF # Fetch the full main ref so merge-base ancestry checks keep working # for older tagged commits that are still contained in main. git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main @@ -71,15 +151,4 @@ jobs: - name: Publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - set -euo pipefail - if [[ -n "${NODE_AUTH_TOKEN:-}" ]]; then - printf '//registry.npmjs.org/:_authToken=%s\n' "$NODE_AUTH_TOKEN" > "$HOME/.npmrc" - fi - PACKAGE_VERSION=$(node -p "require('./package.json').version") - - if [[ "$PACKAGE_VERSION" == *-beta.* ]]; then - npm publish --access public --tag beta --provenance - else - npm publish --access public --provenance - fi + run: bash scripts/openclaw-npm-publish.sh --publish diff --git a/scripts/openclaw-npm-publish.sh b/scripts/openclaw-npm-publish.sh new file mode 100644 index 00000000000..8babee22fe5 --- /dev/null +++ b/scripts/openclaw-npm-publish.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -euo pipefail + +mode="${1:-}" + +if [[ "${mode}" != "--dry-run" && "${mode}" != "--publish" ]]; then + echo "usage: bash scripts/openclaw-npm-publish.sh [--dry-run|--publish]" >&2 + exit 2 +fi + +package_version="$(node -p "require('./package.json').version")" +publish_cmd=(npm publish --access public --provenance) + +if [[ "${package_version}" == *-beta.* ]]; then + publish_cmd=(npm publish --access public --tag beta --provenance) +fi + +if [[ -n "${NODE_AUTH_TOKEN:-}" ]]; then + if [[ "${mode}" == "--dry-run" ]]; then + echo 'Would write npm auth config to $HOME/.npmrc using NODE_AUTH_TOKEN' + else + printf '//registry.npmjs.org/:_authToken=%s\n' "${NODE_AUTH_TOKEN}" > "${HOME}/.npmrc" + fi +fi + +printf 'Publish command:' +printf ' %q' "${publish_cmd[@]}" +printf '\n' + +if [[ "${mode}" == "--dry-run" ]]; then + exit 0 +fi + +"${publish_cmd[@]}"