This guide describes repository publication and every RelayCtl version after
v1.0.0. Deployment operators should use the
production deployment guide.
RelayCtl follows Semantic Versioning:
PATCH(1.0.0to1.0.1) is for backward-compatible fixes and security updates.MINOR(1.0.0to1.1.0) is for backward-compatible features and additive APIs.MAJOR(1.xto2.0.0) is required for breaking API, SDK, webhook, configuration, deployment, or data-contract changes.- A prerelease such as
1.1.0-rc.1is not a production recommendation and is published as a GitHub prerelease.
From 1.0.0 onward, existing migration files and released tags are immutable.
A correction is always a new version.
The release workflow requires these values to agree:
- root
VERSION, containing the version without avprefix; - an entry named
## [x.y.z]inCHANGELOG.md; - bilingual notes at
docs/release-notes/vx.y.z.md; - the pushed Git tag
vx.y.z.
Install Git and GitHub CLI, authenticate with gh auth login, and verify the
publication set contains no .env, .relayctl, .playwright-cli, logs,
backups, browser state, generated output, or upstream credentials.
git branch -M main
git status --ignored --short
git add --all
git diff --cached --name-only
git diff --cached --stat
git commit -m "Release RelayCtl v1.0.0"
gh repo create Sen62455/relayctl `
--public `
--source . `
--remote origin `
--description "Unified control plane for NewAPI, CLIProxyAPI, CPA Manager Plus, and Sub2API"
git push -u origin mainCreate an annotated SDK submodule tag for the standalone Go SDK, then create the root product tag. The SDK tag prefix is required by Go module versioning.
git tag -a sdk/go/relayctl/v1.0.0 -m "RelayCtl Go SDK v1.0.0"
git push origin sdk/go/relayctl/v1.0.0
git tag -a v1.0.0 -m "RelayCtl v1.0.0"
git push origin v1.0.0Pushing the root tag starts .github/workflows/release.yml. Do not manually
create another GitHub Release with the same tag.
Start from an up-to-date main and use a short release branch:
git switch main
git pull --ff-only
git switch -c codex/release-v1.1.0Then:
- Change
VERSIONto the new version withoutv. - Move user-visible
CHANGELOG.mditems fromUnreleasedinto a dated version section, keeping an emptyUnreleasedsection at the top. - Add bilingual
docs/release-notes/vx.y.z.mdnotes. State migrations, compatibility, known limitations, backup requirements, and rollback limits. - Update documentation and
.env.examplewhen behavior or configuration changes. - If the standalone SDK changed, update its compatibility notes and plan the
matching
sdk/go/relayctl/vx.y.ztag. - Run the full verification set below, open a pull request, and merge only after CI succeeds.
Use a disposable PostgreSQL database for integration tests:
go test ./...
go vet ./...
$env:APIM_TEST_DATABASE_URL = 'postgres://relayctl@127.0.0.1:5432/relayctl_test?sslmode=disable'
go test ./internal/database -run TestMigratorIntegration -count=1
go test -p 1 ./... -count=1
Push-Location .\sdk\go\relayctl
go test ./...
go vet ./...
Pop-Location
Push-Location .\examples\webhook-connector
go test ./...
go vet ./...
Pop-Location
Push-Location .\web
npm ci
npm run typecheck
npm run lint
npm run build
npm run test:e2e
Pop-LocationAlso validate production Compose and perform the secret/staged-file audit from the first-publication section. Never run integration tests against production.
After the release pull request is merged, tag the exact tested commit on
main:
$version = (Get-Content .\VERSION -Raw).Trim()
git switch main
git pull --ff-only
git status --short
# Only when the standalone SDK changed for this version:
git tag -a "sdk/go/relayctl/v$version" -m "RelayCtl Go SDK v$version"
git push origin "sdk/go/relayctl/v$version"
git tag -a "v$version" -m "RelayCtl v$version"
git push origin "v$version"Watch both CI and Release workflows:
gh run list --repo Sen62455/relayctl --limit 10
gh run watch --repo Sen62455/relayctl <run-id>
gh release view "v$version" --repo Sen62455/relayctlThe release is complete only when all workflow jobs pass, the GitHub Release
contains SHA256SUMS and every expected archive, both GHCR images have amd64
and arm64 manifests, the container packages are public, and checksum
verification succeeds on a freshly downloaded asset.
If a workflow fails, fix the cause in a new commit. Before any user has consumed the release, a maintainer may delete only the failed unpublished tag and retry after review. Once a tag, image, module, or release is public, never move or overwrite it; increment the version instead.
Before production rollout, take a verified backup and complete an isolated
restore drill. Pin container images by digest or verify the Windows binary with
SHA256SUMS. Roll out one worker set, verify readiness, authentication,
metrics, migrations, and a read-only collection, then announce the release with
links to its notes and deployment guide.
Binary rollback is allowed only when the database migration version did not advance. If it advanced, restore the matching pre-upgrade database into an isolated target before any approved cutover.