mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:50:43 +00:00
706 lines
37 KiB
Markdown
706 lines
37 KiB
Markdown
---
|
|
summary: "Release lanes, operator checklist, validation boxes, version naming, and cadence"
|
|
title: "Release policy"
|
|
read_when:
|
|
- Looking for public release channel definitions
|
|
- Running release validation or package acceptance
|
|
- Looking for version naming and cadence
|
|
---
|
|
|
|
OpenClaw has three public release lanes:
|
|
|
|
- stable: tagged releases that publish to npm `beta` by default, or to npm `latest` when explicitly requested
|
|
- beta: prerelease tags that publish to npm `beta`
|
|
- dev: the moving head of `main`
|
|
|
|
## Version naming
|
|
|
|
- Stable release version: `YYYY.M.D`
|
|
- Git tag: `vYYYY.M.D`
|
|
- Stable correction release version: `YYYY.M.D-N`
|
|
- Git tag: `vYYYY.M.D-N`
|
|
- Beta prerelease version: `YYYY.M.D-beta.N`
|
|
- Git tag: `vYYYY.M.D-beta.N`
|
|
- Do not zero-pad month or day
|
|
- `latest` means the current promoted stable npm release
|
|
- `beta` means the current beta install target
|
|
- Stable and stable correction releases publish to npm `beta` by default; release operators can target `latest` explicitly, or promote a vetted beta build later
|
|
- Every stable OpenClaw release ships the npm package and macOS app together;
|
|
beta releases normally validate and publish the npm/package path first, with
|
|
mac app build/sign/notarize reserved for stable unless explicitly requested
|
|
|
|
## Release cadence
|
|
|
|
- Releases move beta-first
|
|
- Stable follows only after the latest beta is validated
|
|
- Maintainers normally cut releases from a `release/YYYY.M.D` branch created
|
|
from current `main`, so release validation and fixes do not block new
|
|
development on `main`
|
|
- If a beta tag has been pushed or published and needs a fix, maintainers cut
|
|
the next `-beta.N` tag instead of deleting or recreating the old beta tag
|
|
- Detailed release procedure, approvals, credentials, and recovery notes are
|
|
maintainer-only
|
|
|
|
## Release operator checklist
|
|
|
|
This checklist is the public shape of the release flow. Private credentials,
|
|
signing, notarization, dist-tag recovery, and emergency rollback details stay in
|
|
the maintainer-only release runbook.
|
|
|
|
1. Start from current `main`: pull latest, confirm the target commit is pushed,
|
|
and confirm current `main` CI is green enough to branch from it.
|
|
2. Rewrite the top `CHANGELOG.md` section from real commit history with
|
|
`/changelog`, keep entries user-facing, commit it, push it, and rebase/pull
|
|
once more before branching.
|
|
3. Review release compatibility records in
|
|
`src/plugins/compat/registry.ts` and
|
|
`src/commands/doctor/shared/deprecation-compat.ts`. Remove expired
|
|
compatibility only when the upgrade path stays covered, or record why it is
|
|
intentionally carried.
|
|
4. Create `release/YYYY.M.D` from current `main`; do not do normal release work
|
|
directly on `main`.
|
|
5. Bump every required version location for the intended tag, run
|
|
`pnpm plugins:sync` so publishable plugin packages share the release
|
|
version and compatibility metadata, then run the local deterministic preflight:
|
|
`pnpm check:test-types`, `pnpm check:architecture`,
|
|
`pnpm build && pnpm ui:build`, `pnpm plugins:sync:check`, and
|
|
`pnpm release:check`.
|
|
6. Run `OpenClaw NPM Release` with `preflight_only=true`. Before a tag exists,
|
|
a full 40-character release-branch SHA is allowed for validation-only
|
|
preflight. Save the successful `preflight_run_id`.
|
|
7. Kick off all pre-release tests with `Full Release Validation` for the
|
|
release branch, tag, or full commit SHA. This is the one manual entrypoint
|
|
for the four big release test boxes: Vitest, Docker, QA Lab, and Package.
|
|
8. If validation fails, fix on the release branch and rerun the smallest failed
|
|
file, lane, workflow job, package profile, provider, or model allowlist that
|
|
proves the fix. Rerun the full umbrella only when the changed surface makes
|
|
prior evidence stale.
|
|
9. For beta, tag `vYYYY.M.D-beta.N`, then run `OpenClaw Release Publish` from
|
|
the matching `release/YYYY.M.D` branch. It verifies `pnpm plugins:sync:check`,
|
|
publishes all publishable plugin packages to npm first, publishes the same
|
|
set to ClawHub second as ClawPack npm-pack tarballs, and then promotes the
|
|
prepared OpenClaw npm preflight artifact with the matching dist-tag. After
|
|
publish, run post-publish package
|
|
acceptance against the published `openclaw@YYYY.M.D-beta.N` or
|
|
`openclaw@beta` package. If a pushed or published prerelease needs a fix,
|
|
cut the next matching prerelease number; do not delete or rewrite the old
|
|
prerelease.
|
|
10. For stable, continue only after the vetted beta or release candidate has the
|
|
required validation evidence. Stable npm publish also goes through
|
|
`OpenClaw Release Publish`, reusing the successful preflight artifact via
|
|
`preflight_run_id`; stable macOS release readiness also requires the
|
|
packaged `.zip`, `.dmg`, `.dSYM.zip`, and updated `appcast.xml` on `main`.
|
|
11. After publish, run the npm post-publish verifier, optional standalone
|
|
published-npm Telegram E2E when you need post-publish channel proof,
|
|
dist-tag promotion when needed, GitHub release/prerelease notes from the
|
|
complete matching `CHANGELOG.md` section, and the release announcement
|
|
steps.
|
|
|
|
## Release preflight
|
|
|
|
- Run `pnpm check:test-types` before release preflight so test TypeScript stays
|
|
covered outside the faster local `pnpm check` gate
|
|
- Run `pnpm check:architecture` before release preflight so the broader import
|
|
cycle and architecture boundary checks are green outside the faster local gate
|
|
- Run `pnpm build && pnpm ui:build` before `pnpm release:check` so the expected
|
|
`dist/*` release artifacts and Control UI bundle exist for the pack
|
|
validation step
|
|
- Run `pnpm plugins:sync` after the root version bump and before tagging. It
|
|
updates publishable plugin package versions, OpenClaw peer/API compatibility
|
|
metadata, build metadata, and plugin changelog stubs to match the core
|
|
release version. `pnpm plugins:sync:check` is the non-mutating release guard;
|
|
the publish workflow fails before any registry mutation if this step was
|
|
forgotten.
|
|
- Run the manual `Full Release Validation` workflow before release approval to
|
|
kick off all pre-release test boxes from one entrypoint. It accepts a branch,
|
|
tag, or full commit SHA, dispatches manual `CI`, and dispatches
|
|
`OpenClaw Release Checks` for install smoke, package acceptance, cross-OS
|
|
package checks, QA Lab parity, Matrix, and Telegram lanes. Stable/default runs
|
|
keep exhaustive live/E2E and Docker release-path soak behind
|
|
`run_release_soak=true`; `release_profile=full` forces soak on. With
|
|
`release_profile=full` and `rerun_group=all`, it also runs package Telegram
|
|
E2E against the `release-package-under-test` artifact from release checks.
|
|
Provide `npm_telegram_package_spec` after publishing when the same
|
|
Telegram E2E should prove the published npm package too. Provide
|
|
`package_acceptance_package_spec` after publishing when Package Acceptance
|
|
should run its package/update matrix against the shipped npm package instead
|
|
of the SHA-built artifact. Provide
|
|
`evidence_package_spec` when the private evidence report should prove that the
|
|
validation matches a published npm package without forcing Telegram E2E.
|
|
Example:
|
|
`gh workflow run full-release-validation.yml --ref main -f ref=release/YYYY.M.D`
|
|
- Run the manual `Package Acceptance` workflow when you want side-channel proof
|
|
for a package candidate while release work continues. Use `source=npm` for
|
|
`openclaw@beta`, `openclaw@latest`, or an exact release version; `source=ref`
|
|
to pack a trusted `package_ref` branch/tag/SHA with the current
|
|
`workflow_ref` harness; `source=url` for an HTTPS tarball with a required
|
|
SHA-256; or `source=artifact` for a tarball uploaded by another GitHub
|
|
Actions run. The workflow resolves the candidate to
|
|
`package-under-test`, reuses the Docker E2E release scheduler against that
|
|
tarball, and can run Telegram QA against the same tarball with
|
|
`telegram_mode=mock-openai` or `telegram_mode=live-frontier`. When the
|
|
selected Docker lanes include `published-upgrade-survivor`, the package
|
|
artifact is the candidate and `published_upgrade_survivor_baseline` selects
|
|
the published baseline. `update-restart-auth` uses the candidate package as
|
|
both the installed CLI and the package-under-test so it exercises the
|
|
candidate update command's managed restart path.
|
|
Example: `gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f published_upgrade_survivor_baseline=openclaw@2026.4.26 -f telegram_mode=mock-openai`
|
|
Common profiles:
|
|
- `smoke`: install/channel/agent, gateway network, and config reload lanes
|
|
- `package`: artifact-native package/update/restart/plugin lanes without OpenWebUI or live ClawHub
|
|
- `product`: package profile plus MCP channels, cron/subagent cleanup,
|
|
OpenAI web search, and OpenWebUI
|
|
- `full`: Docker release-path chunks with OpenWebUI
|
|
- `custom`: exact `docker_lanes` selection for a focused rerun
|
|
- Run the manual `CI` workflow directly when you only need full normal CI
|
|
coverage for the release candidate. Manual CI dispatches bypass changed
|
|
scoping and force the Linux Node shards, bundled-plugin shards, channel
|
|
contracts, Node 22 compatibility, `check`, `check-additional`, build smoke,
|
|
docs checks, Python skills, Windows, macOS, Android, and Control UI i18n
|
|
lanes.
|
|
Example: `gh workflow run ci.yml --ref release/YYYY.M.D`
|
|
- Run `pnpm qa:otel:smoke` when validating release telemetry. It exercises
|
|
QA-lab through a local OTLP/HTTP receiver and verifies the exported trace
|
|
span names, bounded attributes, and content/identifier redaction without
|
|
requiring Opik, Langfuse, or another external collector.
|
|
- Run `pnpm release:check` before every tagged release
|
|
- Run `OpenClaw Release Publish` for the mutating publish sequence after the
|
|
tag exists. Dispatch it from `release/YYYY.M.D` (or `main` when publishing a
|
|
main-reachable tag), pass the release tag and successful OpenClaw npm
|
|
`preflight_run_id`, and keep the default plugin publish scope
|
|
`all-publishable` unless you are deliberately running a focused repair. The
|
|
workflow serializes plugin npm publish, plugin ClawHub publish, and OpenClaw
|
|
npm publish so the core package is not published before its externalized
|
|
plugins.
|
|
- Release checks now run in a separate manual workflow:
|
|
`OpenClaw Release Checks`
|
|
- `OpenClaw Release Checks` also runs the QA Lab mock parity lane plus the fast
|
|
live Matrix profile and Telegram QA lane before release approval. The live
|
|
lanes use the `qa-live-shared` environment; Telegram also uses Convex CI
|
|
credential leases. Run the manual `QA-Lab - All Lanes` workflow with
|
|
`matrix_profile=all` and `matrix_shards=true` when you want full Matrix
|
|
transport, media, and E2EE inventory in parallel.
|
|
- Cross-OS install and upgrade runtime validation is part of public
|
|
`OpenClaw Release Checks` and `Full Release Validation`, which call the
|
|
reusable workflow
|
|
`.github/workflows/openclaw-cross-os-release-checks-reusable.yml` directly
|
|
- This split is intentional: keep the real npm release path short,
|
|
deterministic, and artifact-focused, while slower live checks stay in their
|
|
own lane so they do not stall or block publish
|
|
- Secret-bearing release checks should be dispatched through `Full Release
|
|
Validation` or from the `main`/release workflow ref so workflow logic and
|
|
secrets stay controlled
|
|
- `OpenClaw Release Checks` accepts a branch, tag, or full commit SHA as long
|
|
as the resolved commit is reachable from an OpenClaw branch or release tag
|
|
- `OpenClaw NPM Release` validation-only preflight also accepts the current
|
|
full 40-character workflow-branch commit SHA without requiring a pushed tag
|
|
- That SHA path is validation-only and cannot be promoted into a real publish
|
|
- In SHA mode the workflow synthesizes `v<package.json version>` only for the
|
|
package metadata check; real publish still requires a real release tag
|
|
- Both workflows keep the real publish and promotion path on GitHub-hosted
|
|
runners, while the non-mutating validation path can use the larger
|
|
Blacksmith Linux runners
|
|
- That workflow runs
|
|
`OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`
|
|
using both `OPENAI_API_KEY` and `ANTHROPIC_API_KEY` workflow secrets
|
|
- npm release preflight no longer waits on the separate release checks lane
|
|
- Run `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`
|
|
(or the matching beta/correction tag) before approval
|
|
- After npm publish, run
|
|
`node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`
|
|
(or the matching beta/correction version) to verify the published registry
|
|
install path in a fresh temp prefix
|
|
- After a beta publish, run `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live`
|
|
to verify installed-package onboarding, Telegram setup, and real Telegram E2E
|
|
against the published npm package using the shared leased Telegram credential
|
|
pool. Local maintainer one-offs may omit the Convex vars and pass the three
|
|
`OPENCLAW_QA_TELEGRAM_*` env credentials directly.
|
|
- To run the full post-publish beta smoke from a maintainer machine, use `pnpm release:beta-smoke -- --beta betaN`. The helper runs Parallels npm update/fresh-target validation, dispatches `NPM Telegram Beta E2E`, polls the exact workflow run, downloads the artifact, and prints the Telegram report.
|
|
- Maintainers can run the same post-publish check from GitHub Actions via the
|
|
manual `NPM Telegram Beta E2E` workflow. It is intentionally manual-only and
|
|
does not run on every merge.
|
|
- Maintainer release automation now uses preflight-then-promote:
|
|
- real npm publish must pass a successful npm `preflight_run_id`
|
|
- the real npm publish must be dispatched from the same `main` or
|
|
`release/YYYY.M.D` branch as the successful preflight run
|
|
- stable npm releases default to `beta`
|
|
- stable npm publish can target `latest` explicitly via workflow input
|
|
- token-based npm dist-tag mutation now lives in
|
|
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
|
for security, because `npm dist-tag add` still needs `NPM_TOKEN` while the
|
|
public repo keeps OIDC-only publish
|
|
- public `macOS Release` is validation-only; when a tag lives only on a
|
|
release branch but the workflow is dispatched from `main`, set
|
|
`public_release_branch=release/YYYY.M.D`
|
|
- real private mac publish must pass successful private mac
|
|
`preflight_run_id` and `validate_run_id`
|
|
- the real publish paths promote prepared artifacts instead of rebuilding
|
|
them again
|
|
- For stable correction releases like `YYYY.M.D-N`, the post-publish verifier
|
|
also checks the same temp-prefix upgrade path from `YYYY.M.D` to `YYYY.M.D-N`
|
|
so release corrections cannot silently leave older global installs on the
|
|
base stable payload
|
|
- npm release preflight fails closed unless the tarball includes both
|
|
`dist/control-ui/index.html` and a non-empty `dist/control-ui/assets/` payload
|
|
so we do not ship an empty browser dashboard again
|
|
- Post-publish verification also checks that published plugin entrypoints and
|
|
package metadata are present in the installed registry layout. A release that
|
|
ships missing plugin runtime payloads fails the postpublish verifier and
|
|
cannot be promoted to `latest`.
|
|
- `pnpm test:install:smoke` also enforces the npm pack `unpackedSize` budget on
|
|
the candidate update tarball, so installer e2e catches accidental pack bloat
|
|
before the release publish path
|
|
- If the release work touched CI planning, extension timing manifests, or
|
|
extension test matrices, regenerate and review the planner-owned
|
|
`plugin-prerelease-extension-shard` matrix outputs from
|
|
`.github/workflows/plugin-prerelease.yml` before approval so release notes do
|
|
not describe a stale CI layout
|
|
- Stable macOS release readiness also includes the updater surfaces:
|
|
- the GitHub release must end up with the packaged `.zip`, `.dmg`, and `.dSYM.zip`
|
|
- `appcast.xml` on `main` must point at the new stable zip after publish
|
|
- the packaged app must keep a non-debug bundle id, a non-empty Sparkle feed
|
|
URL, and a `CFBundleVersion` at or above the canonical Sparkle build floor
|
|
for that release version
|
|
|
|
## Release test boxes
|
|
|
|
`Full Release Validation` is how operators kick off all pre-release tests from
|
|
one entrypoint. For a pinned commit proof on a fast-moving branch, use the
|
|
helper so every child workflow runs from a temporary branch fixed at the target
|
|
SHA:
|
|
|
|
```bash
|
|
pnpm ci:full-release --sha <full-sha>
|
|
```
|
|
|
|
The helper pushes `release-ci/<sha>-...`, dispatches `Full Release Validation`
|
|
from that branch with `ref=<sha>`, verifies every child workflow `headSha`
|
|
matches the target, then deletes the temporary branch. This avoids proving a
|
|
newer `main` child run by accident.
|
|
|
|
For release branch or tag validation, run it from the trusted `main` workflow
|
|
ref and pass the release branch or tag as `ref`:
|
|
|
|
```bash
|
|
gh workflow run full-release-validation.yml \
|
|
--ref main \
|
|
-f ref=release/YYYY.M.D \
|
|
-f provider=openai \
|
|
-f mode=both \
|
|
-f release_profile=stable \
|
|
-f evidence_package_spec=openclaw@YYYY.M.D-beta.N
|
|
```
|
|
|
|
The workflow resolves the target ref, dispatches manual `CI` with
|
|
`target_ref=<release-ref>`, dispatches `OpenClaw Release Checks`, prepares a
|
|
parent `release-package-under-test` artifact for package-facing checks, and
|
|
dispatches standalone package Telegram E2E when `release_profile=full` with
|
|
`rerun_group=all` or when `npm_telegram_package_spec` is set. `OpenClaw Release
|
|
Checks` then fans out install smoke, cross-OS release checks, live/E2E Docker
|
|
release-path coverage when soak is enabled, Package Acceptance with Telegram
|
|
package QA, QA Lab parity, live Matrix, and live Telegram. A full run is only acceptable when the
|
|
`Full Release Validation`
|
|
summary shows `normal_ci` and `release_checks` as successful. In full/all mode,
|
|
the `npm_telegram` child must also be successful; outside full/all it is skipped
|
|
unless a published `npm_telegram_package_spec` was provided. The final
|
|
verifier summary includes slowest-job tables for each child run, so the release
|
|
manager can see the current critical path without downloading logs.
|
|
See [Full release validation](/reference/full-release-validation) for the
|
|
complete stage matrix, exact workflow job names, stable versus full profile
|
|
differences, artifacts, and focused rerun handles.
|
|
Child workflows are dispatched from the trusted ref that runs `Full Release
|
|
Validation`, normally `--ref main`, even when the target `ref` points at an
|
|
older release branch or tag. There is no separate Full Release Validation
|
|
workflow-ref input; choose the trusted harness by choosing the workflow run ref.
|
|
Do not use `--ref main -f ref=<sha>` for exact commit proof on moving `main`;
|
|
raw commit SHAs cannot be workflow dispatch refs, so use
|
|
`pnpm ci:full-release --sha <sha>` to create the pinned temporary branch.
|
|
|
|
Use `release_profile` to select live/provider breadth:
|
|
|
|
- `minimum`: fastest release-critical OpenAI/core live and Docker path
|
|
- `stable`: minimum plus stable provider/backend coverage for release approval
|
|
- `full`: stable plus broad advisory provider/media coverage
|
|
|
|
Use `run_release_soak=true` with `stable` when the release-blocking lanes are
|
|
green and you want the exhaustive live/E2E, Docker release-path, and
|
|
bounded published upgrade-survivor sweep before promotion. That sweep covers
|
|
the latest four stable packages plus pinned `2026.4.23` and `2026.5.2`
|
|
baselines plus older `2026.4.15` coverage, with duplicate baselines removed and
|
|
each baseline sharded into its own Docker runner job. `full` implies
|
|
`run_release_soak=true`.
|
|
|
|
`OpenClaw Release Checks` uses the trusted workflow ref to resolve the target
|
|
ref once as `release-package-under-test` and reuses that artifact in cross-OS,
|
|
Package Acceptance, and release-path Docker checks when soak runs. This keeps
|
|
all package-facing boxes on the same bytes and avoids repeated package builds.
|
|
The cross-OS OpenAI install smoke uses `OPENCLAW_CROSS_OS_OPENAI_MODEL` when the
|
|
repo/org variable is set, otherwise `openai/gpt-5.4`, because this lane is
|
|
proving package install, onboarding, gateway startup, and one live agent turn
|
|
rather than benchmarking the slowest default model. The broader live provider
|
|
matrix remains the place for model-specific coverage.
|
|
|
|
Use these variants depending on release stage:
|
|
|
|
```bash
|
|
# Validate an unpublished release candidate branch.
|
|
gh workflow run full-release-validation.yml \
|
|
--ref main \
|
|
-f ref=release/YYYY.M.D \
|
|
-f provider=openai \
|
|
-f mode=both \
|
|
-f release_profile=stable
|
|
|
|
# Validate an exact pushed commit.
|
|
gh workflow run full-release-validation.yml \
|
|
--ref main \
|
|
-f ref=<40-char-sha> \
|
|
-f provider=openai \
|
|
-f mode=both
|
|
|
|
# After publishing a beta, add published-package Telegram E2E.
|
|
gh workflow run full-release-validation.yml \
|
|
--ref main \
|
|
-f ref=release/YYYY.M.D \
|
|
-f provider=openai \
|
|
-f mode=both \
|
|
-f release_profile=full \
|
|
-f evidence_package_spec=openclaw@YYYY.M.D-beta.N \
|
|
-f npm_telegram_package_spec=openclaw@YYYY.M.D-beta.N \
|
|
-f npm_telegram_provider_mode=mock-openai
|
|
```
|
|
|
|
Do not use the full umbrella as the first rerun after a focused fix. If one box
|
|
fails, use the failed child workflow, job, Docker lane, package profile, model
|
|
provider, or QA lane for the next proof. Run the full umbrella again only when
|
|
the fix changed shared release orchestration or made earlier all-box evidence
|
|
stale. The umbrella's final verifier re-checks the recorded child workflow run
|
|
ids, so after a child workflow is rerun successfully, rerun only the failed
|
|
`Verify full validation` parent job.
|
|
|
|
For bounded recovery, pass `rerun_group` to the umbrella. `all` is the real
|
|
release-candidate run, `ci` runs only the normal CI child, `plugin-prerelease`
|
|
runs only the release-only plugin child, `release-checks` runs every release
|
|
box, and the narrower release groups are `install-smoke`, `cross-os`,
|
|
`live-e2e`, `package`, `qa`, `qa-parity`, `qa-live`, and `npm-telegram`.
|
|
Focused `npm-telegram` reruns require `npm_telegram_package_spec`; full/all runs
|
|
with `release_profile=full` use the release-checks package artifact. Focused
|
|
cross-OS reruns can add `cross_os_suite_filter=windows/packaged-upgrade` or
|
|
another OS/suite filter. QA release-check failures are advisory; a QA-only
|
|
failure does not block release validation.
|
|
|
|
### Vitest
|
|
|
|
The Vitest box is the manual `CI` child workflow. Manual CI intentionally
|
|
bypasses changed scoping and forces the normal test graph for the release
|
|
candidate: Linux Node shards, bundled-plugin shards, channel contracts, Node 22
|
|
compatibility, `check`, `check-additional`, build smoke, docs checks, Python
|
|
skills, Windows, macOS, Android, and Control UI i18n.
|
|
|
|
Use this box to answer "did the source tree pass the full normal test suite?"
|
|
It is not the same as release-path product validation. Evidence to keep:
|
|
|
|
- `Full Release Validation` summary showing the dispatched `CI` run URL
|
|
- `CI` run green on the exact target SHA
|
|
- failed or slow shard names from the CI jobs when investigating regressions
|
|
- Vitest timing artifacts such as `.artifacts/vitest-shard-timings.json` when
|
|
a run needs performance analysis
|
|
|
|
Run manual CI directly only when the release needs deterministic normal CI but
|
|
not the Docker, QA Lab, live, cross-OS, or package boxes:
|
|
|
|
```bash
|
|
gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D
|
|
```
|
|
|
|
### Docker
|
|
|
|
The Docker box lives in `OpenClaw Release Checks` through
|
|
`openclaw-live-and-e2e-checks-reusable.yml`, plus the release-mode
|
|
`install-smoke` workflow. It validates the release candidate through packaged
|
|
Docker environments instead of only source-level tests.
|
|
|
|
Release Docker coverage includes:
|
|
|
|
- full install smoke with the slow Bun global install smoke enabled
|
|
- root Dockerfile smoke image preparation/reuse by target SHA, with QR,
|
|
root/gateway, and installer/Bun smoke jobs running as separate install-smoke
|
|
shards
|
|
- repository E2E lanes
|
|
- release-path Docker chunks: `core`, `package-update-openai`,
|
|
`package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`,
|
|
`plugins-runtime-services`,
|
|
`plugins-runtime-install-a`, `plugins-runtime-install-b`,
|
|
`plugins-runtime-install-c`, `plugins-runtime-install-d`,
|
|
`plugins-runtime-install-e`, `plugins-runtime-install-f`,
|
|
`plugins-runtime-install-g`, and `plugins-runtime-install-h`
|
|
- OpenWebUI coverage inside the `plugins-runtime-services` chunk when requested
|
|
- split bundled plugin install/uninstall lanes
|
|
`bundled-plugin-install-uninstall-0` through
|
|
`bundled-plugin-install-uninstall-23`
|
|
- live/E2E provider suites and Docker live model coverage when release checks
|
|
include live suites
|
|
|
|
Use Docker artifacts before rerunning. The release-path scheduler uploads
|
|
`.artifacts/docker-tests/` with lane logs, `summary.json`, `failures.json`,
|
|
phase timings, scheduler plan JSON, and rerun commands. For focused recovery,
|
|
use `docker_lanes=<lane[,lane]>` on the reusable live/E2E workflow instead of
|
|
rerunning all release chunks. Generated rerun commands include prior
|
|
`package_artifact_run_id` and prepared Docker image inputs when available, so a
|
|
failed lane can reuse the same tarball and GHCR images.
|
|
|
|
### QA Lab
|
|
|
|
The QA Lab box is also part of `OpenClaw Release Checks`. It is the agentic
|
|
behavior and channel-level release gate, separate from Vitest and Docker
|
|
package mechanics.
|
|
|
|
Release QA Lab coverage includes:
|
|
|
|
- mock parity lane comparing the OpenAI candidate lane against the Opus 4.6
|
|
baseline using the agentic parity pack
|
|
- fast live Matrix QA profile using the `qa-live-shared` environment
|
|
- live Telegram QA lane using Convex CI credential leases
|
|
- `pnpm qa:otel:smoke` when release telemetry needs explicit local proof
|
|
|
|
Use this box to answer "does the release behave correctly in QA scenarios and
|
|
live channel flows?" Keep the artifact URLs for parity, Matrix, and Telegram
|
|
lanes when approving the release. Full Matrix coverage remains available as a
|
|
manual sharded QA-Lab run rather than the default release-critical lane.
|
|
|
|
### Package
|
|
|
|
The Package box is the installable-product gate. It is backed by
|
|
`Package Acceptance` and the resolver
|
|
`scripts/resolve-openclaw-package-candidate.mjs`. The resolver normalizes a
|
|
candidate into the `package-under-test` tarball consumed by Docker E2E, validates
|
|
the package inventory, records the package version and SHA-256, and keeps the
|
|
workflow harness ref separate from the package source ref.
|
|
|
|
Supported candidate sources:
|
|
|
|
- `source=npm`: `openclaw@beta`, `openclaw@latest`, or an exact OpenClaw release
|
|
version
|
|
- `source=ref`: pack a trusted `package_ref` branch, tag, or full commit SHA
|
|
with the selected `workflow_ref` harness
|
|
- `source=url`: download an HTTPS `.tgz` with required `package_sha256`
|
|
- `source=artifact`: reuse a `.tgz` uploaded by another GitHub Actions run
|
|
|
|
`OpenClaw Release Checks` runs Package Acceptance with `source=artifact`, the
|
|
prepared release package artifact, `suite_profile=custom`,
|
|
`docker_lanes=doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor update-restart-auth plugins-offline plugin-update`,
|
|
`telegram_mode=mock-openai`. Package Acceptance keeps migration, update,
|
|
configured-auth update restart, stale plugin dependency cleanup, offline plugin
|
|
fixtures, plugin update, and Telegram package QA against the same resolved
|
|
tarball. Blocking release checks use the default latest published package
|
|
baseline; `run_release_soak=true` or
|
|
`release_profile=full` expands to every stable npm-published baseline from
|
|
`2026.4.23` through `latest` plus reported-issue fixtures. Use
|
|
Package Acceptance with `source=npm` for an already shipped candidate, or
|
|
`source=ref`/`source=artifact` for a SHA-backed local npm tarball before
|
|
publish. It is the GitHub-native
|
|
replacement for most of the package/update coverage that previously required
|
|
Parallels. Cross-OS release checks still matter for OS-specific onboarding,
|
|
installer, and platform behavior, but package/update product validation should
|
|
prefer Package Acceptance.
|
|
|
|
The canonical checklist for update and plugin validation is
|
|
[Testing updates and plugins](/help/testing-updates-plugins). Use it when
|
|
deciding which local, Docker, Package Acceptance, or release-check lane proves a
|
|
plugin install/update, doctor cleanup, or published-package migration change.
|
|
Exhaustive published update migration from every stable `2026.4.23+` package is
|
|
a separate manual `Update Migration` workflow, not part of Full Release CI.
|
|
|
|
Legacy package-acceptance leniency is intentionally time boxed. Packages through
|
|
`2026.4.25` may use the compatibility path for metadata gaps already published
|
|
to npm: private QA inventory entries missing from the tarball, missing
|
|
`gateway install --wrapper`, missing patch files in the tarball-derived git
|
|
fixture, missing persisted `update.channel`, legacy plugin install-record
|
|
locations, missing marketplace install-record persistence, and config metadata
|
|
migration during `plugins update`. The published `2026.4.26` package may warn
|
|
for local build metadata stamp files that were already shipped. Later packages
|
|
must satisfy the modern package contracts; those same gaps fail release
|
|
validation.
|
|
|
|
Use broader Package Acceptance profiles when the release question is about an
|
|
actual installable package:
|
|
|
|
```bash
|
|
gh workflow run package-acceptance.yml \
|
|
--ref main \
|
|
-f workflow_ref=main \
|
|
-f source=npm \
|
|
-f package_spec=openclaw@beta \
|
|
-f suite_profile=product \
|
|
-f published_upgrade_survivor_baseline=openclaw@2026.4.26
|
|
```
|
|
|
|
Common package profiles:
|
|
|
|
- `smoke`: quick package install/channel/agent, gateway network, and config
|
|
reload lanes
|
|
- `package`: install/update/restart/plugin package contracts without live
|
|
ClawHub; this is the release-check default
|
|
- `product`: `package` plus MCP channels, cron/subagent cleanup, OpenAI web
|
|
search, and OpenWebUI
|
|
- `full`: Docker release-path chunks with OpenWebUI
|
|
- `custom`: exact `docker_lanes` list for focused reruns
|
|
|
|
For package-candidate Telegram proof, enable `telegram_mode=mock-openai` or
|
|
`telegram_mode=live-frontier` on Package Acceptance. The workflow passes the
|
|
resolved `package-under-test` tarball into the Telegram lane; the standalone
|
|
Telegram workflow still accepts a published npm spec for post-publish checks.
|
|
|
|
## Release publish automation
|
|
|
|
`OpenClaw Release Publish` is the normal mutating publish entrypoint. It
|
|
orchestrates the trusted-publisher workflows in the order the release needs:
|
|
|
|
1. Check out the release tag and resolve its commit SHA.
|
|
2. Verify the tag is reachable from `main` or `release/*`.
|
|
3. Run `pnpm plugins:sync:check`.
|
|
4. Dispatch `Plugin NPM Release` with `publish_scope=all-publishable` and
|
|
`ref=<release-sha>`.
|
|
5. Dispatch `Plugin ClawHub Release` with the same scope and SHA.
|
|
6. Dispatch `OpenClaw NPM Release` with the release tag, npm dist-tag, and
|
|
saved `preflight_run_id`.
|
|
|
|
Beta publish example:
|
|
|
|
```bash
|
|
gh workflow run openclaw-release-publish.yml \
|
|
--ref release/YYYY.M.D \
|
|
-f tag=vYYYY.M.D-beta.N \
|
|
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
|
|
-f npm_dist_tag=beta
|
|
```
|
|
|
|
Stable publish to the default beta dist-tag:
|
|
|
|
```bash
|
|
gh workflow run openclaw-release-publish.yml \
|
|
--ref release/YYYY.M.D \
|
|
-f tag=vYYYY.M.D \
|
|
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
|
|
-f npm_dist_tag=beta
|
|
```
|
|
|
|
Stable promotion directly to `latest` is explicit:
|
|
|
|
```bash
|
|
gh workflow run openclaw-release-publish.yml \
|
|
--ref release/YYYY.M.D \
|
|
-f tag=vYYYY.M.D \
|
|
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
|
|
-f npm_dist_tag=latest
|
|
```
|
|
|
|
Use the lower-level `Plugin NPM Release` and `Plugin ClawHub Release` workflows
|
|
only for focused repair or republish work. For a selected plugin repair, pass
|
|
`plugin_publish_scope=selected` and `plugins=@openclaw/name` to
|
|
`OpenClaw Release Publish`, or dispatch the child workflow directly when the
|
|
OpenClaw package must not be published.
|
|
|
|
## NPM workflow inputs
|
|
|
|
`OpenClaw NPM Release` accepts these operator-controlled inputs:
|
|
|
|
- `tag`: required release tag such as `v2026.4.2`, `v2026.4.2-1`, or
|
|
`v2026.4.2-beta.1`; when `preflight_only=true`, it may also be the current
|
|
full 40-character workflow-branch commit SHA for validation-only preflight
|
|
- `preflight_only`: `true` for validation/build/package only, `false` for the
|
|
real publish path
|
|
- `preflight_run_id`: required on the real publish path so the workflow reuses
|
|
the prepared tarball from the successful preflight run
|
|
- `npm_dist_tag`: npm target tag for the publish path; defaults to `beta`
|
|
|
|
`OpenClaw Release Publish` accepts these operator-controlled inputs:
|
|
|
|
- `tag`: required release tag; must already exist
|
|
- `preflight_run_id`: successful `OpenClaw NPM Release` preflight run id;
|
|
required when `publish_openclaw_npm=true`
|
|
- `npm_dist_tag`: npm target tag for the OpenClaw package
|
|
- `plugin_publish_scope`: defaults to `all-publishable`; use `selected` only
|
|
for focused repair work
|
|
- `plugins`: comma-separated `@openclaw/*` package names when
|
|
`plugin_publish_scope=selected`
|
|
- `publish_openclaw_npm`: defaults to `true`; set `false` only when using the
|
|
workflow as a plugin-only repair orchestrator
|
|
|
|
`OpenClaw Release Checks` accepts these operator-controlled inputs:
|
|
|
|
- `ref`: branch, tag, or full commit SHA to validate. Secret-bearing checks
|
|
require the resolved commit to be reachable from an OpenClaw branch or
|
|
release tag.
|
|
- `run_release_soak`: opt into exhaustive live/E2E, Docker release-path, and
|
|
all-since upgrade-survivor soak on stable/default release checks. It is forced
|
|
on by `release_profile=full`.
|
|
|
|
Rules:
|
|
|
|
- Stable and correction tags may publish to either `beta` or `latest`
|
|
- Beta prerelease tags may publish only to `beta`
|
|
- For `OpenClaw NPM Release`, full commit SHA input is allowed only when
|
|
`preflight_only=true`
|
|
- `OpenClaw Release Checks` and `Full Release Validation` are always
|
|
validation-only
|
|
- The real publish path must use the same `npm_dist_tag` used during preflight;
|
|
the workflow verifies that metadata before publish continues
|
|
|
|
## Stable npm release sequence
|
|
|
|
When cutting a stable npm release:
|
|
|
|
1. Run `OpenClaw NPM Release` with `preflight_only=true`
|
|
- Before a tag exists, you may use the current full workflow-branch commit
|
|
SHA for a validation-only dry run of the preflight workflow
|
|
2. Choose `npm_dist_tag=beta` for the normal beta-first flow, or `latest` only
|
|
when you intentionally want a direct stable publish
|
|
3. Run `Full Release Validation` on the release branch, release tag, or full
|
|
commit SHA when you want normal CI plus live prompt cache, Docker, QA Lab,
|
|
Matrix, and Telegram coverage from one manual workflow
|
|
4. If you intentionally only need the deterministic normal test graph, run the
|
|
manual `CI` workflow on the release ref instead
|
|
5. Save the successful `preflight_run_id`
|
|
6. Run `OpenClaw Release Publish` with the same `tag`, the same `npm_dist_tag`,
|
|
and the saved `preflight_run_id`; it publishes externalized plugins to npm
|
|
and ClawHub before promoting the OpenClaw npm package
|
|
7. If the release landed on `beta`, use the private
|
|
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
|
workflow to promote that stable version from `beta` to `latest`
|
|
8. If the release intentionally published directly to `latest` and `beta`
|
|
should follow the same stable build immediately, use that same private
|
|
workflow to point both dist-tags at the stable version, or let its scheduled
|
|
self-healing sync move `beta` later
|
|
|
|
The dist-tag mutation lives in the private repo for security because it still
|
|
requires `NPM_TOKEN`, while the public repo keeps OIDC-only publish.
|
|
|
|
That keeps the direct publish path and the beta-first promotion path both
|
|
documented and operator-visible.
|
|
|
|
If a maintainer must fall back to local npm authentication, run any 1Password
|
|
CLI (`op`) commands only inside a dedicated tmux session. Do not call `op`
|
|
directly from the main agent shell; keeping it inside tmux makes prompts,
|
|
alerts, and OTP handling observable and prevents repeated host alerts.
|
|
|
|
## Public references
|
|
|
|
- [`.github/workflows/full-release-validation.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/full-release-validation.yml)
|
|
- [`.github/workflows/package-acceptance.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/package-acceptance.yml)
|
|
- [`.github/workflows/openclaw-npm-release.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/openclaw-npm-release.yml)
|
|
- [`.github/workflows/openclaw-release-checks.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/openclaw-release-checks.yml)
|
|
- [`.github/workflows/openclaw-cross-os-release-checks-reusable.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/openclaw-cross-os-release-checks-reusable.yml)
|
|
- [`scripts/resolve-openclaw-package-candidate.mjs`](https://github.com/openclaw/openclaw/blob/main/scripts/resolve-openclaw-package-candidate.mjs)
|
|
- [`scripts/openclaw-npm-release-check.ts`](https://github.com/openclaw/openclaw/blob/main/scripts/openclaw-npm-release-check.ts)
|
|
- [`scripts/package-mac-dist.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/package-mac-dist.sh)
|
|
- [`scripts/make_appcast.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/make_appcast.sh)
|
|
|
|
Maintainers use the private release docs in
|
|
[`openclaw/maintainers/release/README.md`](https://github.com/openclaw/maintainers/blob/main/release/README.md)
|
|
for the actual runbook.
|
|
|
|
## Related
|
|
|
|
- [Release channels](/install/development-channels)
|