Skip to content

feat: Add custom component types for custom commands - #2469

Closed
Ben (Benbentwo) wants to merge 1 commit into
cloudposse:feature/dev-3755-custom-component-typesfrom
Benbentwo:benbentwo/dev-3755-custom-component-types
Closed

Ben (Benbentwo) wants to merge 1 commit into
cloudposse:feature/dev-3755-custom-component-typesfrom
Benbentwo:benbentwo/dev-3755-custom-component-types

Conversation

@Benbentwo

@Benbentwo Ben (Benbentwo) commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Implement shell completion for semantic-typed flags and arguments (component/stack types)
  • Add interactive prompting for missing required semantic-typed values
  • Support custom component types in shell completions

What Changed

  • New custom component type provider system (pkg/component/custom)
  • Shell completion for semantic-typed arguments and flags in custom commands
  • Interactive prompting for missing required semantic-typed values
  • Extended command schema to support semantic types and components
  • Comprehensive test coverage for completion and prompting functionality

Why This Matters

This feature enables custom commands to provide superior developer experience through:

  • Tab completion for component and stack arguments/flags
  • Interactive prompts for required semantic-typed values
  • Support for custom component types beyond built-in types

References

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Opt-in lifecycle hook firing for custom component commands via a fires field
    • Commands can publish outputs via an ATMOS_OUTPUTS file (JSON or KEY=VALUE) consumed by hooks
    • Store hook resolves outputs from custom-component outputs files as well as Terraform state
    • Introduced canonical after-apply event with legacy alias support
  • Improvements

    • SSM parameter retrieval now decrypts SecureString values by default
  • Docs & Tests

    • PRD and extensive unit tests added for hooks and outputs handling

@Benbentwo
Ben (Benbentwo) requested review from a team as code owners May 21, 2026 19:40
@atmos-pro

atmos-pro Bot commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@github-actions github-actions Bot added the size/l Large size PR label May 21, 2026
@mergify

mergify Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

💥 This pull request now has conflicts. Could you fix it Ben (@Benbentwo)? 🙏

@mergify mergify Bot added the conflict This PR has conflicts label May 21, 2026
@mergify

mergify Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

⚠️ The sha of the head commit of this PR conflicts with #1904. Mergify cannot evaluate rules on this PR. Once #1904 is merged or closed, Mergify will resume processing this PR. ⚠️

@coderabbitai

coderabbitai Bot commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 114abbbf-f172-4901-bfa3-82383497b56d

📥 Commits

Reviewing files that changed from the base of the PR and between 9c1edcd and 1aed950.

📒 Files selected for processing (6)
  • cmd/cmd_utils.go
  • docs/prd/hooks-for-custom-components.md
  • errors/errors.go
  • examples/custom-components/README.md
  • internal/exec/stack_processor_process_stacks.go
  • pkg/hooks/hooks.go
✅ Files skipped from review due to trivial changes (2)
  • examples/custom-components/README.md
  • docs/prd/hooks-for-custom-components.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/hooks/hooks.go

📝 Walkthrough

Walkthrough

Adds ATMOS_OUTPUTS support and parsing for custom-component commands, normalizes hook event names, centralizes hook execution in internal.RunHooks (accepting pre-resolved component data), and routes store-hook output lookups to Terraform state or the ATMOS_OUTPUTS file based on component type.

Changes

Lifecycle Hooks for Custom Components

