Developer guide — knife
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Go | 1.26+ | Build and test |
| make | any | Task runner |
| golangci-lint | latest | Linting |
| goreleaser | latest | Release builds |
Install golangci-lint:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Install goreleaser:
go install github.com/goreleaser/goreleaser/v2@latest
Clone and build
git clone https://gitlab.com/cozybadgerde/applications/knife.git
cd knife
make build
The binary is written to build/knife. Run it directly:
./build/knife --help
Running tests
All tests use net/http/httptest and do not require a running snackbox server.
make test
Do not call go test directly — always use make test so that any future pre-test steps defined in the Makefile are included.
Linting
make lint
This runs golangci-lint run ./.... Fix all reported issues before opening a merge request. Code must also pass gofmt formatting.
Regenerating the API client
The generated client in internal/client/snackbox.gen.go is produced from api/openapi.yaml. After updating the OpenAPI spec:
make generate
Do not edit snackbox.gen.go manually. Any manual changes will be lost the next time make generate is run.
Creating a release
Snapshot (local testing)
make dist
This runs goreleaser release --snapshot --clean and places binaries in dist/. A snapshot build does not require a git tag.
Tagged release
- Create and push a semver tag:
bash git tag v1.2.3 git push origin v1.2.3
- The CI pipeline picks up the tag and runs goreleaser to publish the release to GitLab. The
.goreleaser.yamlfile in the repo root controls what is built and uploaded.
Commit message format
knife follows the Conventional Commits specification. A template is provided in .gitmessage:
type(scope): short description
Body (optional): explain the why, not the what.
Footer (optional): BREAKING CHANGE: ..., Closes #issue
Common types: feat, fix, refactor, test, docs, chore, ci.
Configure git to use the template:
git config commit.template .gitmessage
Adding a new command
- Create the command file in
cmd/. Use an existing file such ascmd/me.goas a reference.
bash touch cmd/widgets.go
-
Define the command struct and subcommands using
cobra.Command. -
Register the commands in the file's
init()function:
go func init() { rootCmd.AddCommand(widgetsCmd) widgetsCmd.AddCommand(widgetsListCmd, widgetsGetCmd) // register flags here }
- Write the test file alongside the command file:
bash touch cmd/widgets_test.go
Tests must cover every exported function and every RunE handler. Use net/http/httptest to mock the snackbox API — no live server should be required.
- Run tests and lint to verify:
bash make test make lint
- Open a merge request following the commit message conventions above.