Skip to content

docs: unify installation prompts across registries #404

docs: unify installation prompts across registries

docs: unify installation prompts across registries #404

Workflow file for this run

name: CI
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
release-metadata:
name: Release metadata
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
release_commit: ${{ steps.release.outputs.release_commit }}
release_tag: ${{ steps.release.outputs.tag }}
release_version: ${{ steps.release.outputs.version }}
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24.15.0"
- name: Validate release metadata
run: npm run check:versions
- name: Resolve release transition
id: release
run: node scripts/resolve-release-transition.mjs
- name: Detect release version change
shell: bash
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
RELEASE_VERSION: ${{ steps.release.outputs.version }}
run: |
set -euo pipefail
if [[ -z "$BASE_SHA" || "$BASE_SHA" =~ ^0+$ ]]; then
echo "No comparison commit is available; skipping release detection."
exit 0
fi
if ! git cat-file -e "${BASE_SHA}:package.json"; then
echo "::error::Cannot read package.json from comparison commit ${BASE_SHA}."
exit 1
fi
previous_version="$(
git show "${BASE_SHA}:package.json" |
node -p "JSON.parse(require('fs').readFileSync(0, 'utf8')).version"
)"
if [[ "$RELEASE_VERSION" == "$previous_version" ]]; then
echo "Package version remains ${RELEASE_VERSION}; no version-transition check is needed."
exit 0
fi
RELEASE_PREVIOUS_VERSION="$previous_version" npm run check:versions
echo "Package version increased from ${previous_version} to ${RELEASE_VERSION}."
validate:
name: ${{ matrix.os }} / Node.js ${{ matrix.node-version }} / OpenClaw ${{ matrix.openclaw_version }}
needs: release-metadata
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
node-version: "24.15.0"
openclaw_version: "2026.6.1"
validation: compatibility
- os: ubuntu-latest
node-version: "22.22.3"
openclaw_version: "2026.7.1"
validation: compatibility
- os: ubuntu-latest
node-version: "24.15.0"
openclaw_version: "2026.8.2"
validation: compatibility
- os: windows-latest
node-version: "24.15.0"
openclaw_version: "2026.8.2"
validation: compatibility
- os: ubuntu-latest
node-version: "24.15.0"
openclaw_version: "2026.9.1"
validation: compatibility
- os: ubuntu-latest
node-version: "22.22.3"
openclaw_version: "2026.9.2"
validation: compatibility
- os: ubuntu-latest
node-version: "24.15.0"
openclaw_version: "2026.9.2"
validation: strict
pack_check: true
dependency_audit: true
- os: ubuntu-latest
node-version: "26"
openclaw_version: "2026.9.2"
validation: compatibility
- os: windows-latest
node-version: "24.15.0"
openclaw_version: "2026.9.2"
validation: strict
- os: ubuntu-latest
node-version: "24"
openclaw_version: beta
validation: compatibility
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
check-latest: ${{ matrix.openclaw_version == 'beta' }}
cache: npm
cache-dependency-path: package-lock.json
registry-url: https://registry.npmjs.org
- name: Use lockfile-compatible npm
if: startsWith(matrix.node-version, '22.')
run: npm install --global npm@11.12.1 --no-audit --no-fund
- name: Install dependencies
run: npm ci
- name: Install compatibility OpenClaw
id: openclaw
if: matrix.validation == 'compatibility'
shell: bash
env:
OPENCLAW_SPEC: ${{ matrix.openclaw_version }}
run: |
set -euo pipefail
npm install --no-save --package-lock=false --ignore-scripts \
"openclaw@${OPENCLAW_SPEC}"
installed_version="$(node -p 'require("./node_modules/openclaw/package.json").version')"
if [[ "$OPENCLAW_SPEC" != "beta" && "$installed_version" != "$OPENCLAW_SPEC" ]]; then
echo "::error::Expected OpenClaw ${OPENCLAW_SPEC}, found ${installed_version}."
exit 1
fi
echo "Resolved OpenClaw ${OPENCLAW_SPEC} to ${installed_version}."
echo "installed_version=${installed_version}" >> "$GITHUB_OUTPUT"
- name: Verify plugin install and update commands
env:
OPENCLAW_EXPECTED_VERSION: ${{ steps.openclaw.outputs.installed_version || matrix.openclaw_version }}
run: node scripts/check-plugin-install-update.mjs
- name: Typecheck and build compatibility runtime
if: matrix.validation == 'compatibility'
run: npm run typecheck && npm run build
- name: Smoke test compatibility runtime
if: matrix.validation == 'compatibility'
env:
OPENCLAW_EXPECTED_VERSION: ${{ steps.openclaw.outputs.installed_version }}
run: node scripts/check-host-compatibility.mjs
- name: Audit all dependencies
if: matrix.dependency_audit
run: npm run audit:all
- name: Check project
if: matrix.validation == 'strict'
run: npm run check
- name: Smoke test current runtime
if: matrix.validation == 'strict'
env:
OPENCLAW_EXPECTED_VERSION: ${{ matrix.openclaw_version }}
run: node scripts/check-host-compatibility.mjs
- name: Inspect package contents
if: matrix.pack_check
run: npm run pack:check
gate:
name: Gate
if: always()
needs:
- release-metadata
- validate
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Require all validation jobs
env:
RELEASE_METADATA_RESULT: ${{ needs.release-metadata.result }}
VALIDATE_RESULT: ${{ needs.validate.result }}
run: |
if [[ "$RELEASE_METADATA_RESULT" != "success" || "$VALIDATE_RESULT" != "success" ]]; then
echo "::error::Required CI jobs did not succeed (release-metadata=$RELEASE_METADATA_RESULT, validate=$VALIDATE_RESULT)."
exit 1
fi
tag-release:
name: Reconcile release tag
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs:
- release-metadata
- gate
runs-on: ubuntu-latest
timeout-minutes: 30
concurrency:
group: release-reconcile-${{ needs.release-metadata.outputs.release_tag }}
cancel-in-progress: false
permissions:
actions: write
contents: write
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24.15.0"
registry-url: https://registry.npmjs.org
- name: Reconcile release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_COMMIT: ${{ needs.release-metadata.outputs.release_commit }}
RELEASE_TAG: ${{ needs.release-metadata.outputs.release_tag }}
RELEASE_VERSION: ${{ needs.release-metadata.outputs.release_version }}
run: |
set -euo pipefail
tag_commit="$(git rev-list -n 1 "refs/tags/${RELEASE_TAG}" 2>/dev/null || true)"
if [[ -n "$tag_commit" ]]; then
if [[ "$tag_commit" != "$RELEASE_COMMIT" ]]; then
echo "::error::${RELEASE_TAG} points to ${tag_commit}, not release commit ${RELEASE_COMMIT}."
exit 1
fi
tag_version="$(
git show "${RELEASE_TAG}:package.json" |
node -p "JSON.parse(require('fs').readFileSync(0, 'utf8')).version"
)"
if [[ "$tag_version" != "$RELEASE_VERSION" ]]; then
echo "::error::${RELEASE_TAG} contains package version ${tag_version}, not ${RELEASE_VERSION}."
exit 1
fi
echo "${RELEASE_TAG} already points to release commit ${tag_commit}."
elif [[ "$RELEASE_COMMIT" != "$GITHUB_SHA" ]]; then
echo "::error::Missing ${RELEASE_TAG} can only be created by CI for release commit ${RELEASE_COMMIT}."
echo "::error::Rerun that commit's main workflow; do not tag a later same-version commit."
exit 1
fi
registry_error="$(mktemp)"
trap 'rm -f "$registry_error"' EXIT
if published_version="$(
npm view "openclaw-weixin@${RELEASE_VERSION}" version \
--registry=https://registry.npmjs.org 2>"$registry_error"
)"; then
if [[ "$published_version" != "$RELEASE_VERSION" ]]; then
echo "::error::npm returned unexpected version ${published_version} for ${RELEASE_VERSION}."
exit 1
fi
if [[ -z "$tag_commit" ]]; then
echo "::error::openclaw-weixin@${RELEASE_VERSION} is published, but ${RELEASE_TAG} is missing."
exit 1
fi
echo "openclaw-weixin@${RELEASE_VERSION} is already published."
exit 0
fi
if ! grep -Eq 'E404|404 Not Found' "$registry_error"; then
cat "$registry_error" >&2
echo "::error::Could not determine whether openclaw-weixin@${RELEASE_VERSION} is published."
exit 1
fi
repository_visibility="$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.visibility')"
if [[ "$repository_visibility" != "public" ]]; then
echo "::error::Repository must be public before creating ${RELEASE_TAG} for npm provenance."
exit 1
fi
: > "$registry_error"
if ! latest_version="$(
npm view "openclaw-weixin@latest" version \
--registry=https://registry.npmjs.org 2>"$registry_error"
)"; then
cat "$registry_error" >&2
echo "::error::Could not read the npm latest version."
exit 1
fi
RELEASE_PREVIOUS_VERSION="$latest_version" npm run check:versions
if [[ -z "$tag_commit" ]]; then
gh api --method POST "repos/${GITHUB_REPOSITORY}/git/refs" \
-f ref="refs/tags/${RELEASE_TAG}" \
-f sha="$RELEASE_COMMIT"
tag_commit="$RELEASE_COMMIT"
fi
active_runs="$(
gh run list --repo "$GITHUB_REPOSITORY" --workflow release.yml --commit "$tag_commit" \
--limit 20 --json status --jq '[.[] | select(.status != "completed")] | length'
)"
if [[ "$active_runs" != "0" ]]; then
echo "A release workflow is already queued or running for ${RELEASE_TAG}."
exit 0
fi
successful_runs="$(
gh run list --repo "$GITHUB_REPOSITORY" --workflow release.yml --commit "$tag_commit" \
--limit 20 --json conclusion,status \
--jq '[.[] | select(.status == "completed" and .conclusion == "success")] | length'
)"
if [[ "$successful_runs" != "0" ]]; then
echo "::error::A successful release run exists, but npm does not contain openclaw-weixin@${RELEASE_VERSION}."
exit 1
fi
# GITHUB_TOKEN-created tags do not recursively trigger push workflows.
gh workflow run release.yml --repo "$GITHUB_REPOSITORY" --ref "$RELEASE_TAG"