Repository navigation
docs: unify installation prompts across registries #404
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" |