go install names binaries after the directory, so cmd/docs installed an ambiguous `docs` binary into $GOBIN that could clobber or be clobbered by other tools. Move it to cmd/corestack-docs, matching corestack-goose, and update goreleaser, CI, docs and usage text. Accepted ADRs keep their text and gain a dated rename note. BREAKING CHANGE: `go install go.auvem.com/corestack/cmd/docs@latest` stops resolving after the next tag; use cmd/corestack-docs. @v0.1.0 still installs the old `docs` binary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.6 KiB
corestack go
Shared Go building blocks. Includes corestack-docs, a checker for architecture decision records (ADRs) and implementation plans; page, Bob keyset pagination; and lifecycle, a service and worker coordinator.
migrate
migrate configures Goose providers for embedded SQL and Go
migrations, with structured logging and Postgres startup locking.
corestack-docs
Install:
go install go.auvem.com/corestack/cmd/corestack-docs@latest
Use, from a repository root:
corestack-docs new adr "Use Example Queue for background jobs" # creates docs/adr/<id>.md
corestack-docs new plan "Adopt Example Queue" # creates docs/plans/<id>.md
corestack-docs check [--root DIR] # prints path:line: message; exit 1 on problems
The format is specified in docs/docs-format.md; that document is the complete rule set. Exit status is 0 when every record is valid, 1 when problems are reported and 2 for usage errors.
page
page provides transport-neutral Bob keyset pagination with typed
items, mixed-direction sorts, opaque typed cursors, and a separate opt-in count.
Pass a trusted Sort and a typed row key in the same column order; sort columns
must be non-null and end in a unique column. See the runnable example
and cursor decision.
SQLite runs in-process in the normal test suite (requires CGO). PostgreSQL runs in
CI; locally set PAGE_POSTGRES_DSN to an isolated test database to run the same
flow. Set PAGE_REQUIRE_POSTGRES=1 to fail rather than skip when the DSN is absent.
MySQL mod composition compiles; its runtime behavior has not been verified.
lifecycle
go.auvem.com/corestack/lifecycle sets up modules in registration order, runs
services concurrently, and tears down successful setups in reverse order.
Construct an App with a required *slog.Logger, register Module callbacks,
and call Run(ctx) once. See the two-service example.
Launch background work with app.Go(ctx, name, fn) using the callback's lifecycle
context or a descendant, and handle admission errors. Run waits for every service
and admitted worker; raw goroutines remain your responsibility. First failure or
an injected signal cancels work before teardown. One shared shutdown deadline
(default 30 seconds) covers hooks and callback completion; a second signal
abandons shutdown. Callbacks must cooperate: abandonment cannot kill goroutines,
and the caller owns process exit and any unreleased resources.
During App-initiated shutdown, callback errors containing only the callback's
context cancellation are omitted. Mixed cancellation and independent failures
are retained intact to preserve wrapper types, identity and custom matching;
these errors may still match cancellation through errors.Is.
The caller owns signal subscription, SIGINT/SIGTERM filtering, a channel buffered for at least two signals, and subscription cleanup. Nil signals disable reception. There are no signal subscriptions, process exits, external dependencies or CLI integration in this package.
lifecycle/cli
go.auvem.com/corestack/lifecycle/cli adapts native urfave/cli/v3 commands.
Bind Serve(config, modules) to run selected services, or Action(config, modules, fn) for a one-off with selected setup/cleanup and module services suppressed.
See the executable serve/inspect example.
Run(ctx, cliRoot, args) accepts argv including the program name and returns the
exit code and inspectable error: success/help/graceful first signal is 0, usage is
2, and runtime/lifecycle failure is 1. Runtime failures dominate mixed errors.
Run prints diagnostics without exiting; the caller owns process exit. Nil signals
subscribe to SIGINT/SIGTERM during adapted actions; injected channels stay caller
owned. The private lifecycle App does not expose managed-worker admission.
Use fresh command trees and leave ExitErrHandler, OnUsageError and
CommandNotFound unset; Run owns those hooks. Other native hooks run outside the
adapted lifecycle action. Native environment/custom validation and generated-help
parse failures can return 1 with native diagnostics; custom pre-lifecycle
validators may return urfavecli.Exit(err, 2) for usage. Help and flags use native
urfave/cli declarations, without a configuration or environment facade.
Status
No support is guaranteed. Breaking changes, including to the format rules, may happen before 1.0 and are listed in the release notes.
License
BSD-3-Clause, see LICENSE.