release
GitHub规范 Kandev 版本管理与发布流程,涵盖 Stable SemVer、npm Nightly 及多平台分发渠道。指导维护者通过 CI 执行版本递增、构建、发布及通知贡献者等任务。
Trigger Scenarios
Install
npx skills add kdlbs/kandev --skill release -g -y
SKILL.md
Frontmatter
{
"name": "release",
"description": "Kandev release and version-channel conventions — unified Stable SemVer plus deterministic npm-only Nightlies. Use when cutting a release, changing channels, debugging artifacts, or answering version-channel questions."
}
Release & Versioning
Kandev Stable releases use a single SemVer X.Y.Z shared across all distribution channels.
npm also has an explicit prerelease-only nightly channel; it is not part of the unified Stable
artifact set.
Version targets
apps/cli/package.jsonversion →X.Y.Z- npm main package:
kandev@X.Y.Z - npm runtime packages:
@kdlbs/runtime-{platform}@X.Y.Z(5 platforms; declared asoptionalDependenciesin main package) - Git tag:
vX.Y.Z(three-part; legacyvM.mtags normalize toM.m.0) - Homebrew formula:
kdlbs/homebrew-kandevFormula/kandev.rbversion "X.Y.Z" - Scoop bucket:
kdlbs/scoop-kandevbucket/kandev.jsonversion, URL, and hash - GitHub release:
vX.Y.Zwith standard platform archiveskandev-{platform}.tar.gz, full offline archiveskandev-{platform}-full.tar.gz, checksums, Windows ZIP equivalents, remote helper assets, andruntime-size-report.md
Stable default archive names contain the standard runtime: host kandev, host agentctl, and
remote-helpers.json. The -full archives also contain all four remote helper executables. Stable
npm packages, Homebrew, Scoop, winget, Chocolatey, and Desktop use standard archives. Containers
and npm Nightlies stay full. Desktop keeps one standard installer and updater track.
npm, Homebrew, and Scoop are sibling channels, not chained. All three consume the same GitHub release artifacts; none depends on another package-manager channel.
For npm Nightly, Stable X.Y.Z plus a full main SHA produces
X.Y.(Z+1)-nightly.sha<first-12-lowercase-hex>. kandev and all five runtime packages publish at
that exact version under npm's nightly dist-tag. Nightly never moves latest and creates no Git
tag, GitHub Release, Homebrew formula, Scoop bucket update, Desktop feed/build, or container tag.
Release flow
Stable runs entirely in CI via .github/workflows/release.yml, triggered by a maintainer from the GitHub Actions UI:
- Maintainer clicks "Run workflow" → keeps
channel=stable→ picksbump(patch/minor/major) → optionaldry_runordesktop_validation_only. preparejob bumps version + regenerates CHANGELOG, opens release PR, squash-merges, tagsvX.Y.Z.build-web,build-bundles,build-remote-helpers,build-desktop, and both Docker builds create the channel inputs.publish-releasepromotes staged standard archives to the existing default names, publishes full archives and helper assets, then attaches checksums, the size report, desktop artifacts, and notes.publish-npmpublishes 5@kdlbs/runtime-*packages + mainkandevpackage to npmjs.update-homebrew-tappushes updatedFormula/kandev.rbtokdlbs/homebrew-kandevvia SSH deploy key.update-scoop-bucketpushes updatedbucket/kandev.jsontokdlbs/scoop-kandevvia its SSH deploy key.
Contributor notices
The Release workflow has a notify_contributors checkbox. It defaults to false. When selected, the workflow calls the reusable notification workflow after GitHub Release, npm, Homebrew, and Scoop publication all succeed. Dry runs, desktop validation, Nightly, cancellation before the notification job starts, and publication errors skip the call. Cancellation after posting starts can leave partial notices; rerun with the exact tag to complete safely.
For manual notices or recovery, run Notify release contributors from the main ref. Leave release_tag empty to select the latest published Stable release. Enter an exact tag to select another release. The dry_run checkbox previews the same PR selection and comment text without posting.
The helper reads PR links from the release notes. It posts only to merged PRs from this repository that belong to the selected release tag. It excludes bots and maintainers from cliff.toml. The job token posts as github-actions[bot]. Only notices from that bot or a listed maintainer count as already sent.
Each comment includes a hidden release ID marker. Repeat runs skip comments with that marker and the exact unmarked notice used for v0.97.0. After a partial run, use the separate workflow with the exact tag. It skips confirmed notices and retries only missing notices. Wait for GitHub rate limits to clear before retrying.
Release PR ruleset bypass
A normal Stable release creates its branch and pull request with GITHUB_TOKEN.
It uses RELEASE_PR_BYPASS_TOKEN only for an exact-head gh pr merge --admin.
Store this fine-grained personal access token in the protected release
environment. Its owner must remain an organization administrator. Select only
kdlbs/kandev and grant contents: write repository permission.
Record the token owner and expiration date. Rotate the environment secret before the token expires or the owner loses administrator access. The workflow must stop before tag creation when the token is missing or cannot bypass the ruleset.
After the merge, use GITHUB_TOKEN to read the PR state. Tag only the merge
commit that GitHub reports after it appears on origin/main.
Workflow-control invariant: When a channel intentionally skips a job, every
downstream job reachable through that dependency chain must use a status function
such as !cancelled() plus explicit needs.<job>.result == 'success' checks.
For a partial Stable release, preserve the existing signed tag and rerun with
backfill_tag; never run a normal bump against an existing tag. Declare Stable
complete only after publish-release, publish-npm, update-homebrew-tap, and
update-scoop-bucket each succeed and their artifacts are verified—an aggregate
green run can hide skipped publication jobs.
Required web, runtime, and desktop artifact uploads attempt up to three times,
with waits of 30 seconds and 60 seconds between attempts. They fail explicitly
when an expected file is missing. Desktop matrix targets use fail-fast: false
so a transient upload failure does not cancel sibling targets, but publication
still requires the complete matrix to succeed. Rerun a failed producer job in
the same workflow run after a transient failure. If the signed tag already
exists and the run remains partial, use backfill_tag for that tag after
checking which channels already succeeded.
Stable has no local release driver; the entire Stable flow runs in GHA. The Nightly metadata and
publication revalidation state machine lives in scripts/release/nightly-release.sh, which GHA
invokes for scheduled and manual Nightly runs.
The same workflow schedules npm Nightly with cron 0 12 * * *. It skips before building when
main has no commit after the latest Stable tag, the exact commit is already published, or a same
or newer main Nightly supersedes the scheduled commit. Eligible runs build only the shared web
bundle and five native runtime archives, then publish runtimes first and kandev last with OIDC
provenance. Stable and Nightly workflow runs share one non-cancelling release-wide concurrency
slot. Before publishing, Nightly rechecks the stable Git/npm baseline and the previously observed
nightly tag; a pending Stable tag or moved value safely suppresses stale publication.
Maintainers may run that same Nightly path from the Actions UI with the main ref and
channel=nightly. dry_run=true retains the real metadata and registry preflight but skips shared
builds and all npm writes. The shared form's required bump value is ignored for Nightly;
desktop_validation_only and backfill_tag are Stable-only and rejected when combined with it.
Validate Nightly automation changes with:
node --test scripts/release/nightly-version.test.mjs scripts/release/nightly-release.test.mjs
python3 .github/scripts/release-workflow-contract_test.py
bash -n scripts/release/nightly-release.sh scripts/release/publish-npm.sh
Release-tag signing configuration
The release workflow reads signing configuration from the GitHub release
environment. RELEASE_GPG_PRIVATE_KEY and the optional
RELEASE_GPG_PASSPHRASE are environment secrets. The full 40-character
RELEASE_GPG_FINGERPRINT is an environment variable, not a secret: the
workflow reads vars.RELEASE_GPG_FINGERPRINT, so storing it as a secret makes
normal-release preflight treat it as missing.
.github/release-signing-key.asc must contain exactly one public primary key
whose fingerprint matches that variable; never commit private key material.
backfill_tag repairs publication for an already-signed existing tag only and
does not bypass the normal-release signing checks.
Desktop signing is automatic. Complete macOS/Windows signing and notarization secrets produce signed artifacts; missing or incomplete signing inputs produce unsigned desktop artifacts and the GitHub release notes get an unsigned-artifact warning. desktop_validation_only=true builds artifacts from the current workflow ref for maintainer inspection and skips the release PR, tag, GitHub release, npm publish, Homebrew update, Scoop update, and public container tags.
Runtime resolution
The published npm shim (apps/cli/bin/native-shim.js) locates its bundled runtime via:
KANDEV_BUNDLE_DIRenv var (set by Homebrew wrapper, used by tests).- Installed
@kdlbs/runtime-{platform}npm package viarequire.resolve(). - The Homebrew/manual install path execs
bin/kandevdirectly. (--runtime-versionis rejected by the native launcher.)
Runtime helper binary checklist
When adding, renaming, or removing bundled helper binaries such as agentctl-<goos>-<goarch>, update every packaging surface in the same PR:
- backend build targets and scripts
- Docker/runtime image copy steps
.github/workflows/release.ymlbundle, macOS signing, and notarization loopsscripts/release/prepare-desktop-runtime.shscripts/release/verify-desktop-runtime.shscripts/release/remote-helper-assets.mjsapps/backend/internal/agent/runtime/lifecycle/remote_helper_manifest.goand the cache resolverscripts/release-desktop.test.shapps/desktop/AGENTS.mdruntime resource list
Verify with the helper build plus release-runtime tests, for example:
make -C apps/backend build-agentctl-remote
bash scripts/release-desktop.test.sh
Version History
-
ee1f355
Current 2026-10-19 04:24
新增稳定版运行时精简分发支持;增加发布后通知外部贡献者的功能。
-
d324d49
2026-09-22 09:46
增加CI发布工件上传的加固措施
-
c07691c
2026-08-19 20:45
新增 Scoop 渠道自动化发布支持;修复通过管理员 Token 绕过 Release PR 检查的问题。
-
1578843
2026-08-16 08:48
新增npm nightly渠道说明及对应的自动化发布流程,完善版本目标定义。
- b4239d8 2026-07-24 17:33


