Skip to content

Commit fead0fa

Browse files
authored
Merge branch 'main' into renovate/floci-floci
2 parents 89fc4e1 + b1124da commit fead0fa

173 files changed

Lines changed: 11535 additions & 350 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../agent-skills/skills/atmos-terraform-state-migrations

.claude/skills/field-test/SKILL.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
---
2+
name: field-test
3+
description: "Hands-on manual DX test pass of a feature or CLI command: read the real implementation and tests, hypothesize plausible user misunderstandings and misuse automated tests don't cover, build durable fixtures, execute for real against real state, and report ranked findings. Investigation only — never fixes anything found. Invoke on explicit requests like 'field test X' / 'do a DX test pass on X' / 'find vibe-coded slop in X'."
4+
argument-hint: "Feature or command to test, e.g. 'atmos vendor pull'"
5+
metadata:
6+
copyright: Copyright Cloud Posse, LLC 2026
7+
version: "1.0.0"
8+
---
9+
10+
# Field Test
11+
12+
Hands-on, adversarial test pass of **`$ARGUMENTS`** (the feature/command named when this skill
13+
was invoked, e.g. `atmos vendor pull`). If no target was given, ask which feature/command to test
14+
before starting.
15+
16+
Goal: catch "vibe-coded slop" — behavior that looks fine in code review but breaks or misleads a
17+
real user — not to re-run what automated tests already cover. Anticipate plausible user
18+
misunderstandings, not just obvious bugs.
19+
20+
**This pass is investigation only.** Do not fix anything you find — see Phase 5. Report and stop;
21+
the user decides what to fix (and when they do, that follow-up work should close with the
22+
`fix-log` skill, not this one).
23+
24+
## Phase 1 — Research before touching anything
25+
26+
The goal is a map of "documented or plausible usage" minus "already tested" = what needs manual
27+
verification. This phase is broad, read-only research — delegate it to `Agent subagent_type:
28+
"Explore"` (1-3 agents in parallel, one per bullet below) rather than doing it all serially inline.
29+
30+
- **Implementation** — the actual code, not just its docs or the skill describing it. Per this
31+
repo's conventions, business logic lives in narrow `pkg/` packages, not `internal/exec/` (being
32+
phased out) — check both `cmd/<command>/` (thin call site) and the `pkg/` package(s) it
33+
delegates to for the real logic and error paths.
34+
- **Docs and skills** — every relevant page under `website/docs/cli/commands/`, the matching
35+
`.claude/skills/atmos-*` skill(s) for the subsystem, and any README describing the feature. Note
36+
anything phrased with confidence you haven't independently confirmed against the code — docs and
37+
skills describe intended behavior, not necessarily current behavior.
38+
- **Existing automated tests** — unit tests colocated with the code, `tests/test-cases/` fixtures,
39+
`tests/testdata/` golden snapshots. For each, note exactly what it does and doesn't exercise
40+
(mocked vs. real execution, which flags/paths/backends are hit).
41+
- **Every flag, config option, and documented action/mode** — grep for them and list them. You
42+
will need to touch every one in Phase 4.
43+
44+
## Phase 2 — Generate hypotheses, don't just wander
45+
46+
Before running anything, write down concrete things to try, prioritized by what a real user would
47+
plausibly do:
48+
49+
- Every flag combination that seems natural but might not be validated (two flags that should be
50+
mutually exclusive; two config fields whose combination is never cross-checked).
51+
- Every place the docs/skill claim something you haven't verified against actual code.
52+
- Any "safe-looking" command (`plan`/`preview`/`--dry-run`/`list`/`describe`) that might secretly
53+
mutate state or trigger side effects, if built the same way as a mutating command — Atmos has
54+
many of these pairs (e.g. `terraform plan` vs `apply`, `vendor diff` vs `pull`), so this is a
55+
high-yield category here specifically.
56+
- Any action/mode described in docs but not exercised by ANY test or example in the repo — those
57+
are the highest-yield targets; if nothing has ever run it for real, assume it's broken until you
58+
prove otherwise.
59+
- Copy-paste/misconfiguration scenarios — what happens if a user copies a working stack/component
60+
block and changes one field but forgets a related one?
61+
- Error messages — accurate, do they name the actual flags/values involved, do they suggest a fix
62+
(per this repo's error-builder/hint conventions)?
63+
- Idempotency/rerun-safety — run the same operation twice; does the second run behave correctly?
64+
- Determinism — run the same read-only command several times with no state change between runs —
65+
is the output identical every time?
66+
67+
## Phase 3 — Build real, durable fixtures
68+
69+
- Prefer extending or copying an existing fixture (`tests/test-cases/`, `examples/`, `demo/`) over
70+
inventing one from scratch.
71+
- Build fixtures that exercise every documented capability, especially ones nothing in the repo
72+
currently exercises. Make them realistic, not minimal-to-the-point-of-artificial.
73+
- If real infrastructure/emulators are available for what you're testing, use them for at least one
74+
pass — this repo ships local AWS/GCP/Azure/Kubernetes/Vault/registry emulators for exactly this
75+
purpose (see the `atmos-emulator` skill). Don't rely solely on mocked/dry-run paths, since that's
76+
exactly what's already covered by automated tests.
77+
- Never manually edit golden snapshot files under `tests/test-cases/`, `tests/testdata/`, or
78+
`tests/snapshots/` — regenerate them via `-regenerate-snapshots` per CLAUDE.md's Golden Snapshots
79+
section.
80+
- Keep fixtures that have lasting value (they close real coverage gaps); don't create
81+
scratch-and-delete throwaways unless truly one-off.
82+
83+
## Phase 4 — Execute for real, with discipline
84+
85+
- Run actual commands against a disposable fixture or emulator by default. Before any command that
86+
can mutate state, obtain explicit user confirmation. Run against shared or production state only
87+
with a documented backup and rollback plan. Don't reason abstractly about what "should" happen —
88+
observe what does happen. Build a fresh binary first (`atmos build`) if the change under test
89+
isn't already reflected in `./build/atmos`.
90+
- Never pipe redirection into a command under test — per CLAUDE.md, piping breaks TTY detection,
91+
which can mask exactly the DX issues (interactive prompts, color, spinners) you're testing for.
92+
- **Before every test, verify you're actually starting from a clean/expected state — don't
93+
assume.** Stale state from a previous run (yours or a prior session's) will silently corrupt your
94+
results. Reset explicitly and confirm the reset worked (check a resource count/id changed, not
95+
just that a command exited 0).
96+
- When something surprises you, reduce it to the smallest reproducible case and verify the repro
97+
twice.
98+
- If Phase 1 research made a claim, verify it live before trusting it — code-reading can miss
99+
control flow (e.g. assuming a flag is silently ignored when it actually errors, or vice versa).
100+
Correct the record explicitly when research turns out wrong.
101+
- Test the happy path too, not just edge cases — confirm what's supposed to work actually does, so
102+
the report distinguishes real regressions from things that were never broken.
103+
104+
## Phase 5 — Report
105+
106+
For every finding: exact repro command(s), expected vs. actual output, and severity (silent data
107+
loss/mutation > crash on reasonable input > confusing error message > cosmetic). Rank the report by
108+
severity, most dangerous first. Explicitly call out anything verified as working correctly too — a
109+
report that's only bad news is as misleading as one that's only good news.
110+
111+
Keep a running scratch log of findings as you go (in your own working notes/task list) rather than
112+
reconstructing everything at the end from memory — but don't commit that log. Per CLAUDE.md's Git
113+
section, scratch/research files never get committed; only the fixtures built in Phase 3 (if kept
114+
for lasting value) and this final report are durable output.
115+
116+
Do not fix anything found — this pass is investigation only. Stop and report; the user decides what
117+
to fix. End by invoking the `say` skill — a completed test pass reaching a stopping point a human
118+
should review is exactly its trigger.
119+
120+
## Related
121+
122+
- **`Explore` agent** — Phase 1's broad read-only research.
123+
- **`atmos-emulator` skill** — real local infra for Phase 3/4 when the target touches
124+
AWS/GCP/Azure/Kubernetes.
125+
- **`docs` skill** — conventions for the CLI docs being cross-checked in Phase 1.
126+
- **`fix-log` skill** — for the user's follow-up once they decide what to fix; out of scope here.
127+
- **`say` skill** — end-of-pass notification.

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ jobs:
547547
FLOCI_GCP_ENDPOINT: "http://localhost:4588"
548548
FLOCI_AZURE_ENDPOINT: "http://localhost:4577"
549549
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
550-
run: go test ./tests -run 'Test((AWS(StoreHooks|Secrets)|GCPSecrets|AzureSecrets)FlociE2E|LocalGitOpsPushE2E|Scaffold(AWSLandingZone|GCPLandingZone|AzureLandingZone|AWSApp)FlociE2E|InitFromTemplateRepoGiteaE2E)' -count=1 -timeout 25m -v
550+
run: go test ./tests -run 'Test((AWS(StoreHooks|Secrets)|GCPSecrets|AzureSecrets)FlociE2E|LocalGitOpsPushE2E|Scaffold(AWSLandingZone|GCPLandingZone|AzureLandingZone|AWSApp)FlociE2E|InitFromTemplateRepoGiteaE2E|TerraformFlociTfmigrateS3History)' -count=1 -timeout 25m -v
551551

552552
# run k3s demo tests
553553
k3s:

agent-skills/AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ When a task involves Atmos, activate the matching skill for detailed guidance.
104104
| Emulator components: AWS/GCP/Azure/Kubernetes/Vault/OpenBao/registry local emulators | `atmos-emulator` | `agent-skills/skills/atmos-emulator/SKILL.md` |
105105
| Compositions: named service groupings and `atmos composition validate` | `atmos-compositions` | `agent-skills/skills/atmos-compositions/SKILL.md` |
106106
| terraform plan/apply/deploy/destroy, workspace management, backend config, varfile generation | `atmos-terraform` | `agent-skills/skills/atmos-terraform/SKILL.md` |
107+
| Terraform state migrations with tfmigrate, migration HCL, migrate CLI, hooks, history mode, rerun safety | `atmos-terraform-state-migrations` | `agent-skills/skills/atmos-terraform-state-migrations/SKILL.md` |
107108
| Terraform/OpenTofu linting: `atmos terraform lint`, TFLint configuration and rules, component toolchain pins, lifecycle hooks, SARIF CI findings | `atmos-lint` | `agent-skills/skills/atmos-lint/SKILL.md` |
108109
| helmfile sync/apply/destroy/diff, Kubernetes deployments, EKS integration, varfile generation | `atmos-helmfile` | `agent-skills/skills/atmos-helmfile/SKILL.md` |
109110
| Native Helm (experimental): Helm Go SDK template/diff/apply/delete, chart sources, values, repositories, provision targets | `atmos-helm` | `agent-skills/skills/atmos-helm/SKILL.md` |
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
name: atmos-terraform-state-migrations
3+
description: "Terraform state migration workflow with tfmigrate in Atmos: writing migration HCL, running atmos terraform migrate plan/apply/list, wiring kind: tfmigrate hooks, configuring history mode, and handling state refactors, rerun safety, workspace context, backend history variables, and CI-safe migrations."
4+
metadata:
5+
copyright: Copyright Cloud Posse, LLC 2026
6+
version: "1.0.0"
7+
references:
8+
- references/tfmigrate-migration-patterns.md
9+
---
10+
11+
# Atmos Terraform State Migrations
12+
13+
Use this skill when creating or reviewing Terraform state migrations for Atmos components. Atmos delegates state
14+
migrations to `tfmigrate`. It runs `tfmigrate` in the same component context as `atmos terraform plan` and `apply`.
15+
Before `tfmigrate` runs, Atmos performs auth identity setup, source and workdir provisioning, backend and varfile
16+
generation, Terraform init, workspace selection, toolchain resolution, and `TFMIGRATE_EXEC_PATH` setup.
17+
18+
For migration HCL syntax and examples, load
19+
[references/tfmigrate-migration-patterns.md](references/tfmigrate-migration-patterns.md).
20+
21+
## Start With Resolved Context
22+
23+
Never guess stack names, component names, workspaces, backend paths, or state addresses.
24+
25+
```bash
26+
atmos describe component <component> -s <stack>
27+
atmos terraform migrate list <component> -s <stack>
28+
atmos terraform state list <component> -s <stack>
29+
```
30+
31+
Use the resolved component output to confirm:
32+
33+
- the final Terraform component and component path
34+
- Terraform workspace name
35+
- backend type and backend settings
36+
- whether a `kind: tfmigrate` hook already exists
37+
- history key and history bucket from `atmos terraform migrate list`
38+
39+
Use `atmos terraform state show <component> -s <stack> <address>` when resource identity or import IDs are unclear.
40+
If a refactor can be handled with Terraform `moved` blocks and stays in the same state, prefer that unless the user
41+
specifically needs `tfmigrate` automation or multi-state moves.
42+
43+
## One-Off CLI Workflow
44+
45+
Create a migration file in a project-owned migrations directory, then preview it before applying. `tfmigrate`
46+
resolves `--migration` relative to the `migration_dir` in its config. The Atmos-generated default config points
47+
`migration_dir` at the component's `migrations/` directory when one exists. Pass just the filename, not a
48+
`migrations/`-prefixed path.
49+
50+
```bash
51+
atmos terraform migrate plan <component> -s <stack> --migration 20260527090000_refactor_vpc.hcl
52+
atmos terraform migrate apply <component> -s <stack> --migration 20260527090000_refactor_vpc.hcl
53+
```
54+
55+
For multiple selected component instances:
56+
57+
```bash
58+
atmos terraform migrate plan --components vpc,eks -s <stack> --migration 20260527090000_refactor.hcl
59+
atmos terraform migrate plan --query '.settings.requires_migration == true' --tfmigrate-config .tfmigrate.hcl
60+
atmos terraform migrate plan --affected --migration 20260527090000_refactor.hcl
61+
```
62+
63+
Do not run `apply` until `plan` succeeds and the Terraform plan after migration does not show unintended destroy/create
64+
changes. `--affected` does not support `--include-dependents` for migrate.
65+
66+
## Migration Files
67+
68+
Use `tfmigrate` HCL for state operations that need reviewable, repeatable files. A migration file contains exactly one
69+
`migration` block.
70+
71+
```hcl
72+
migration "state" "rename_subnet" {
73+
actions = [
74+
"mv aws_subnet.private aws_subnet.private_primary",
75+
]
76+
}
77+
```
78+
79+
Common actions:
80+
81+
- `mv <source> <destination>` for renames and module/address moves in one state.
82+
- `rm <addresses>...` for removing state bindings without destroying infrastructure.
83+
- `import <address> <id>` for binding existing infrastructure.
84+
- `replace-provider <from> <to>` for provider address migrations.
85+
- `xmv <source-pattern> <destination-pattern>` for wildcard moves.
86+
- `migration "multi_state"` for moving resources between component directories or state files.
87+
88+
Keep migration filenames sortable, usually with a timestamp prefix. In history mode, unapplied migrations are processed
89+
in filename order.
90+
91+
## Hook Wiring
92+
93+
Use hooks when the migration should run as part of normal `plan`, `apply`, or `deploy` workflows.
94+
95+
```yaml
96+
components:
97+
terraform:
98+
s3-bucket:
99+
dependencies:
100+
tools:
101+
tfmigrate: "0.4.x"
102+
103+
hooks:
104+
state-migration:
105+
events:
106+
- before.terraform.plan
107+
- before.terraform.apply
108+
kind: tfmigrate
109+
migration: 20260527090000_remove_template_provider.hcl
110+
mode: dynamic
111+
```
112+
113+
`mode: dynamic` is the default. `before.terraform.plan` runs `tfmigrate plan`. `before.terraform.apply` and
114+
`before.terraform.deploy` run `tfmigrate apply`. Use `mode: plan` or `mode: apply` only when the hook must always run
115+
one action.
116+
117+
Hook fields:
118+
119+
- `migration`: path to one migration file.
120+
- `config`: path to `.tfmigrate.hcl`; omit `migration` when using history mode.
121+
- `backend_config`: entries passed as repeated `tfmigrate --backend-config` flags for the Terraform state backend.
122+
- `mode`: `dynamic`, `plan`, or `apply`.
123+
124+
## History Mode
125+
126+
Single-file `tfmigrate apply path.hcl` is not idempotent. A rerun can fail if a source address already moved, or an
127+
address was already removed. For CI-safe reruns, use `tfmigrate` history mode with durable storage.
128+
129+
```yaml
130+
hooks:
131+
state-migration:
132+
events:
133+
- before.terraform.plan
134+
- before.terraform.apply
135+
kind: tfmigrate
136+
config: .tfmigrate.hcl
137+
mode: dynamic
138+
```
139+
140+
Atmos exposes helper variables for `.tfmigrate.hcl`:
141+
142+
```hcl
143+
tfmigrate {
144+
migration_dir = "./tfmigrate"
145+
146+
history {
147+
storage "s3" {
148+
bucket = env.ATMOS_TFMIGRATE_HISTORY_BUCKET
149+
key = env.ATMOS_TFMIGRATE_HISTORY_KEY
150+
region = env.ATMOS_TFMIGRATE_HISTORY_REGION
151+
role_arn = env.ATMOS_TFMIGRATE_HISTORY_ROLE_ARN
152+
}
153+
}
154+
}
155+
```
156+
157+
The default history key is `tfmigrate/<stack>/<component>/<workspace>/history.json`. Atmos passes history settings to
158+
`tfmigrate`, but does not persist or repair history itself. Configure durable S3, GCS, or CI-persisted local storage.
159+
160+
## Safety Checklist
161+
162+
Before committing migration work:
163+
164+
1. Confirm the migration addresses come from `atmos terraform state list`, not from code names alone.
165+
2. Confirm the migration file targets the resolved component working directory and workspace.
166+
3. Run `atmos terraform migrate plan` and inspect the post-migration Terraform plan.
167+
4. Use history mode for hooks or CI workflows that may rerun.
168+
5. Keep migration files and hook wiring in the same PR as the Terraform refactor they support.
169+
6. Remove or disable one-shot hook wiring after the migration has safely run everywhere it is intended to run.

0 commit comments

Comments
 (0)