Thanks for your interest in zd-cli. This project is small, so onboarding
is short. Please skim this document before opening a pull request.
git clone https://github.com/hackath0r/zd-cli.git
cd zd-cli
go mod download
make build
./zd versionYou will need:
- Go 1.22 or later (1.25+ recommended)
golangci-lintformake lintgoreleaseronly if you want to test the release pipeline locally
api/ vendored OpenAPI spec + codegen config
cmd/zd/ cobra commands; one file per resource group
internal/zenduty/ hand-written wrapper + generated typed client
internal/{config,output,errors,version}
shared CLI plumbing
internal/tools/ one-shot Go programs used by the Makefile
scripts/ install.sh, install.ps1
- Fork and create a branch from
main. - Make your change. Keep PRs focused; one feature or fix per PR.
- If you touched the OpenAPI spec, run
make openapi-pull && make generateso the generated client stays in sync. - Run the standard checks:
make lint make test make build - Commit using Conventional Commits.
Examples:
feat(incident): add --include-resolved,fix(retry): honour Retry-After when seconds is 0. The release notes are generated from commit messages, so a clean history matters. - Push and open a PR. The
ciworkflow runs lint, tests on linux/macOS/windows, and verifies the generated client is up to date.
- Find the right file under
cmd/zd/. If the command is for an existing resource group (incident, event, oncall, etc.), append to that file. New top-level groups get a new file plus a registration line incmd/zd/root.go. - Implement the command using the
callAPIgeneric helper for clean error/context handling. - Provide a
*output.TableSpecso--output tabledoes the right thing. Tables usetext/tabwriter. - Add a focused test (httptest server in
internal/zenduty/auth_test.goshows the pattern). Aim for a useful assertion, not coverage padding. - If your command shells out to a new endpoint, glance at the generated
code in
internal/zenduty/zenduty.gen.goto confirm the request body shape and JSON200 vs JSON201 wrapper. Some upstream endpoints declare list responses as single objects; usedecodeList[T]/decodeOne[T]to work around those.
Please open an issue with:
- The command you ran (redact your token)
- Expected vs actual behaviour
zd versionoutput- Output of
zd <command> --debugif relevant
Security vulnerabilities should go to SECURITY.md, not public issues.
gofmt+goimports(runmake fmt).- Errors propagate as
*internal/errors.ExitErrorso the exit code contract works. - Comments explain why, not what. Avoid restating the next line in a comment.
- Keep cobra command help readable; long descriptions belong in
Long:, one-liners inShort:.
Thanks again. Even a typo fix is a contribution.