|
| 1 | +<!-- FOR AI AGENTS - Human readability is a side effect, not a goal --> |
| 2 | +<!-- Managed by agent: keep sections and order; edit content, not structure --> |
| 3 | +<!-- Last updated: 2026-03-21 --> |
| 4 | + |
| 5 | +# AGENTS.md |
| 6 | + |
| 7 | +**Precedence:** the **closest `AGENTS.md`** to the files you're changing wins. Root holds global defaults only. |
| 8 | + |
| 9 | +## Commands |
| 10 | +> Source: go.mod, .golangci.yaml, CLAUDE.md |
| 11 | +
|
| 12 | +| Task | Command | ~Time | |
| 13 | +|------|---------|-------| |
| 14 | +| Typecheck | `go build ./...` | ~10s | |
| 15 | +| Lint | `golangci-lint run` | ~15s | |
| 16 | +| Format | `gofumpt -w .` | ~2s | |
| 17 | +| Test (single) | `go test -v -race -run TestName ./package/...` | ~2s | |
| 18 | +| Test (all) | `go test -v -race ./...` | ~30s | |
| 19 | +| Build | `go build ./...` | ~10s | |
| 20 | +| Tidy deps | `go mod tidy` | ~5s | |
| 21 | + |
| 22 | +> If commands fail, verify against go.mod or ask user to update. |
| 23 | +
|
| 24 | +## Workflow |
| 25 | +1. **Before coding**: Read nearest `AGENTS.md` + check Golden Samples for the area you're touching |
| 26 | +2. **After each change**: Run the smallest relevant check (lint → typecheck → single test) |
| 27 | +3. **Before committing**: Run full test suite if changes affect >2 files or touch shared code |
| 28 | +4. **Before claiming done**: Run verification and **show output as evidence** — never say "try again" or "should work now" without proof |
| 29 | + |
| 30 | +## File Map |
| 31 | +``` |
| 32 | +. |
| 33 | +├── automation/ # Core interface: Automation + ServerArgs, ResourceResults |
| 34 | +│ └── automation.go |
| 35 | +├── cloud/ # Cloud provider implementations (each implements automation.Automation) |
| 36 | +│ ├── cloud.go # Provider name mapping + SSH key helper |
| 37 | +│ ├── akamai/ # Akamai Connected Cloud (Linode) |
| 38 | +│ ├── aws/ # Amazon Web Services |
| 39 | +│ ├── azure/ # Microsoft Azure |
| 40 | +│ ├── civo/ # Civo |
| 41 | +│ ├── do/ # DigitalOcean |
| 42 | +│ ├── exoscale/ # Exoscale |
| 43 | +│ ├── fuga/ # Fuga Cloud (OpenStack-based) |
| 44 | +│ ├── gce/ # Google Compute Engine |
| 45 | +│ ├── hetzner/ # Hetzner Cloud |
| 46 | +│ ├── multipass/ # Ubuntu Multipass (local) |
| 47 | +│ ├── oci/ # Oracle Cloud Infrastructure |
| 48 | +│ ├── openstack/ # Generic OpenStack |
| 49 | +│ ├── ovh/ # OVHcloud |
| 50 | +│ ├── scaleway/ # Scaleway |
| 51 | +│ ├── vexxhost/ # VEXXHOST (OpenStack-based) |
| 52 | +│ └── vultr/ # Vultr |
| 53 | +├── common/ # Shared utilities (StringPtr, server name helpers, color output) |
| 54 | +│ └── common.go |
| 55 | +├── model/ # Data models: MinecraftResource, server spec, SSH, Java settings |
| 56 | +│ └── model.go |
| 57 | +├── template/ # Go templates for cloud-init/bash provisioning (//go:embed) |
| 58 | +│ ├── template.go |
| 59 | +│ └── template_test.go |
| 60 | +├── update/ # Remote server ops via SSH (update, file transfer, commands) |
| 61 | +│ └── server.go |
| 62 | +├── .golangci.yaml # Linter config (tagliatelle, forbidigo, gosec, etc.) |
| 63 | +├── go.mod # Go 1.24.9 |
| 64 | +└── CONTRIBUTING.md # DCO sign-off required |
| 65 | +``` |
| 66 | + |
| 67 | +## Golden Samples (follow these patterns) |
| 68 | + |
| 69 | +| For | Reference | Key patterns | |
| 70 | +|-----|-----------|--------------| |
| 71 | +| Cloud provider | `cloud/hetzner/hetzner.go` | Implements `automation.Automation`, uses native SDK | |
| 72 | +| Test | `template/template_test.go` | Table-driven tests with golden files | |
| 73 | +| Interface | `automation/automation.go` | Central interface definition | |
| 74 | +| Model | `model/model.go` | Getter-based config model | |
| 75 | + |
| 76 | +## Utilities (check before creating new) |
| 77 | + |
| 78 | +| Need | Use | Location | |
| 79 | +|------|-----|----------| |
| 80 | +| Create server name with tags | `CreateServerNameWithTags` | `common/` | |
| 81 | +| Extract fields from server name | `ExtractFieldsFromServername` | `common/` | |
| 82 | +| Colored output | `Green` | `common/` | |
| 83 | +| String pointer | `StringPtr` | `common/` | |
| 84 | +| SSH public key from args | `GetSSHPublicKey` | `cloud/cloud.go` | |
| 85 | +| Provider name lookup | `GetCloudProviderFullName` / `GetCloudProviderCode` | `cloud/cloud.go` | |
| 86 | + |
| 87 | +## Heuristics (quick decisions) |
| 88 | + |
| 89 | +| When | Do | |
| 90 | +|------|-----| |
| 91 | +| Adding a cloud provider | Create dir under `cloud/`, implement `automation.Automation`, register in `cloud/cloud.go` + `model/model.go` | |
| 92 | +| JSON struct tags | Use `snake_case` (enforced by `tagliatelle` linter) | |
| 93 | +| YAML struct tags | Use `camelCase` (enforced by `tagliatelle` linter) | |
| 94 | +| Need `ioutil.*` | Use `os` / `io` equivalents (forbidden by `forbidigo`) | |
| 95 | +| Embedding files | Use `//go:embed` directive (see `template/`) | |
| 96 | +| SSH operations | Use `github.com/melbahja/goph` | |
| 97 | +| Template functions | Use `github.com/Masterminds/sprig/v3` | |
| 98 | +| Adding dependency | Ask first — we minimize deps | |
| 99 | +| Unsure about pattern | Check Golden Samples above | |
| 100 | + |
| 101 | +## Boundaries |
| 102 | + |
| 103 | +### Always Do |
| 104 | +- Sign-off commits with `git commit -s` (DCO compliance) |
| 105 | +- Run pre-commit checks before committing |
| 106 | +- Add tests for new code paths |
| 107 | +- Use conventional commit format: `type(scope): subject` |
| 108 | +- **Show test output as evidence before claiming work is complete** |
| 109 | +- Handle all errors (enforced by `errcheck`) |
| 110 | +- Use `gofumpt` formatting (not just `gofmt`) |
| 111 | + |
| 112 | +### Ask First |
| 113 | +- Adding new dependencies |
| 114 | +- Modifying CI/CD configuration |
| 115 | +- Changing the `automation.Automation` interface |
| 116 | +- Adding new cloud providers |
| 117 | +- Running full e2e test suites |
| 118 | +- Repo-wide refactoring or rewrites |
| 119 | + |
| 120 | +### Never Do |
| 121 | +- Commit secrets, credentials, or sensitive data |
| 122 | +- Use `ioutil.*` functions (use `os`/`io` instead) |
| 123 | +- Push directly to main/master branch |
| 124 | +- Skip error handling |
| 125 | +- Add `//nolint` without justification |
| 126 | +- Modify generated files |
| 127 | + |
| 128 | +## Module Boundaries |
| 129 | + |
| 130 | +> Cloud provider packages (`cloud/*`) must not import each other. Shared logic → `common/` or `cloud/cloud.go`. |
| 131 | +
|
| 132 | +## Terminology |
| 133 | + |
| 134 | +| Term | Means | |
| 135 | +|------|-------| |
| 136 | +| `Automation` | Interface all cloud providers implement | |
| 137 | +| `MinecraftResource` | Top-level config model for a Minecraft server | |
| 138 | +| `ServerArgs` | Arguments for provider operations | |
| 139 | +| `DCO` | Developer Certificate of Origin — requires `git commit -s` | |
| 140 | + |
| 141 | +## Index of scoped AGENTS.md |
| 142 | + |
| 143 | +No scoped files — this is a flat SDK. All conventions apply globally. |
| 144 | + |
| 145 | +## When instructions conflict |
| 146 | +The nearest `AGENTS.md` wins. Explicit user prompts override files. |
0 commit comments