|
| 1 | +# AGENTS.md — cnctl CLI |
| 2 | + |
| 3 | +Instructions for AI coding agents working on the `cnctl` CLI. |
| 4 | + |
| 5 | +## Project |
| 6 | + |
| 7 | +Rust CLI (`cnctl`) for managing Cloud Native Days Norway conferences. |
| 8 | +Standalone Cargo project inside `cli/` of the main website monorepo. |
| 9 | + |
| 10 | +## Build & Test |
| 11 | + |
| 12 | +```sh |
| 13 | +mise run check # clippy + fmt-check + test (parallel) |
| 14 | +mise run clippy # pedantic lints, warnings as errors |
| 15 | +mise run fmt # format with rustfmt |
| 16 | +mise run test # all tests (unit + E2E) |
| 17 | +cargo test # alternative without mise |
| 18 | +``` |
| 19 | + |
| 20 | +## Architecture |
| 21 | + |
| 22 | +- **Commands** live in `src/commands/<domain>/` as multi-file modules (`mod.rs`, `args.rs`, `interactive.rs`, etc.) |
| 23 | +- **Types** live in `src/types/` — one file per API domain, re-exported from `mod.rs` |
| 24 | +- **Client** (`src/client.rs`) — tRPC HTTP client, all API calls go through here |
| 25 | +- **Display** (`src/display/`) — terminal rendering, table formatting, colors |
| 26 | +- **Template** (`src/template.rs`) — `{{{VAR}}}` substitution engine |
| 27 | +- Keep commands thin: API calls in `mod.rs`, display logic in `display/`, business logic in domain modules |
| 28 | + |
| 29 | +## Coding Conventions |
| 30 | + |
| 31 | +- Clippy pedantic enabled — no warnings allowed |
| 32 | +- Serde: `#[serde(rename_all = "camelCase")]`, `#[serde(rename = "_id")]`, `#[serde(default)]` |
| 33 | +- Unknown enum variants: `#[serde(other)] Unknown` with custom `Deserialize` + `Default` impls |
| 34 | +- Error handling: return `anyhow::Result<T>`, avoid `unwrap()` / `process::exit()` |
| 35 | +- Tests: unit tests in `#[cfg(test)]` modules, E2E tests in `tests/e2e.rs` using wiremock |
| 36 | + |
| 37 | +## Commit Messages & Release Notes |
| 38 | + |
| 39 | +Release notes are **auto-generated** from commit messages using [git-cliff](https://git-cliff.org/) (configured in `cliff.toml`). |
| 40 | + |
| 41 | +**All commits must use [Conventional Commits](https://www.conventionalcommits.org/) format:** |
| 42 | + |
| 43 | +- `feat:` / `feat(scope):` — new features (included in release notes) |
| 44 | +- `fix:` — bug fixes (included) |
| 45 | +- `perf:` — performance improvements (included) |
| 46 | +- `refactor:` — code refactoring (included) |
| 47 | +- `docs:` — documentation changes (included) |
| 48 | +- `chore:`, `style:`, `ci:`, `test:`, `build(deps):` — excluded from release notes |
| 49 | + |
| 50 | +Examples: |
| 51 | +``` |
| 52 | +feat(sponsors): add email functionality with template support |
| 53 | +fix: handle missing conference ID in sponsor lookup |
| 54 | +refactor: extract shared email builder into helper module |
| 55 | +``` |
| 56 | + |
| 57 | +## Releases |
| 58 | + |
| 59 | +Releases are fully automated via GitHub Actions: |
| 60 | + |
| 61 | +1. Push to `main` triggers CI (`ci.yml`: clippy, fmt, test on Linux/macOS/Windows) |
| 62 | +2. On CI success, release workflow (`release.yml`) cross-compiles for 5 targets |
| 63 | +3. git-cliff generates release notes from commits since the last tag |
| 64 | +4. A GitHub Release is created with binaries, checksums, and build provenance attestations |
| 65 | + |
| 66 | +Tags use date-based versioning: `YYYY.MM.DD-<shortsha>`. Do **not** create tags manually — the release workflow handles this. |
0 commit comments