Skip to content

Commit fa8d238

Browse files
committed
Add AGENTS.md with agent contribution guidelines
Document project conventions, branch/PR workflow, testing requirements, release process, and common pitfalls for AI coding agents working on this codebase. Codifies existing patterns observed from git history, CI configuration, and maintainer preferences.
1 parent c8eb402 commit fa8d238

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Agent Guidelines for tfutils/tfenv
2+
3+
Ground rules for AI coding agents contributing to this repository.
4+
5+
## Project Overview
6+
7+
tfenv is a Terraform version manager written in Bash, modelled after rbenv.
8+
~2.5k LOC across `bin/`, `lib/`, `libexec/`, `test/`, and `share/`.
9+
10+
- **Language:** Bash (no shellcheck — deliberate choice)
11+
- **Default branch:** `master`
12+
- **Last release:** v3.0.0 (July 2022) — there is a large unreleased backlog
13+
- **Maintainer:** Mike Peachey (Jaz)
14+
15+
## Repository Structure
16+
17+
```
18+
bin/ Entry points (terraform shim, tfenv command)
19+
lib/ Shared libraries sourced by multiple scripts
20+
libexec/ Subcommands (tfenv-install, tfenv-use, etc.)
21+
test/ Integration tests (download real Terraform binaries)
22+
share/ Static assets (HashiCorp PGP keys)
23+
.github/ CI workflows
24+
```
25+
26+
### Design Principle: Standalone Execution
27+
28+
Every `libexec/` script contains its own boilerplate for resolving
29+
`TFENV_ROOT` and sourcing helpers. This is **intentional** — each script
30+
must be executable in isolation for independent testing. Do not refactor
31+
this into a shared loader.
32+
33+
## Branch and PR Workflow
34+
35+
1. **Never commit directly to `master`.** Always use a feature branch.
36+
2. **Branch naming:** `fix/<short-description>` for bugs,
37+
`feat/<short-description>` for features, `chore/<short-description>`
38+
for maintenance. Reference the issue number where applicable
39+
(e.g. `fix/406-unbound-requested-variable`).
40+
3. **One logical change per branch/PR.** Do not bundle unrelated fixes.
41+
4. **PRs target `master`.** There is no develop or staging branch.
42+
5. **Merge strategy:** The repo uses merge commits (not squash).
43+
Do not force-push or rebase shared branches.
44+
45+
## Commit Messages
46+
47+
Freeform — no conventional commits standard is enforced. Be descriptive.
48+
Reference issue numbers where applicable (e.g. `Fix #406: ...`).
49+
50+
Historical examples:
51+
- `Fix realpath not available on macOS`
52+
- `Cope with different line endings in .terraform-version`
53+
- `Reduce duplication, and add safety`
54+
55+
## Testing
56+
57+
### What the tests are
58+
59+
Integration tests that **download and install real Terraform binaries**
60+
from HashiCorp. They are not fast, they are not unit tests, and they
61+
require network access.
62+
63+
### How to run tests
64+
65+
```bash
66+
# Install dependencies (macOS only — installs ggrep via Homebrew)
67+
./test/install_deps.sh
68+
69+
# Run all test suites
70+
./test/run.sh
71+
72+
# Run a specific test suite
73+
./test/run.sh test_install_and_use.sh
74+
```
75+
76+
### Test framework
77+
78+
- `test/test_common.sh` provides setup and helpers
79+
- `test/run.sh` discovers and runs all `test_*` files
80+
- Helper functions: `error_and_proceed` (log failure, continue),
81+
`check_active_version`, `check_installed_version`,
82+
`check_default_version`, `cleanup`
83+
- **Do not use `error_and_die`** — it does not exist in the test context
84+
85+
### Known issue: test runner always exits 0
86+
87+
`test/run.sh` ends with `exit 0` regardless of test failures. It logs
88+
failures but the exit code does not reflect them. This means CI may not
89+
catch test regressions. Be aware and check test output manually.
90+
91+
### CI matrix
92+
93+
| Trigger | Platforms |
94+
|---------|-----------|
95+
| Pull request | `macos-latest`, `ubuntu-latest` |
96+
| Push to master | `ubuntu-24.04`, `ubuntu-22.04`, `macos-14`, `macos-13`, `windows-2025`, `windows-2022` |
97+
98+
CI also builds the Dockerfile and validates it on Ubuntu runners.
99+
100+
## Before Submitting a PR
101+
102+
1. **Run the test suite locally** and verify all tests pass. Do not rely
103+
solely on CI — the exit code bug means CI may report green on failure.
104+
2. **Read the diff carefully.** Bash quoting and operator precedence bugs
105+
are the most common class of defect in this codebase.
106+
3. **Test on at least one platform.** If you only have Linux, note that
107+
in the PR. macOS and Windows have different `readlink`, `grep`, and
108+
`sed` behaviours.
109+
4. **Do not modify the test runner exit code bug** as a drive-by fix in
110+
an unrelated PR. It should be its own tracked change.
111+
112+
## Release Process
113+
114+
Releases are manual and infrequent. The historical process is:
115+
116+
1. Accumulate changes on `master`
117+
2. Update `CHANGELOG.md` with a new version section using the format:
118+
```
119+
## X.Y.Z (Month Day, Year)
120+
121+
* CATEGORY: Description (Contributor Name <email>)
122+
```
123+
Categories: `BREAKING CHANGE`, `NEW FEATURE`, `FIX`, `MAJOR THANKS`
124+
3. Create an annotated tag: `git tag -a vX.Y.Z -m "tfenv vX.Y.Z"`
125+
4. Push the tag: `git push origin vX.Y.Z`
126+
5. Update `Dockerfile` if it hardcodes the version
127+
128+
**Agents must not create releases or tags without explicit instruction
129+
from the maintainer.**
130+
131+
## Things Agents Must Not Do
132+
133+
- **Do not run `git push` to `master` or any remote branch** without
134+
explicit approval from Jaz.
135+
- **Do not create GitHub releases or tags.**
136+
- **Do not close or lock issues** — only the maintainer triages.
137+
- **Do not refactor the standalone boilerplate** in `libexec/` scripts.
138+
- **Do not add shellcheck** directives, configs, or CI steps.
139+
- **Do not add new dependencies** (external tools, packages) without
140+
discussion. The project deliberately has minimal dependencies
141+
(bash, curl, grep/ggrep, unzip).
142+
- **Do not modify `.github/workflows/`** without explicit approval —
143+
CI changes affect all platforms and have outsized blast radius.
144+
145+
## Common Pitfalls in This Codebase
146+
147+
These are the most frequent sources of bugs. Check for them in every change:
148+
149+
1. **Shell operator precedence:** `cmd1 || cmd2 | cmd3` means
150+
`cmd1 || (cmd2 | cmd3)`, not `(cmd1 || cmd2) | cmd3`.
151+
2. **Unquoted variables:** Always quote `"${var}"` in arguments,
152+
conditions, and assignments. Unquoted variables cause word-splitting.
153+
3. **Double-quoted traps:** `trap "rm ${var}" EXIT` expands at definition
154+
time and is vulnerable to word-splitting. Use functions or single quotes.
155+
4. **`$@` in for-loops:** Always quote: `for arg in "$@"`.
156+
5. **Regex anchoring:** `^1.1` matches `1.10.x` because `.` is a regex
157+
wildcard. Use `^1\.1\.` for exact prefix matching.
158+
6. **Cross-platform differences:** macOS uses BSD `sed`/`grep`/`readlink`.
159+
GNU extensions may not be available. The project installs `ggrep` on
160+
macOS but uses the system `sed` and `readlink`.
161+
7. **`set -uo pipefail`:** All scripts run with strict mode. Undefined
162+
variables cause immediate crashes. Use `${var:-default}` for optional
163+
variables.
164+
8. **Carriage returns:** `.terraform-version` files from Windows/WSL may
165+
contain `\r`. Always strip with `tr -d '\r'` after reading.

0 commit comments

Comments
 (0)