feat(cloudformation): migration guide, inline templates, and field-test fixes [EXPERIMENTAL] - #3002
Draft
Erik Osterman (Cloud Posse) (osterman) wants to merge 18 commits into
Conversation
Contributor
|
Tip Atmos Pro
No affected stacks workflow was detected for this pull request. |
Erik Osterman (Cloud Posse) (osterman)
force-pushed
the
osterman/cfn-phase4-migration-graduation
branch
from
August 27, 2026 11:39
5542812 to
1c5a72c
Compare
Erik Osterman (Cloud Posse) (osterman)
had a problem deploying
to
screengrabs
August 27, 2026 11:39 — with
GitHub Actions
Failure
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
Erik Osterman (Cloud Posse) (osterman)
force-pushed
the
osterman/cfn-phase4-migration-graduation
branch
from
August 27, 2026 11:44
1c5a72c to
03e1964
Compare
Erik Osterman (Cloud Posse) (osterman)
had a problem deploying
to
screengrabs
August 27, 2026 11:45 — with
GitHub Actions
Failure
Resource Changes Found for
|
Erik Osterman (Cloud Posse) (osterman)
force-pushed
the
osterman/cfn-phase4-migration-graduation
branch
from
August 27, 2026 15:43
3ab568d to
39f7b60
Compare
Erik Osterman (Cloud Posse) (osterman)
had a problem deploying
to
screengrabs
August 27, 2026 15:43 — with
GitHub Actions
Failure
Erik Osterman (Cloud Posse) (osterman)
had a problem deploying
to
screengrabs
August 27, 2026 15:43 — with
GitHub Actions
Failure
Erik Osterman (Cloud Posse) (osterman)
force-pushed
the
osterman/cfn-phase4-migration-graduation
branch
from
August 27, 2026 16:00
39f7b60 to
1e61d70
Compare
Erik Osterman (Cloud Posse) (osterman)
had a problem deploying
to
screengrabs
August 27, 2026 16:00 — with
GitHub Actions
Failure
Erik Osterman (Cloud Posse) (osterman)
had a problem deploying
to
screengrabs
August 27, 2026 16:00 — with
GitHub Actions
Failure
Erik Osterman (Cloud Posse) (osterman)
force-pushed
the
osterman/cfn-phase4-migration-graduation
branch
from
September 2, 2026 21:33
f78b640 to
49827bf
Compare
Erik Osterman (Cloud Posse) (osterman)
temporarily deployed
to
screengrabs
September 2, 2026 21:33 — with
GitHub Actions
Inactive
Erik Osterman (Cloud Posse) (osterman)
force-pushed
the
osterman/cfn-phase4-migration-graduation
branch
from
September 2, 2026 22:32
49827bf to
7a29b3d
Compare
Erik Osterman (Cloud Posse) (osterman)
temporarily deployed
to
screengrabs
September 2, 2026 22:32 — with
GitHub Actions
Inactive
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## osterman/cfn-phase3-stacksets-observability #3002 +/- ##
===============================================================================
+ Coverage 83.61% 83.65% +0.03%
===============================================================================
Files 1975 1984 +9
Lines 192295 193027 +732
===============================================================================
+ Hits 160797 161471 +674
- Misses 23489 23511 +22
- Partials 8009 8045 +36
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Closes a real Phase 1 PRD gap surfaced by a completeness audit: the artifact
bucket used by template packaging (kind: aws/s3 provision targets) had no
CLI-managed lifecycle, unlike Terraform's equivalent atmos terraform backend
verb-for-verb clone this PRD explicitly called for.
pkg/provisioner/backend's ProvisionBackend/DeleteBackendWithParams read
Terraform's own top-level backend_type/backend stack-manifest shape, not
CFN's provision.targets.<name>: {kind: aws/s3, ...} shape. Rather than
teaching the shared provisioner layer a second config shape (which would
break the PRD's explicit "no new backend type" promise), the new
pkg/component/aws/cloudformation/backend.go adapts entirely on the CFN side:
resolves the kind: aws/s3 target (implicit-single-or---target, same pattern
already used for stackset/packaging targets) and builds a synthetic
backend_type/backend map before handing off to the existing, real
ProvisionBackend/DeleteBackendWithParams code path — spinner and warning
handling included, unmodified.
ListBackends/DescribeBackend in the shared provisioner layer are themselves
unconditional ErrNotImplemented stubs today, even for Terraform. CFN's need
is narrower (one kind: aws/s3 target per component, not Terraform's full
backend-type matrix), so describe/list are real implementations here via a
direct S3BackendExists call rather than mirroring the stub.
Verified live against Floci: create/describe/list/update/delete all
exercised end-to-end against a real S3 bucket (confirmed independently via
raw `aws s3` calls), including delete's --force gate.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the PRD's deferred Migration Guide scope. Framed as "migrating off Rain onto Atmos," not "how to write Rain syntax in Atmos" — there is no Rain compatibility layer, so the guide leads with resolving !Rain:: directives (Constant/Env/Include/Embed/S3/Module) to their Atmos-native or plain-CloudFormation equivalents before a template will deploy at all, plus a verb cross-reference table (every right-hand-side Atmos verb checked directly against cmd/aws/cloudformation/cloudformation.go's mounted commands, none invented). Two new artifacts, both linked from the agent-skills routing table and the website's Migration Guides sidebar: the agent-facing skill reference (agent-skills/skills/atmos-migration/references/from-rain.md) and the user-facing Crawl/Walk/Run guide (website/docs/migration/from-rain.mdx). Corrects an assumption from earlier in the PRD: template packaging (kind: aws/s3 provision targets) is size-triggered only — it uploads a template past CloudFormation's 51,200-byte inline limit, but does not rewrite local asset references the way `aws cloudformation package`/Rain's `pkg` do. The guide states this explicitly rather than implying full asset-aware parity. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Continuation lines under numbered-list items used 3-space indentation (aligned to the "1. " marker width), violating .editorconfig's indent_size=2 for *.md — caught by the atmos-validate-editorconfig pre-commit hook, which scans the whole tree rather than the diff, on an unrelated later commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes a gap flagged in the example: no recorded demo, unlike its sibling examples/emulator-aws. Mirrors emulator-aws's cast pipeline exactly (fixture setup, recording, sanitize/validate scripts), showing the deploy/output/ delete lifecycle against a real Floci emulator. Noted for later: pkg/component/aws/cloudformation's DescribeStackEvents poll loop occasionally races a fast-completing create against Floci (events not yet visible when the stack already reports CREATE_COMPLETE) — the deploy still succeeds correctly, but recording needed a retry roughly 1-in-4 to 1-in-5 attempts to capture the full event stream. Not a functional bug (the same race the delete-path fix earlier in this stack already handles for DescribeStackEvents' own not-found case), but worth keeping in mind if an automated Floci E2E test is ever written — it may need the same retry tolerance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ooks/S3-auth fixes Fixes the full set of findings from this session's field-test pass on aws/cloudformation (bulk-selection infinite recursion shared by every bulk-capable component type, logs stdout routing, error-sentinel misuse, missing confirmation gates, diff/changeset leaks, real backend auto-provisioning, small doc drift), adds CFN inline-template support (`template:` as inline body, new `path:` for file references, plumbed through two component-config allowlists that were silently dropping the new key), and fixes a missing EndpointURL override in the shared pkg/ci/artifact/s3 store that broke template uploads against emulated AWS endpoints. Live-verified hooks fire only for diff/apply/delete, matching the code. Each change is documented in its own docs/fixes/ entry. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e-templates fix-log atmos-validate-editorconfig requires indentation in multiples of 2; the numbered-list continuation lines used 3-space indentation (aligned to "1. "/"2. "'s width) instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ainer/workflow/terraform/vendor/list
--labels was WithStringFlag (comma-separated only) while --tags was already WithStringSliceFlag
(repeatable and/or comma-separated) — an inconsistency found while fixing the same issue for
aws/cloudformation. The flag is independently duplicated (not shared) across cloudformation,
kubernetes, helm, container, workflow, terraform, vendor (x4), and list (x6) commands, so this
converts every one of them to match --tags' registration and parsing.
pkg/tags.ParseLabelsFlag now takes []string instead of string; every call site converts from
GetString("labels") to GetStringSlice("labels"), and every flag registration from
WithStringFlag("labels", ...) to WithStringSliceFlag("labels", ...). Docs updated to show the
repeatable form.
See docs/fixes/2026-08-25-labels-flag-repeatable.md for the full file list and validation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the changelog post covering the whole feature (all 4 phases plus this session's field-test fixes, inline templates, and migration guide), and links it into the extensibility initiative's roadmap milestone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…plate golangci-lint's add-constant rule flagged a 4th literal "%w: %w" after the gh-stack rebase merged phase1's wrapFmt-introducing commit ahead of this one; swap in the existing package-level constant instead of a duplicate literal. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uild failure The docs build's cast-validation step failed because every aws/cloudformation doc page beyond Phase 1's 8 verbs (backend, changeset, drift, fmt, get, list, logs, source, stackset, tree, watch) referenced a screengrab cast that was never recorded — demo/casts/atmos.d/screengrabs/cli.yaml's command manifest still only listed Phase 1's verbs. Added the missing 32 commands to both the generate and validate command lists and recorded all 41 aws/cloudformation casts via `atmos --chdir=demo/casts casts generate screengrabs cli --filter=cloudformation`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… stacks followLogs wrote each stack's newly-fetched events immediately after polling it, per poll iteration — printing events in poll order rather than event-time order whenever an earlier-polled stack's events were actually newer than a later-polled stack's. Now collects the iteration's events across every stack, sorts by timestamp, then writes, matching the non-follow path's existing sort. Also tightened the aws/cloudformation JSON schema: 'template'/'path' now reject empty values, and the object schema enforces they're mutually exclusive (previously only checked in Go's validateComponentConfig, so an IDE/editor validating against the schema wouldn't catch either mistake). Found via CodeRabbit review. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ws " from every usage line
cmd/aws/cloudformation/cloudformation.go's init() called both
awsCmd.AddCommand(CloudFormationCmd) (correct, in cmd/aws/aws.go) AND its own
internal.Register(&CommandProvider{}), which re-parents CloudFormationCmd
directly onto RootCmd via the top-level command registry. Cobra's AddCommand
mutates the child's parent pointer in place, so whichever call ran last won
— the registry-based one, since it runs from cmd/root.go's init() after every
imported package's own init() has already run. Two live, confirmed effects:
- Every `atmos aws cloudformation ...` --help usage line rendered
"atmos cloudformation ..." (via cmd.CommandPath()/UseLine()), missing "aws".
- `atmos cloudformation ...` (without the aws namespace) worked as an
undocumented, unintended duplicate top-level command, alongside the real
`atmos aws cloudformation ...` path.
No other `aws/<service>` subcommand (eks, security, compliance, ecr) does
this self-registration — cloudformation was the only one. Removed the rogue
internal.Register call and the now-dead CommandProvider type; it was never
needed since aws.go already wires the command in correctly.
Regenerated all 41 aws/cloudformation screengrab casts to reflect the
corrected usage lines (`atmos --chdir=demo/casts casts generate screengrabs
cli --filter=cloudformation`), which also incidentally resolved the
`changeset delete --help` cast advertising a --retain-resources flag it
doesn't have (that cast was stale, predating other fixes).
Also: documented that `backend update` creates the bucket first when it
doesn't exist yet, matching `backend create`'s shared code path (the doc
previously only described it as an existing-bucket update); and updated the
backend auto-provisioning fix-log's stale Follow-ups section — the S3
identity/EndpointURL bug it flagged as unresolved was fixed the same day in
2026-08-25-artifact-s3-store-endpoint-override.md.
Found via CodeRabbit review (phase4 --dir website/--dir docs passes). --dir
internal came back clean (0 findings). The Rain --config Parameters-map
wrapping finding on from-rain.mdx and the source.uri single-file
template-inference finding on aws-cloudformation.mdx were not fixed: the
former needs verifying Rain's actual external config-file format (can't
confirm from this repo alone), and the latter's claimed behavior doesn't
exist anywhere in pkg/component/aws/cloudformation — no code derives a
template path from source.uri's basename.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ntinel The stack rebase silently auto-merged a phase3 hunk (the nil StackSetOperation guard) referencing ErrAwsCloudFormationStackSetFailed, a sentinel dropped during conflict resolution in favor of this branch's existing APICallFailed/OperationFailed split — no conflict marker surfaced since the hunk didn't textually overlap with the errors.go conflict. Caught by `go build` immediately after the rebase, not by git. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…/list renderBackendStatuses fell through to the table renderer for any unrecognized format value (e.g. a typo'd --format=jsonn), the same silently-swallowed-bad-format bug class already fixed for `output`'s renderOutputsSummary. Now errors with ErrInvalidFlagValue, matching the convention pkg/toolchain/list.go already uses for the same kind of check. Found via CodeRabbit review (phase4 --dir cmd pass). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ypes list, fix quoting claim - apply.mdx's Flags list was missing --base, despite the --affected example right above it using --base origin/main. - The shared /cli/configuration/components overview page never listed AWS CloudFormation in its "Supported Component Types" dl, even though the YAML example below it already includes aws/cloudformation. - The CFN configuration page claimed the "aws/cloudformation" YAML key "must be quoted... because it contains a /" — verified against a real YAML parser: a bare '/' does not require quoting in YAML. Reworded to describe the quoting as a documentation convention, not a requirement. Found via CodeRabbit review (phase1 pass). A pkg/datafetcher/schema/stacks/ stack-config/1.0.json finding (add secrets to the CFN component manifest) was not fixed: every component type in that schema file is missing secrets (it's a stale, test-only-referenced duplicate of the actively-maintained pkg/datafetcher/schema/atmos/manifest/1.0.json, which already has it) — fixing only CFN there would be a new inconsistency, not a fix. The "union of sections" affected-detection finding (removed sections aren't flagged as affected) was not fixed either: it's the deliberate, tested behavior "section absent locally is skipped" shared by every component type's equivalent helper (see TestAddHelmSectionAffected_NoFalsePositives and TestAddKubernetesSectionAffected's identical subtests) — diverging only CFN from that convention would be new inconsistency, not a fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The --labels flag was migrated from a single comma-separated string to a repeatable pflag StringSlice (fix(cli) 5587d16), but the CLI --help golden snapshots that render its flag description were never regenerated, so every Acceptance Tests shard exercising `--help` for terraform/config commands fails on a stdout mismatch. Regenerated via `-regenerate-snapshots` and hand-verified against the diff CI itself produced; unrelated macOS-local artifacts (trailing blank-line drift, toolchain-info column width) from the same batch regeneration run were discarded rather than committed.
…ndependent TestPrintStackEvent_FailedStatusWithReason and TestValidateTemplate assert raw substring containment against captured stderr from ui.Error/ui.Success, which route through toastMarkdown's styled renderer. At narrower terminal widths (as GitHub Actions' non-TTY runners render, vs. this local environment), toastMarkdown soft-wraps the text and re-emits ANSI style codes per wrapped segment, splitting literal substrings like "CREATE_FAILED" and "template is valid" across escape-code (and sometimes newline+indent) boundaries — breaking the naive assert.Contains checks in CI while passing locally. Verified against a real repro: sweeping COLUMNS from 15 to 120 reproduced both failure shapes (escape-code-only splits and real newline+indent wraps). Fixed by stripping ANSI (github.com/charmbracelet/x/ansi, already vendored) and collapsing whitespace before asserting, via a shared normalizeUIOutput test helper — confirmed passing at every width in that sweep, not just the one CI happened to hit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
what
aws/cloudformationcomponent type: backend management(
backend create/describe/update/delete/list) for the S3 artifact bucket CloudFormationpackaging uses, and a migration guide for Rain/raw-CloudFormation users.
infinite recursion (shared by every bulk-capable component type),
logsstdout routing, missingconfirmation gates, changeset/diff leaks, error-sentinel misuse, and small doc drift.
provision.backend.enabled: truenow actually provisions,instead of requiring a manual
backend createfirst).template:is now the inline template body (string orstructured map, flowing through Atmos's own
{{ }}templating pipeline), and a newpath:keytakes over the file-reference role
template:used to have.EndpointURLoverride in the sharedpkg/ci/artifact/s3store thatbroke template uploads against emulated AWS endpoints (e.g. Floci).
aws cfn/helm/kubernetesduplicating the entire global CLI flag set as localpersistent flags (found via this session's
--helpoutput investigation).--labelsrepeatable across every command family that has it (kubernetes, helm,container, workflow, terraform, vendor, list, cloudformation), matching
--tags' existingrepeatable-flag behavior.
why
management, a documented migration path off Rain, and every rough edge found during a real,
adversarial DX test pass fixed before the feature is announced.
discovered during this pass, not originally scoped work.
references
docs/fixes/.website/docs/migration/from-rain.mdxcloudformation-component-prd.