Layer / File(s) Summary
Hook event normalization and legacy aliasing
pkg/hooks/event.go, pkg/hooks/event_test.go
Introduce AfterApply as canonical event; add NormalizeEvent and tests; support legacy after-terraform-apply aliasing and per-hook matching.
Outputs file reading and format auto-detection
pkg/hooks/outputs_file.go, pkg/hooks/outputs_file_test.go
Add ReadOutputsFile that auto-detects JSON vs KEY=VALUE, with parsers, isJSONObject, and comprehensive tests.
HooksFromComponent and hook matching
pkg/hooks/hooks.go, pkg/hooks/hooks_test.go
Add HooksFromComponent to build hooks from a resolved component map; update Hooks.RunAll to normalize events and filter hooks with hookMatchesEvent.
Shared hook execution infrastructure
cmd/internal/runhooks.go
Add internal.RunHooks to centralize CLI arg processing, config init, optional populate callback, optional pre-resolved component usage, hook resolution, and execution.
Terraform command hook refactoring
cmd/terraform/apply.go, cmd/terraform/deploy.go, cmd/terraform/utils.go
Terraform apply/deploy now fire AfterApply and delegate hook execution to internal.RunHooks.
Store hook for custom component outputs
pkg/hooks/store_cmd.go, pkg/hooks/store_cmd_custom_test.go, pkg/hooks/store_cmd_nil_handling_test.go, pkg/hooks/store_cmd_test.go
Introduce CustomOutputGetter, defaultCustomOutputter reading ATMOS_OUTPUTS, and dispatch getOutputValue by ComponentType (terraform vs custom). Update logging, error types, and tests.
Custom command hook firing and outputs
cmd/cmd_utils.go, cmd/cmd_utils_fires_test.go
Typed custom commands create a temporary ATMOS_OUTPUTS file, inject ATMOS_OUTPUTS into step env, capture resolved component for reuse, and conditionally fire events from Command.Fires via internal.RunHooks.
Schema and environment setup
pkg/schema/command.go, pkg/schema/schema.go, errors/errors.go, pkg/store/aws_ssm_param_store.go
Add Command.Fires and ConfigAndStacksInfo.OutputsFilePath. Add sentinel errors for outputs handling. SSM parameter requests now set WithDecryption: true.
Specification and examples
docs/prd/hooks-for-custom-components.md, examples/custom-components/README.md
Add PRD describing design, wiring, test scenarios, and examples; minor README formatting fixes.
Stack processor validation
internal/exec/stack_processor_process_stacks.go
Validate custom component entries are map[string]any and surface ErrInvalidComponentMapType on malformed entries.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • cloudposse/atmos#2309: Related to hooks event/matching logic and store hook output retrieval changes.
  • cloudposse/atmos#1639: Related to custom-component validation and error handling touching stack processing.

Suggested labels

minor

Suggested reviewers

  • osterman
  • aknysh
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Add custom component types for custom commands' directly and clearly summarizes the main change: enabling custom component types to work with custom commands.
Linked Issues check ✅ Passed The PR implements the coding requirements for all three linked issues: #1787 (custom component types recognition), #444 (external input to workflows via outputs), and #438 (autocompletion for custom commands).
Out of Scope Changes check ✅ Passed All changes align with the linked objectives: custom component support infrastructure, lifecycle hook coordination via outputs files, event normalization, hook firing configuration, and related test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
internal/exec/stack_processor_process_stacks_test.go (2)

882-903: 💤 Low value

Nice coverage of metadata injection and filter behavior — small assertion tightening suggestion.

The metadata-injection assertions (lines 895-900) are exactly the kind of structural checks the happy-path tests are missing. One small thing: the negative branch at line 902 uses !hasScript || len(scriptSection) == 0. When hasScript is false, scriptSection is the zero value — fine — but the intent reads more clearly as two separate assertions, e.g. assert.NotContains(t, components, "script"). Optional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/exec/stack_processor_process_stacks_test.go` around lines 882 - 903,
The negative assertion for script components is ambiguous; instead of asserting
!hasScript || len(scriptSection) == 0, replace it with a clearer check that the
"script" key is absent from components (e.g., use assert.NotContains(t,
components, "script")) or split into two explicit assertions: assert.False(t,
hasScript) and if hasScript then assert.Len(t, scriptSection, 0). Update
references around components, scriptSection, deployApp and the cfg.* symbols
(cfg.ComponentTypeSectionName, cfg.VarsSectionName) accordingly so the intent is
unambiguous.

350-732: ⚡ Quick win

Happy-path assertions are weak — consider asserting structure, not just non-nil.

Nearly every validateResult in TestProcessStackConfig_HappyPath is assert.NotNil(t, result). Since ProcessStackConfig always returns a non-nil map when err == nil, these cases effectively only assert NoError. For the cases that exercise specific sections (e.g., terraform backend, providers, hooks, stack name override), a couple of targeted assertions on the returned components/name keys would catch real regressions without much added effort.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/exec/stack_processor_process_stacks_test.go` around lines 350 - 732,
The test TestProcessStackConfig_HappyPath uses shallow assertions
(validateResult closures calling assert.NotNil on result) which only check for
non-nil maps; update each validateResult in that table (the closures passed in
the test cases) to assert specific structure and values for the sections under
test (e.g., for the "config with stack-level name override" case assert
result["name"] == "custom-stack-name"; for terraform backend/provider/hook cases
assert presence and expected keys under result["components"] or
result["terraform"] such as backend.bucket, providers.aws.region,
hooks.before_init; for env/vars/settings/auth/components cases assert the
corresponding keys exist and have expected values) so
TestProcessStackConfig_HappyPath fails on real regressions rather than only nil
checks.
examples/custom-components/components/script/deploy-app/deploy.sh (1)

