Releasing
Introduction
This page is for maintainers. The set — vuka, ui, web, cmd/vuka and cmd/vukavet — is released by one command, so every module of a release is checked, tagged and published together.
Running a Release
Run the command in a vuka checkout with the ui and web checkouts beside it:
work/
vuka/ github.com/vuka-lang/vuka/v2 (and cmd/vuka, cmd/vukavet)
vuka-ui/ github.com/vuka-lang/ui/v2
vuka-web/ github.com/vuka-lang/web/v2A dry run prints the plan; -yes carries it out:
cd work/vuka
vuka release v2.1.0 # checks, then prints the plan; changes nothing
vuka release -yes v2.1.0 # does it-ui and -web point at checkouts elsewhere.
Before You Run It
Write the release's section in docs/releases.md, headed with the version and date, for app authors: what changed, what to do, the required source changes. The heading looks like this:
## v2.1.0 — 2026-11-02A section marked unreleased passes a dry run with a warning and stops -yes.
A deprecation or (in a major) a breaking change also needs documented source changes and an upgradeSteps entry naming it (cmd/vuka/upgrade.go), so vuka upgrade runs it for apps crossing the release. An entry looks like this:
var upgradeSteps = []upgradeStep{
{"v1.2.0", []string{"url-tags"}, "url:\"q\" tags become @ui.URL(\"q\")"},
}Checks
Every run, dry or not, checks:
- each repository is on
main, has no uncommitted changes, and is level withorigin/main(after a fetch); - each module is the one expected, and
cmd/vuka/toolchain.gohas its four version constants; - the version is
vX.Y.Z, at least v0.50.0, after every tag of every module of the set, and its major is the one the module paths carry (/v2for v2.x); docs/releases.mdhas its section;- the patch train: a patch release within seven days of the set's last one is refused unless
-securitysays it is a security fix; go vet ./...andgo test ./...pass in each module, run against the checkouts being released: for the run, a module's requirements of vuka, ui and web are replaced by their checkouts, as CI does, and its go.mod and go.sum are put back after;VUKAis the command built from them, and apps the tests make withvuka neware pointed at them and at an orm checkoutvuka-ormbeside them (VUKA_NEW_REPLACE, unless set) (-no-testskips them, for a quick look at the plan).
A failed check stops the release before anything changes.
What It Does
In dependency order, so each module requires tags that exist:
- tag vuka
vX.Y.Z(annotated) and push it; - ui:
go get github.com/vuka-lang/vuka/v2@vX.Y.Z,go build ./..., commit, tag, push; - web:
go getvuka and ui atvX.Y.Z, build, commit, tag, push; - cmd/vuka: write
vX.Y.Zintotoolchain.go(the command's version and the setvuka newpins),go getvuka and the other libraries of the set its go.mod requires, build, commit, tagcmd/vuka/vX.Y.Z, push; - cmd/vukavet: tag
cmd/vukavet/vX.Y.Zon the same commit and push it (it requires none of the set); - wait for proxy.golang.org to serve the five modules (
-proxy-wait, 10m by default; 0 skips it; a slow proxy is a warning, not a failure); - install
github.com/vuka-lang/vuka/cmd/vuka/v2@vX.Y.Zandgithub.com/vuka-lang/vuka/cmd/vukavet/v2@vX.Y.ZwithGOPROXY=directinto a temporary directory and check that itsvuka versionreports the set.
NOTE
The go commands run with GOPROXY=direct GOSUMDB=off GOWORK=off, so fresh tags resolve at once and a go.work doesn't leak local checkouts into a release. It never runs go mod tidy.
Scaffold Lockfiles
Each frontend package.json vuka new writes has a package-lock.json beside it in cmd/vuka/scaffold/app (the Vue, React and Svelte frontends' are templates, for the app's name), so installs run npm ci and don't resolve the packages from scratch. After changing a scaffold package.json, regenerate the lockfiles with npm 11 (the script runs it with npx):
cd cmd/vuka
sh scripts/lockfiles.sh # or: go generate -run lockfiles .TestScaffoldLockfiles fails while a lockfile's packages differ from its package.json's. Regenerate them before a release, too, so new apps start on current versions within their ranges.
WARNING
Generate them with npm 11 or newer: npm 10 can't resolve the islands' web/ set.
Releasing the ORM
github.com/vuka-lang/orm/v2 has versions of its own and isn't part of vuka release. It requires vuka and web, so a release of it that should require a new set comes after that set: in an orm checkout on main,
GOPROXY=direct GOSUMDB=off GOWORK=off go get github.com/vuka-lang/vuka/v2@vX.Y.Z github.com/vuka-lang/web/v2@vX.Y.Z
go build ./... && go vet ./... && go test ./...
git commit -am "orm vA.B.C: require vuka, web vX.Y.Z"
git tag -a vA.B.C -m "orm vA.B.C"
git push origin HEAD:refs/heads/main refs/tags/vA.B.CormVersion in cmd/vuka/new.go is the orm vuka new pins and vuka upgrade moves apps to; a release of the set whose scaffolds need a new orm sets it in the release's pull request and releases the orm right after the set.
When a Step Fails
WARNING
Tags are never moved or deleted.
Fix the cause and run the same command again: a module whose tag is already on its branch is skipped, and the release carries on with the next. A step that failed after its commit but before its tag leaves the repository ahead of origin/main; push that commit (or reset it) so the checks pass, then rerun.
The VS Code Extension
The extension in editors/vscode has its own version and is published by the Extension workflow when a vscode-vX.Y.Z tag is pushed (or by hand from the Actions tab). The tag must match version in its package.json:
git tag vscode-v0.5.0 && git push origin vscode-v0.5.0The run tests the grammars, packages vuka.vsix (kept as an artifact), then publishes it:
- Open VSX (VSCodium and other VS Code–based editors) with the
OVSX_PATsecret: a token from open-vsx.org for an account that owns thevuka-langnamespace (npx ovsx create-namespace vuka-lang -p <token>, once). - VS Code Marketplace with the
VSCE_PATsecret: an Azure DevOps token with the Marketplace "Manage" scope for thevuka-langpublisher. Skipped while the secret isn't set.