Thanks for your interest in improving tfctl! All contributions are welcome:
- Bug reports & fixes
- New features & enhancements
- Documentation & examples
- Refactors & performance improvements
- Feedback, ideas, and testing
- Fork the repo and clone your fork
- Create a branch:
git switch -c feature/short-descriptor - Make changes (see Style & Conventions below)
- Run build & basic smoke checks:
go build ./... - Open a Pull Request (PR) with a clear title & description
- Respond to review feedback
Requirements:
- Go (see the version badge in
README.md– use that or newer minor) - GNU Make (optional if you add helper targets later)
- Access to Terraform Cloud / Enterprise (for remote backend integration tests, optional)
Recommended tooling (optional but helpful):
golangci-lintfor static analysisgofumptorgo fmt(the repo follows standard formatting)git-cliffor conventional commit helpers for generating changelogs (future)
internal/
attrs/ Attribute parsing, transforms & list management
backend/ Backend resolution & implementations (cloud, remote, s3, local)
command/ CLI command builders & shared helpers
config/ Configuration loading and accessors
differ/ State diff helpers
driller/ JSON drilling / extraction support
meta/ Runtime metadata container
output/ Filtering, sorting, rendering (table, json, yaml)
state/ State loading & (optional) decryption
util/ Generic utilities (root dir parsing, etc.)
version/ Version metadata
cmd/ (if added later) Thin entrypoint(s) (currently top-level main.go)
- Follow standard Go idioms; prefer clarity over cleverness.
- Keep functions focused; extract helpers once duplication appears 3+ times.
- Avoid premature abstraction – let patterns stabilize first.
- Run
go fmt ./...(CI will fail if formatting diverges). - New comments: single space after periods; wrap at ≤ 80 cols when practical.
- Use American English spelling (e.g., “behavior”, “initialization”).
- All exported identifiers MUST have GoDoc.
- Package-level docs live in
doc.go(already present for internal packages). - Use
TODO,FIXME,NOTE,THINKprefixes deliberately:TODO: Concrete planned work.FIXME: Known bug needing correction.THINK: Open design question / speculative consideration.
- Remove stale THINK/TODO blocks when resolved.
- Wrap errors with context using
fmt.Errorf("context: %w", err). - Sentinel errors (
var ErrX = errors.New(...)) only when callers neederrors.Is/errors.As. - Do not log AND return an error unless it adds distinct value; prefer one or the other.
- Use
apex/logconsistently (already in project). - Debug logs should aid diagnosis without leaking secrets.
- Avoid debug spam inside hot loops unless guarded by coarse checks.
- New commands should reuse helpers in
internal/command/common.go. - Always support
--tldr(short usage examples) when adding a new query-like command. - Prefer composability over bespoke one-off flags when possible.
- Keep filtering semantics in
internal/output; avoid leaking parsing logic into commands. - If adding new filter operands, update:
- Parser regex
- Docs (
docs/filters.md) - Tests (add new cases)
- Avoid adding backend-specific conditionals in generic layers; extend backend interfaces instead.
- S3 / remote / cloud / local should converge on consistent method semantics (already mostly aligned).
Format (inspired by Conventional Commits, relaxed):
<type>(optional-scope): short summary
Longer body explaining intent, rationale, side effects.
Refs: #123 (optional)
Types (suggested):
- bug, chore, docs, feat, refactor, revert, test.
Examples:
feat(backend): add s3 version filtering
fix(output): correct case-insensitive contains operand
main(ormaster): always buildable; releases cut from it.- Feature branches:
feat/... - Fix branches:
bug/... - Docs-only:
docs/... - Avoid long-lived branches; rebase over merge when keeping a feature branch up-to-date.
Current test coverage is minimal (if present). You can help by adding tests.
Guidelines:
- Put table-driven tests alongside the code in
_test.gofiles. - Cover happy-path plus at least one edge case per function of interest.
- Avoid brittle tests tied to implementation details; test observable behavior.
- For backend-dependent logic, use small golden fixtures or mockable interfaces.
Suggested future test areas:
- Filter parsing & evaluation
- Attr transformation chaining
- Backend selection logic (
NewBackend) for matrix of root dir states - State version diff selection
- Only optimize after profiling (
pprof,benchstat). - Be cautious with large allocations in tight loops (e.g., filtering + transforms).
- Use streaming / iterative decoding only if a real-world dataset size justifies it.
When adding / changing functionality:
- Update
README.mdif user-facing behavior changes. - Add / adjust docs under
docs/(filters, flags, attrs, quickstart, etc.). - Add a TLDR example if a command gains a notable new pattern.
- Ensure version bump in
internal/version(if present) or tagging pipeline handles it. - Confirm changelog section (future automation TBD).
- Tag:
git tag -a vX.Y.Z -m "Release vX.Y.Z" && git push origin vX.Y.Z - CI / GoReleaser publishes artifacts & signatures.
- Manually verify signatures using
KEYSfile.
- Report sensitive security issues privately (email in README) before filing a public issue.
- Do NOT include secrets in logs, errors, or test fixtures.
- Validate user input (especially filter specs or dynamic paths) before usage.
Run through quickly:
- go build ./... succeeds
- Added / updated GoDoc for new exported symbols
- No lingering double-space sentences in new comments
- Flags / command wiring reuse
common.gohelpers - Added / updated docs & examples where applicable
- Any new filter operand documented & tested
- No debug leftovers or commented-out code blocks
Look for labels such as:
good first issuehelp wanteddocs
If something lacks context, ask before investing heavy effort.
- Use GitHub Issues for bugs / features.
- Use PR discussions for implementation-level feedback.
- Keep discussions technical and respectful.
Terraform, Terraform Enterprise, and HCP Terraform are trademarks of HashiCorp, Inc. OpenTofu is a trademark of The Linux Foundation.
If you don’t want to use a Makefile, you can enable a versioned Git pre-commit hook included in this repo that automatically regenerates man and TLDR pages from the canonical Markdown docs when you commit.
What it does on each commit:
- Builds the tiny generator at
tools/docgen. - Generates
docs/man/share/man1/*.1anddocs/tldr/*.mdfromdocs/commands/*.md. - Stages changed generated files so they’re included in the commit.
Enable it once per clone:
git config core.hooksPath .githooksDisable:
git config --unset core.hooksPathRun generator manually if needed:
go run tools/docgen/main.go -root .Your contributions help make infrastructure automation easier. Thank you for helping improve tfctl.