2-5: 💤 Low value

Small wording nit on the comment.

The comment says "uses the component vars via Go templates," but ${APP_NAME}/${VERSION}/${REPLICAS} in this script are plain shell variables, not Go template expressions. Since this file is illustrative-only, consider clarifying so readers don't expect Go-template substitution here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/custom-components/components/script/deploy-app/deploy.sh` around
lines 2 - 5, Update the comment to avoid implying Go template syntax where shell
variables are used: change the line that says "The custom command uses the
component vars via Go templates" to clarify that this script is illustrative and
uses plain shell variables (e.g., ${APP_NAME}, ${VERSION}, ${REPLICAS}) rather
than Go-template expressions; ensure the new comment mentions that the real
custom command may source or substitute these values via Go templates but this
example simply demonstrates shell variable usage in deploy.sh.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/cmd_utils.go`:
- Around line 1506-1550: Add performance tracking to processCustomComponentType
by inserting a defer perf.Track(nil, "cmd.processCustomComponentType")() as the
very first statement in the function (immediately after the signature) and leave
a blank line after that defer; ensure you reference the perf.Track helper and
the function name exactly "cmd.processCustomComponentType" so the call reads
perf.Track(nil, "cmd.processCustomComponentType")().

In `@examples/custom-components/README.md`:
- Line 11: The README.md contains fenced code blocks without a language hint
(MD040); update each plain triple-backtick block that shows directory or snippet
labels to include a language hint such as text so markdownlint stops flagging
them — specifically change the block containing the string
"examples/custom-components/" and the block containing "Component: deploy-app"
(and the other occurrence at the same section referenced as 40-40) to use
```text fenced blocks; ensure all similar untargeted triple-backtick blocks in
the file are updated the same way.

In `@internal/exec/stack_processor_process_stacks.go`:
- Around line 596-632: The three adjacent merges for vars/settings/env use
inconsistent write semantics (vars always overwritten, settings/env only written
when non-empty) and perform only shallow copies; make the behavior consistent
and perform deep merges: change the vars logic so
componentMap[cfg.VarsSectionName] is only set if the merged componentVars is
non-empty (same rule as SettingsSectionName and EnvSectionName), and replace the
manual range-based shallow merge for each of
componentVars/componentSettings/componentEnv with a deep merge using the
existing m.Merge helper (use m.Merge to merge global section into the component
section or vice-versa so nested maps are merged rather than replaced),
referencing the existing identifiers componentMap, cfg.VarsSectionName,
cfg.SettingsSectionName, cfg.EnvSectionName,
componentVars/componentSettings/componentEnv and m.Merge to locate and update
the code.
- Around line 584-587: The custom-component branch silently continues when
components cannot be asserted to map[string]any (componentsMap check), which
hides malformed entries; change that to return an explicit error consistent with
the built-in handlers (like ErrInvalidComponentsTerraform/Helmfile/Packer)
instead of continue so callers see the problem—either reuse an existing
ErrInvalidComponentsCustom (or introduce one) and return it with context naming
the offending component key, matching the inner non-map check behavior near the
later validation.

---

Nitpick comments:
In `@examples/custom-components/components/script/deploy-app/deploy.sh`:
- Around line 2-5: Update the comment to avoid implying Go template syntax where
shell variables are used: change the line that says "The custom command uses the
component vars via Go templates" to clarify that this script is illustrative and
uses plain shell variables (e.g., ${APP_NAME}, ${VERSION}, ${REPLICAS}) rather
than Go-template expressions; ensure the new comment mentions that the real
custom command may source or substitute these values via Go templates but this
example simply demonstrates shell variable usage in deploy.sh.

