DBFlux uses trunk-based development with short-lived release branches. One long-lived branch (main) is the integration target; a release/vX.Y branch is cut per minor during stabilization and discarded after EOL.
This document is the human-facing reference. The automated dbflux-release skill (skills/dbflux-release/SKILL.md) follows these same rules.
| Channel | Source branch | Tag pattern | GitHub release kind | Built by |
|---|---|---|---|---|
| nightly | main HEAD |
nightly (rolling) |
prerelease | Cron — daily |
| rc | release/vX.Y |
vX.Y.Z-rc.N |
prerelease | Tag push |
| stable | release/vX.Y |
vX.Y.Z |
published | Tag push |
The -dev.N channel is retired. Nightly replaces it. Old -dev.N tags remain on GitHub but no new ones are created.
Per-channel application icons are tracked in issue #183. Do not implement them here.
The changelog is derived from git history by git-cliff. Do not hand-edit [Unreleased].
cliff.tomlat the repo root configures the generator.[Unreleased]means "every user-visible conventional commit since the last stable tag." rc and nightly tags are transparent: they do not close the[Unreleased]window (skip_tagsincliff.toml).- Commit messages are load-bearing. A
feat,fix, orperfcommit surfaces in the changelog; achore,ci,docs,test,refactor, orstylecommit is dropped. Security-relevant changes usefix(security):or aSecurity:footer. - The
[Unreleased]block closes only at stable. When a stable tag is pushed, git-cliff renders the full set of user-visible commits since the previous stable as the release notes for that tag. - Do not hand-rename
[Unreleased]when cutting an RC or a nightly. The RC cut procedure is simpler under this model — see below.
CHANGELOG.md is kept in the repository and updated at release time by prepending the new version's section with git-cliff --prepend. It is never hand-edited and never fully regenerated — a full regeneration (git-cliff -o CHANGELOG.md) would collapse all historical sections into one range from the last stable tag, destroying the ## [0.6.0] and ## [0.6.0-dev.N] entries.
v0.7.0 transition: git-cliff changelog generation applies from v0.7.0 onward. The
## [0.6.0]and## [0.6.0-dev.N]sections are hand-written baselines committed toCHANGELOG.md. They must never be regenerated — doing so would duplicate or collapse them. The prepend workflow begins with the first v0.7.0 RC.
| Branch | Lifetime | Accepts | Tags produced |
|---|---|---|---|
main |
permanent | every new commit (features, fixes, refactors) | (none — nightly rolling) |
release/vX.Y |
until EOL | cherry-picked fixes only (no new features) | vX.Y.Z-rc.N, vX.Y.Z, vX.Y.(Z+1) |
- A commit is never authored on a release branch. It always lands on
mainfirst, then isgit cherry-pick -x <sha>into the release branch. - A release branch is never merged back into
main. - No new features on a release branch once cut. Only bugfixes and the release's own version-artifact bumps.
mainis always open for development. There is no manual CHANGELOG entry required onmain— commit messages carry the information.
Tags must be annotated:
git tag -a vX.Y.Z[-suffix.N] -m "vX.Y.Z[-suffix.N]"
git push origin vX.Y.Z[-suffix.N]The release workflow (.github/workflows/release.yml) classifies tags automatically:
| Tag pattern | Allowed source branch | GitHub release kind |
|---|---|---|
vX.Y.Z-rc.N |
release/vX.Y |
prerelease |
vX.Y.Z |
release/vX.Y |
stable (published) |
| anything else | (safety net) | draft |
The workspace version (Cargo.toml [workspace.package].version) is the source of truth. All other manifests must stay in lockstep.
On main:
The manifest version is X.(Y+1).0-dev.0, where X.Y is the minor currently being stabilized on release/vX.Y. This marker is set when release/vX.Y is cut and stays on main through the entire stabilization window and beyond, until the next cut. It is a development marker only — no -dev.N releases are ever published. The nightly workflow derives X.(Y+1).0-nightly+<sha> from it by stripping the pre-release suffix and appending -nightly+<short-sha>.
On release/vX.Y:
- Next RC: if the last tag is
vX.Y.Z-rc.N→-rc.(N+1). If none →-rc.0. - Promote to stable: drop the RC suffix →
vX.Y.0. - Patch: increment
Z→vX.Y.(Z+1). Never bump the minor on a release branch.
- Features land on
main. No manual changelog entries required. - When ready to stabilize, cut
release/v0.7frommainHEAD.- On
release/v0.7: bump every versioned artifact to0.7.0-rc.0. Commit and push. - On
main: bump every versioned artifact to0.8.0-dev.0. Commit and push.mainnow targets the next minor. - Tag
v0.7.0-rc.0on the release branch. git-cliff renders the unreleased range as the RC body automatically.
- On
- A bug is found during RC:
- Commit the fix on
main. git cherry-pick -x <sha>intorelease/v0.7.- Bump to
v0.7.0-rc.1and tag.
- Commit the fix on
- When clean, bump the release branch from
v0.7.0-rc.Ntov0.7.0. Tagv0.7.0. git-cliff renders the full unreleased range (sincev0.6.0) as the stable release notes. mainis already on0.8.0-dev.0— no further bump needed after stable.- Patches (
v0.7.1,v0.7.2, …) come from the same release branch via cherry-picks frommain.
-
Verify you are on
main, clean tree, up to date withorigin/main. -
Verify
.github/workflows/release.ymlonmaincontains theClassify releasejob. If missing, fix onmainfirst — otherwise stable tags will publish as drafts. -
Create the branch (use a dedicated worktree if you use the bare-repo layout so
mainstays checked out):git worktree add ../release-vX.Y -b release/vX.Y main # or in a single-checkout repo: git checkout -b release/vX.Y -
On
release/vX.Y:-
Bump every versioned artifact to
X.Y.0-rc.0(see Files to Bump). -
Prepend the new RC section to
CHANGELOG.md:git-cliff --tag vX.Y.0-rc.0 --unreleased --prepend CHANGELOG.md git add CHANGELOG.md # fold into the same chore(release) commit as the version bumpWarning: do NOT use
git-cliff -o CHANGELOG.md. That fully regenerates the file and collapses all historical sections since the last stable tag into a single block. -
Commit:
chore(release): cut release/vX.Y at vX.Y.0-rc.0. -
Push:
git push -u origin release/vX.Y.
-
-
Back on
main:- Bump every versioned artifact to
X.(Y+1).0-dev.0(main now targets the next minor). - Commit:
chore(version): move main to X.(Y+1).0-dev.0 marker. - Push.
- Bump every versioned artifact to
-
Tag
vX.Y.0-rc.0on the release branch.
There is no CHANGELOG rename step under the git-cliff model. The RC release body is generated from conventional commits automatically.
Run on release/vX.Y when the RC is clean:
-
Bump every versioned artifact from
X.Y.0-rc.NtoX.Y.0. -
Prepend the stable section to
CHANGELOG.md:git-cliff --tag vX.Y.0 --unreleased --prepend CHANGELOG.md git add CHANGELOG.md # fold into the same chore(release) commit as the version bumpWarning: do NOT use
git-cliff -o CHANGELOG.md. That fully regenerates the file and collapses all historical sections since the last stable tag into a single block. -
Commit:
chore(release): promote release/vX.Y to vX.Y.0. -
Tag
vX.Y.0on the release branch and push branch + tag.
git-cliff generates the curated release notes from all user-visible commits since the previous stable tag. There is no manual CHANGELOG curation step.
Optional curation: if you want to add a human-written intro or editorial note to the stable release body, you can do so directly in the GitHub Release edit UI after the workflow publishes it. This does not touch CHANGELOG.md.
main is bumped to X.(Y+1).0-dev.0 when release/vX.Y is cut (see Cut Procedure, step 5). No further bump to main is required after the stable tag. Nightly builds continue from main HEAD automatically, producing X.(Y+1).0-nightly+<sha> throughout the stabilization window.
Per release, update all of the following to the exact same version:
Cargo.toml—[workspace.package].version. Workspace crates inherit viaversion.workspace = true.flake.nixresources/windows/installer.iss- Manual review (does not inherit):
examples/custom_driver/Cargo.toml.
After the GitHub Release artifacts for the tag are published, also update:
nix/release-info.nix—version+ both prebuilt-tarballurls andhashes (see Nix below). This is a per-branch channel pointer. It requires the published artifacts, so it lands as a follow-up commit once the release workflow finishes.
The AUR PKGBUILD lives in an external AUR repository, not in this repo. It is bumped only for stable tags.
.github/workflows/nightly.yml runs daily at 03:17 UTC:
- Reads the workspace version from
Cargo.toml, strips any existing pre-release suffix, and appends-nightly+<short-sha>(e.g.0.8.0-nightly+abc1234whenmaincarries0.8.0-dev.0). NoCargo.tomlcommit required. Becausemaintracks the next minor from the momentrelease/vX.Yis cut, the nightly version is always clearly ahead of the stabilizing line. - Calls
build.ymlwithchannel: nightly. - Computes the SHA256 SRI hash of each Linux tarball and regenerates
nix/nightly-info.nixwith the real hashes and the rolling release URLs. - Commits the updated
nix/nightly-info.nixon top of the currentmainHEAD. This commit is not pushed tomain— it becomes the sole target of thenightlytag. - Force-moves the
nightlytag to the pin commit and pushes the tag. Pushing the tag is sufficient to make the commit reachable on the remote; no branch push is required. - Publishes or updates the rolling
nightlyGitHub prerelease with the new artifacts and a git-cliff-generated body covering commits since the last stable tag. The release's tag points at the pin commit, sonix/nightly-info.nixatnightlyref always matches the published artifacts.
The nightly tag is force-pushed and the release is replaced on every run. Only the canonical repository (0xErwin1/dbflux) runs the schedule.
Skip when main has not advanced. A scheduled run first compares the current main HEAD against the commit the last nightly was built from (git rev-parse nightly^, the pin commit's first parent). If they match, the run skips entirely: no rebuild, no tag move, no release churn. This avoids republishing an identical build under a fresh, non-reproducible hash that would needlessly break Nix pins. A manual workflow_dispatch run always builds, even with no new commits.
The workflow pins nix/nightly-info.nix at the nightly ref on every run. Downstream users get the prebuilt nightly binary without compiling from source:
# Run nightly directly
nix run github:0xErwin1/dbflux/nightly#dbflux-nightly
# Install into a profile
nix profile install github:0xErwin1/dbflux/nightly#dbflux-nightlyA from-source nightly (no hash pinning required) also works:
nix run github:0xErwin1/dbflux/nightly#dbflux-sourceDo not consume #dbflux-nightly from main. On main, nix/nightly-info.nix contains placeholder hashes that will not fetch. Always use the nightly ref as shown above.
A release branch should never contain commits absent from main, except release-only commits (chore(release): ..., chore(version): ...).
# On main: land the fix.
git checkout main
# ...commit, push...
# On release branch: cherry-pick with -x to record the source SHA.
git checkout release/vX.Y
git cherry-pick -x <sha>Audit: every non-release commit on release/vX.Y since branch-off should mention (cherry picked from commit ...) in its message.
git log --grep='cherry picked from' release/vX.Y| Tag kind | GitHub Release | AUR | Nix flake (this repo) | nixpkgs (future) |
|---|---|---|---|---|
| nightly | prerelease | skip | auto-pinned — #dbflux-nightly on nightly ref |
skip |
-rc.N |
prerelease | skip | bump release branch's + main's release-info |
skip |
Stable vX.Y.Z |
published | bump + push | bump release branch's + main's release-info |
bump + PR |
AUR pkgver does not allow - (reserved for pkgrel). For stable releases the translation is a no-op (pkgver=X.Y.Z). For hypothetical AUR prereleases:
vX.Y.Z-rc.N→pkgver=X.Y.Z.rc.N
The flake exposes several packages on Linux (x86_64 and aarch64):
| Package | What it provides |
|---|---|
dbflux (default) |
Prebuilt stable/rc binary when available, source otherwise |
dbflux-bin |
Explicit prebuilt from nix/release-info.nix |
dbflux-source |
Source build via crane (all platforms) |
dbflux-nightly |
Rolling nightly prebuilt from nix/nightly-info.nix (use nightly ref) |
Stable / RC (nix/release-info.nix): per-branch channel pointer. main tracks the newest published tag of any kind; each release/vX.Y tracks its own line's newest. After a tag's artifacts publish, refresh release-info.nix on every branch whose channel that tag advances.
ver=X.Y.Z
for arch in amd64 arm64; do
hex=$(curl -fsSL "https://github.com/0xErwin1/dbflux/releases/download/v$ver/dbflux-linux-$arch.tar.gz.sha256" | awk '{print $1}')
nix-hash --to-sri --type sha256 "$hex"
doneUpdate version, both urls, and both hashes in nix/release-info.nix. Verify locally:
nix build .#dbflux-bin --no-link --print-out-pathsNightly (nix/nightly-info.nix): auto-updated by the nightly workflow on the nightly ref. Do not update this file manually. Consume via:
nix run github:0xErwin1/dbflux/nightly#dbflux-nightlyNot yet upstream. When it is, only stable tags will get a PR to NixOS/nixpkgs. PR title convention: dbflux: A -> B.
- Tagging
vX.Y.ZorvX.Y.Z-rc.Nwhile HEAD is onmain. - Tagging an RC while HEAD is on
main. - Merging
release/vX.Yback intomain. - Creating new features (non-fix commits) on a
release/*branch. - Bumping minor or major version inside a
release/*branch. - Pushing a tag without a clean working tree.
- Pushing the AUR bump with
pkgvercontaining a hyphen. - Cutting
release/vX.Yfrom amainHEAD that does not contain theClassify releasejob inrelease.yml. - Creating new
-dev.Ntags (the channel is retired; use nightly instead).
cargo check --workspace
cargo fmt --all -- --check
cargo clippy --workspace -- -D warnings
cargo test --workspace.github/workflows/release.yml— classification logic and artifact publishing.github/workflows/nightly.yml— daily nightly build.github/workflows/build.yml— reusable build jobs (called by release and nightly).github/release-template.md— installation section appended to every release bodycliff.toml— git-cliff configuration for changelog generationskills/dbflux-release/SKILL.md— agent-facing skill that automates this process