Commits
Use this shape:feat, fix, perf, refactor, docs, test, build,
and chore. Scopes name the affected area, such as mail, ui, or api.
Use ! and a BREAKING CHANGE: footer when a commit breaks a documented
interface.
Keep subjects brief and bodies focused.
Changelog and versions
User-visible changes update the[Unreleased] section of
CHANGELOG.md
in the same pull request. Write for operators and call out required migration
steps directly.
A release normally adds at most one numbered database migration; never rewrite a
published migration. For this taxonomy cutover, beta.2 at schema 0002 is the published
upgrade baseline. Published 0001/0002 are unchanged; all unreleased mobile and
taxonomy changes are consolidated in 0003_taxonomy_foundation.sql. Verify fresh
initialization and populated 0002 → 0003 upgrades, restart idempotence, preserved
data and failed-upgrade rollback. Intermediate development schemas are not supported
upgrade inputs. The rebuild marker must remain the first line of 0003.
See Architecture for the runner.
Before v1.0, plan a fresh-schema baseline and a final beta upgrade bridge. The final
beta must bring supported older archives to the baseline’s schema version. v1.0
can then create that schema directly for a new database, accept an archive already
at that version, and direct older archives to the tagged final beta first. Keep
schema versions increasing independently of release versions. Remove the old
upgrade SQL from the active runner only after testing exact schema equivalence
and the complete upgrade path. This transition requires migration-runner support;
renaming branches or resetting schema version numbers cannot implement it.
Suchi follows SemVer:
MAJOR: incompatible stable-interface changes after 1.0MINOR: features and potentially breaking pre-1.0 changesPATCH: fixes and internal changes
Release checklist
-
When the web app changed, rebuild its committed embedded copy and review the
generated asset changes:
-
Move the
[Unreleased]entries under the new version and date. UpdatedevelopmentVersionindistro/cmd/suchi/main.goto the current source version line with a-devsuffix. - Confirm the shipped Microsoft OAuth registration still permits personal and work/school device-code sign-in.
-
Run the local verification suite:
- Manually exercise behavior that depends on external services or accounts, including Microsoft sign-in, configured email providers, and hosted LLMs affected by the release.
- Recheck public size, memory, startup, network, and feature claims against the accepted benchmark and the final build.
-
Commit the release metadata, then create and push a signed annotated tag:
-
Dispatch the manual release workflow:
Use
PUBLISH=falsefor an artifacts-only run.
anydoc export target. Those binaries and licenses are packaged for standalone
downloads. The image job downloads only that run’s AnyDoc artifacts, verifies
their checksums, and supplies them as an anydoc named build context for both
runtime variants. Docker selects the matching amd64 or arm64 directory;
missing or damaged artifacts fail the build instead of triggering recompilation.
Plain local Docker builds omit that context and still compile from pinned source.
Release builds inject the version and source revision into the Go binary.
Settings reads the identity from /api/whoami, showing only the version for
tagged production releases. Unversioned builds use the source’s
developmentVersion (currently v0.1.0-beta.2-dev) and append the short revision
when available. suchi version likewise retains an injected release version and
adds the revision for development builds. Docker has no .git directory, so
manual builds must pass REVISION to retain source identification and VERSION
for a tagged release. Local VCS builds without an injected version use the source
version line, not Go’s tag-derived module pseudo-version. Missing development
revisions are labeled unavailable, not guessed.
Publishing container images without Actions
GHCR images can be built and pushed directly when Actions is unavailable. Build from the release tag, never from a different branch with the release version injected: the image contents must agree with the Git tag. Set the release coordinates on every build machine:write:packages. The login username is the personal account that owns the
token, which may differ from the organization in IMAGE:
Build on native architecture hosts
Rust compilation foranydoc is very slow through QEMU. A cancelled
cargo build step is not cached because its Docker layer never completes. For
a faster multi-architecture release, build AMD64 on an x86-64 Linux host and
ARM64 on an Apple Silicon or Linux ARM64 host, push temporary architecture
tags, and combine them into the public manifest.
On the x86-64 Linux host:
anydoc source commit and build instructions are
pinned independently of the Suchi version, so the completed Rust layer is reused
until that pin or recipe changes. Cargo registry and target cache mounts also
retain incremental work in the local BuildKit builder when a compile is
interrupted before its image layer can be exported.
The full image follows the same process with --target full and temporary
tags ending in -full-amd64 and -full-arm64; publish the final tags as
$VERSION-full and beta-full. beta-standard is an explicit alias for the
standard beta image and is useful where the selected image variant should be
obvious from configuration alone.
The first command-line push creates a private, unlinked GHCR package by
default. In the package settings, make it public, connect it to the Suchi
repository, and grant that repository Actions access so later workflow pushes
can update it. Direct local publication does not reproduce the workflow’s
keyless Cosign signatures or GitHub release artifacts; handle those separately
before calling the release complete.
Automation
checks.ymlis the single manual entry point for repository validation.ci.ymlruns formatting, tests, vet, lint, and UI checks when called by it.smoke.ymltests the built images and ingest paths when called by it. Both variants are rebuilt with the exported AnyDoc context and an unusable Rust base to catch accidental recompilation; binary and license bytes must match the export before the usual ingestion checks run.restore-drill.ymlvalidates backup restoration when called by it.release.ymlpublishes only when manually dispatched from an existing tag. Its preflight runs fresh Go/UI checks, embedded bundle parity, and dependency advisory scans. Images wait for both binary matrices before publication and reuse the AnyDoc matrix’s verified binaries rather than rebuilding them. Artifacts-only branch runs usesnapshot-<commit>names and skip signing and publication; they still produce ordinary workflow artifacts and GHA caches.
main.