In `@internal/exec/stack_processor_process_stacks_test.go`:
- Around line 882-903: The negative assertion for script components is
ambiguous; instead of asserting !hasScript || len(scriptSection) == 0, replace
it with a clearer check that the "script" key is absent from components (e.g.,
use assert.NotContains(t, components, "script")) or split into two explicit
assertions: assert.False(t, hasScript) and if hasScript then assert.Len(t,
scriptSection, 0). Update references around components, scriptSection, deployApp
and the cfg.* symbols (cfg.ComponentTypeSectionName, cfg.VarsSectionName)
accordingly so the intent is unambiguous.
- Around line 350-732: The test TestProcessStackConfig_HappyPath uses shallow
assertions (validateResult closures calling assert.NotNil on result) which only
check for non-nil maps; update each validateResult in that table (the closures
passed in the test cases) to assert specific structure and values for the
sections under test (e.g., for the "config with stack-level name override" case
assert result["name"] == "custom-stack-name"; for terraform
backend/provider/hook cases assert presence and expected keys under
result["components"] or result["terraform"] such as backend.bucket,
providers.aws.region, hooks.before_init; for env/vars/settings/auth/components
cases assert the corresponding keys exist and have expected values) so
TestProcessStackConfig_HappyPath fails on real regressions rather than only nil
checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c89d5d34-5153-4ec8-bcc9-81b31b9a2fed

📥 Commits

Reviewing files that changed from the base of the PR and between b010bae and 844dc35.

📒 Files selected for processing (26)
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • errors/errors.go
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • examples/custom-components/components/script/deploy-app/deploy.sh
  • examples/custom-components/stacks/catalog/script/deploy-app.yaml
  • examples/custom-components/stacks/deploy/dev.yaml
  • internal/exec/describe_component.go
  • internal/exec/describe_component_test.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
  • internal/exec/vendor_utils.go
  • pkg/component/custom/provider.go
  • pkg/component/custom/provider_test.go
  • pkg/component/registry.go
  • pkg/component/registry_test.go
  • pkg/schema/command.go
  • tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
  • website/plugins/file-browser/index.js
  • website/src/data/roadmap.js
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

Comment thread cmd/cmd_utils.go
Comment thread examples/custom-components/README.md Outdated
Comment thread internal/exec/stack_processor_process_stacks.go
Comment thread internal/exec/stack_processor_process_stacks.go Outdated
@Benbentwo
Ben (Benbentwo) marked this pull request as draft May 21, 2026 20:18
@Benbentwo
Ben (Benbentwo) changed the base branch from main to feature/dev-3755-custom-component-types June 1, 2026 18:42
@mergify mergify Bot added stacked Stacked and removed conflict This PR has conflicts labels Jun 1, 2026
@Benbentwo

Copy link
Copy Markdown
Contributor Author

CodeRabbit (@coderabbitai) full review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
pkg/hooks/hooks.go (1)

147-154: 💤 Low value

Loop var e shadows the internal/exec import alias.

It works fine today, but e is the package alias on Line 10, so any future edit inside this loop that reaches for the exec package would silently grab the string instead. A quick rename keeps things unambiguous.

