This guide is for contributors to the Devctl repository. Project authors using the CLI should start with the user guide.
Install the repository-pinned tools once, or again after .mise.toml changes:
mise installRun the complete local CI contract through Mise:
mise run checkcheck runs the core checks plus golangci-lint and e2e workflows. The
check:core task contains formatting, dependency-graph hygiene, Go tests,
build, generated documentation, and the Orders API example. The separate
mise run test:race task runs the race-enabled suite; CI runs it on pushes to
main and on the nightly schedule.
Pull request CI runs the core, lint, and e2e checks in separate Linux jobs.
The separate Main CI workflow cross-builds the Devctl binary for macOS amd64
and arm64 with CGO disabled on pushes to main. The Docker image check runs
in PR CI only when Dockerfile or .dockerignore changes. Race tests run
separately on pushes to main and on the nightly schedule. Native macOS jobs
are intentionally not part of regular CI because the repository has no
platform-specific implementation. The release workflow still builds and
publishes native macOS release archives for both architectures.
Regenerate the CLI reference after changing visible command metadata:
mise run docs:generateThe command reference is generated from CLI metadata. docs:check checks that
reference; prose changes also need repository-local link and heading-anchor
checks. Product rules and architecture are indexed in Documentation.
| Artifact | Platforms |
|---|---|
| CLI release archive | Linux amd64, macOS amd64 and arm64 |
| Devctl container image | Linux amd64 and arm64 |
The release helper derives stable and RC versions through git-cliff and
existing tags. Stable calculation ignores RC tags; RC versions carry a
sequential -rc.N suffix. Release creation requires new commits and an unused
remote tag, creates an annotated tag, and builds with GOWORK=off and CGO
disabled. Archives include the binary, README, and license. The GitHub Release
is created as a draft for manual publication.
The image workflow accepts a published SemVer or RC release tag and checks its
commit/version metadata before building the image. Stable images receive both
the version tag and latest; RC images receive only their version tag. The
workflow publishes provenance attestations. The image packages Devctl, Go,
Git, Node, and quicktype; it is tooling for mounted Projects, not an application
deployment image generated by scaffold.
The source of these rules is the version helper, release workflow, and image workflow. Packaging the current checkout also requires resolving the local dependency constraint below.
For local work across sibling devctl and go-libs checkouts, create a Go
workspace outside either repository, for example in their parent directory:
go work init ./devctl ./go-libs/...Use that workspace only for interactive development. Do not commit go.work.
Before submitting, rerun the checks above with GOWORK=off so an external
workspace does not hide dependency-graph problems.
The current migration implementation temporarily requires
github.com/devctllabs/go-libs/dbmigrate v0.0.0 with a go.mod replacement to
../go-libs/dbmigrate. Keep that module in a sibling go-libs checkout; the
replacement also applies with GOWORK=off. A standalone release, module
installation, or Docker build needs a published dependency version in place of
this local replacement.
Run the focused CLI, service, and repository tests during migration changes:
GOWORK=off go test ./cmd/devctl/internal/migrate ./internal/service/migration ./internal/repository/migration
GOWORK=off go test ./cmd/devctl -run 'TestMigrateCIWorkflow|TestInitScaffoldCreatesMigrationToolingWithoutOwningSQL'Repository tests execute SQL against temporary SQLite databases, including no-change application, dirty state, partial rollback, file containment, and creation collisions. Environment tests cover URL precedence and safe failures. The main-package workflow runs the built CLI against a temporary SQLite Project; the scaffold test also exercises a generated Mise migration wrapper.
Live PostgreSQL and ClickHouse verification is separate from these automated
tests. mise run example:orders:check runs the example's Go tests without a live
database; it does not apply the PostgreSQL SQL in examples/orders-api.
To verify that example's actual migration, build the current Devctl binary and
put it on PATH, provide ORDERS_API_DB_PRIMARY_POSTGRES_MIGRATIONS_URL for an
isolated PostgreSQL database, and run mise run migrate:primary:postgres:up
from examples/orders-api. Check the resulting orders columns and constraints,
status, repeated up, down, and reapplication. The
getting started guide describes an API round
trip against the migrated schema. ClickHouse smoke verification likewise needs
an isolated live server and the selected target's migration URL; include
non-transactional failure and dirty-state behavior when changing its adapter.
Devctl uses github.com/devctllabs/go-libs/filesystem for rooted file
operations, go-libs/log for structured logging, and go-libs/di for command
scenario graphs. Atomic file publication, Git, process execution, and external
tool boundaries remain owned by Devctl. Completed Target or scaffold changes
are not rolled back after a later failure.