♻️ Optional rename
-func hookMatchesEvent(hook Hook, event HookEvent) bool {
-	for _, e := range hook.Events {
-		if NormalizeEvent(e) == event {
-			return true
-		}
-	}
-	return false
-}
+func hookMatchesEvent(hook Hook, event HookEvent) bool {
+	for _, candidate := range hook.Events {
+		if NormalizeEvent(candidate) == event {
+			return true
+		}
+	}
+	return false
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/hooks/hooks.go` around lines 147 - 154, The loop variable `e` in function
hookMatchesEvent shadows the package import alias `exec`; rename the loop
variable to a more descriptive name (e.g., evt or eventStr) in hookMatchesEvent
so it no longer collides with the import alias, update all uses inside that loop
(including the call to NormalizeEvent) to the new name, and run `go vet`/tests
to ensure no other references rely on the old short name.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/cmd_utils.go`:
- Around line 670-684: The temp-file creation error currently uses fmt.Errorf
directly; update the CreateTemp error handling to wrap the underlying err with
the appropriate static error from errors/errors.go (use errors.Join or
fmt.Errorf with the static error's %w as per project convention) before passing
it to errUtils.CheckErrorPrintAndExit; modify the block around os.CreateTemp,
the variable outputsFilePath, and the err passed into
errUtils.CheckErrorPrintAndExit so the logged/returned error is the static error
combined with the original err (ensure the static error symbol from
errors/errors.go is referenced).

In `@docs/prd/hooks-for-custom-components.md`:
- Around line 349-368: The Implementation plan wrongly instructs adding both
BeforeApply and AfterApply constants while the code and design scope exclude
before-apply; update the plan to remove any reference to BeforeApply and state
only AfterApply is added (matching pkg/hooks/event.go where AfterApply is
defined), and ensure other steps (store_cmd.go, cmd_utils.go, docs) do not
reference or implement BeforeApply.

In `@pkg/hooks/hooks.go`:
- Around line 61-64: The yaml.Unmarshal error path returns nil for *Hooks which
is inconsistent with other error branches and can cause a panic when callers
call the value-receiver method HasHooks; change the error return to return
&Hooks{} along with the wrapped error. Specifically, in the block where
yaml.Unmarshal(yamlData, &items) fails, replace the nil *Hooks return with
&Hooks{} so functions/methods like Hooks.HasHooks and other callers always
receive a non-nil *Hooks even on error.

---

Nitpick comments:
In `@pkg/hooks/hooks.go`:
- Around line 147-154: The loop variable `e` in function hookMatchesEvent
shadows the package import alias `exec`; rename the loop variable to a more
descriptive name (e.g., evt or eventStr) in hookMatchesEvent so it no longer
collides with the import alias, update all uses inside that loop (including the
call to NormalizeEvent) to the new name, and run `go vet`/tests to ensure no
other references rely on the old short name.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 471f3818-a089-45d0-afc6-d7379e278343

📥 Commits

Reviewing files that changed from the base of the PR and between 844dc35 and 9c1edcd.

📒 Files selected for processing (21)
  • cmd/cmd_utils.go
  • cmd/cmd_utils_fires_test.go
  • cmd/internal/runhooks.go
  • cmd/terraform/apply.go
  • cmd/terraform/deploy.go
  • cmd/terraform/utils.go
  • docs/prd/hooks-for-custom-components.md
  • errors/errors.go
  • pkg/hooks/event.go
  • pkg/hooks/event_test.go
  • pkg/hooks/hooks.go
  • pkg/hooks/hooks_test.go
  • pkg/hooks/outputs_file.go
  • pkg/hooks/outputs_file_test.go
  • pkg/hooks/store_cmd.go
  • pkg/hooks/store_cmd_custom_test.go
  • pkg/hooks/store_cmd_nil_handling_test.go
  • pkg/hooks/store_cmd_test.go
  • pkg/schema/command.go
  • pkg/schema/schema.go
  • pkg/store/aws_ssm_param_store.go

Comment thread cmd/cmd_utils.go
Comment thread docs/prd/hooks-for-custom-components.md
Comment thread pkg/hooks/hooks.go
@Benbentwo

Copy link
Copy Markdown
Contributor Author

CodeRabbit (@coderabbitai) review

@coderabbitai

coderabbitai Bot commented Jun 3, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Benbentwo
Ben (Benbentwo) marked this pull request as ready for review June 3, 2026 21:30
Ben (Benbentwo) added a commit to Benbentwo/atmos that referenced this pull request Jun 3, 2026
- Status: Draft -> Implemented (PR cloudposse#2469, stacked on/pending merge into cloudposse#1904)
- Section 3: describe the two typed getters actually built
  (TerraformOutputGetter + CustomOutputGetter dispatched via
  isTerraformComponent) instead of the original single-getter sketch; note
  the outputs file parses JSON or KEY=VALUE.
- Section 4: replace the stale generic AfterApply firing prose with the
  before/after.<type>.<subcommand> fireComponentHook flow that shipped.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@mergify

mergify Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

💥 This pull request now has conflicts. Could you fix it Ben (@Benbentwo)? 🙏

@mergify mergify Bot added the conflict This PR has conflicts label Jun 4, 2026
Custom component types fire `<phase>.<type>.<subcommand>` lifecycle hooks
(e.g. before.agent.greeting / after.agent.greeting) and publish outputs via
$ATMOS_OUTPUTS so a `store` hook can persist results — closing the
run → outputs → next-run loop Terraform already has.

- pkg/hooks: ComponentEvent(phase,type,subcommand) helper + PhaseBefore/After;
  HooksFromComponent builds hooks from an already-resolved component map
  (avoids re-describing custom types the built-in describe path can't see);
  store_cmd dispatches output resolution on component type (terraform getter
  vs ATMOS_OUTPUTS file via defaultCustomOutputter); outputs_file parses
  JSON or KEY=VALUE.
- cmd: cmd/internal/runhooks.go shared RunHooks with optional
  preResolvedComponent; custom command path fires before/after derived events.
- internal/exec: custom component types deep-merge global vars/settings/env
  via m.Merge (matching built-in inheritance) and error on malformed config.
- errors: ErrReadOutputsFile, ErrCreateOutputsFile, ErrCustomOutputMissing.
- examples/custom-components: hello-world with a post-run store hook (Redis).
- docs: PRD, website hooks docs, changelog blog, roadmap milestone.
- tests: event naming, outputs-file parsing, store dispatch, SSM WithDecryption.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Benbentwo
Ben (Benbentwo) force-pushed the benbentwo/dev-3755-custom-component-types branch from 4c01670 to e0c2622 Compare June 4, 2026 18:48
@mergify mergify Bot removed the conflict This PR has conflicts label Jun 4, 2026
@mergify

mergify Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

💥 This pull request now has conflicts. Could you fix it Ben (@Benbentwo)? 🙏

@mergify mergify Bot added the conflict This PR has conflicts label Jun 4, 2026
@aknysh
Andriy Knysh (aknysh) deleted the branch cloudposse:feature/dev-3755-custom-component-types June 4, 2026 23:59
@atmos-pro

atmos-pro Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Note

Atmos Pro  

Waiting for your GitHub Actions workflow to upload affected stacks.
Learn More.

@mergify mergify Bot removed the conflict This PR has conflicts label Jun 5, 2026
Ben (Benbentwo) added a commit to Benbentwo/atmos that referenced this pull request Jun 8, 2026
- outputs_file: strip exactly one pair of surrounding quotes (single or
  double) instead of greedily trimming all quote chars, so an inner quote
  survives (e.g. "'hello'" -> 'hello'). Add a nested-quote test.
- outputs_file: add a CRLF test documenting that TrimSpace already strips
  trailing \r from Windows line endings (the flagged concern was already
  handled — no code change needed).
- docs/roadmap: correct stale PR references from cloudposse#2469 to cloudposse#2584; update the
  PRD status (custom component types cloudposse#1904 has merged to main).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Ben (Benbentwo) added a commit to Benbentwo/atmos that referenced this pull request Jun 9, 2026
- outputs_file: strip exactly one pair of surrounding quotes (single or
  double) instead of greedily trimming all quote chars, so an inner quote
  survives (e.g. "'hello'" -> 'hello'). Add a nested-quote test.
- outputs_file: add a CRLF test documenting that TrimSpace already strips
  trailing \r from Windows line endings (the flagged concern was already
  handled — no code change needed).
- docs/roadmap: correct stale PR references from cloudposse#2469 to cloudposse#2584; update the
  PRD status (custom component types cloudposse#1904 has merged to main).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Ben (Benbentwo) added a commit to Benbentwo/atmos that referenced this pull request Jun 10, 2026
- outputs_file: strip exactly one pair of surrounding quotes (single or
  double) instead of greedily trimming all quote chars, so an inner quote
  survives (e.g. "'hello'" -> 'hello'). Add a nested-quote test.
- outputs_file: add a CRLF test documenting that TrimSpace already strips
  trailing \r from Windows line endings (the flagged concern was already
  handled — no code change needed).
- docs/roadmap: correct stale PR references from cloudposse#2469 to cloudposse#2584; update the
  PRD status (custom component types cloudposse#1904 has merged to main).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/l Large size PR stacked Stacked

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom Component Types workflow - being able to specify some external input Enabling Autocompletion for Custom CLI commands

3 participants