Skip to content

feat: Implement workflow step types with registry pattern (DEV-263, DEV-2969) - #1899

Merged
Andriy Knysh (aknysh) merged 60 commits into
mainfrom
feature/dev-263-add-input-type-to-atmos-workflows
May 30, 2026
Merged

Andriy Knysh (aknysh) merged 60 commits into
mainfrom
feature/dev-263-add-input-type-to-atmos-workflows

Conversation

@osterman

@osterman Erik Osterman (Cloud Posse) (osterman) commented Dec 20, 2025 •

Copy link
Copy Markdown
Member

what

  • Add 20+ step types across 4 categories (Interactive, Output, UI, Command) with extensible registry pattern
  • Support Go template variable passing between steps (e.g., {{ .steps.step1.value }})
  • Implement per-step output modes: viewport (pager), raw (passthrough), log (grouped), none (silent)
  • Interactive handlers with TTY detection and clear error messages in CI environments

why

Addresses DEV-263 (add input type to workflows) and DEV-2969 (add viewport support). Enables users to build complex multi-step workflows with user interaction, conditional execution, and flexible result display.

references

Summary by CodeRabbit

Release Notes

  • New Features

    • Added 25+ interactive step types for workflows and custom commands (input, confirm, choose, filter, file, write, markdown, spin, table, style, and more).
    • Support for configurable output modes (viewport, raw, log, none) and step-level display options.
    • Workflow progress rendering and status indicators.
  • Documentation

    • Comprehensive guides for interactive workflows and custom commands with step type reference.
    • New examples demonstrating interactive deployments, credentials collection, and multi-step flows.
  • Bug Fixes

    • Improved error messaging for workflow step validation and execution failures.

Review Change Stack

@github-actions github-actions Bot added the size/xl Extra large size PR label Dec 20, 2025
@mergify

mergify Bot commented Dec 20, 2025

Copy link
Copy Markdown
Contributor

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@github-actions

github-actions Bot commented Dec 20, 2025 •

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@codecov

codecov Bot commented Dec 20, 2025 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.13647% with 405 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.69%. Comparing base (6259051) to head (d92c2b5).

Files with missing lines Patch % Lines
pkg/runner/step/filter.go 36.47% 53 Missing and 1 partial ⚠️
pkg/runner/step/file.go 46.73% 46 Missing and 3 partials ⚠️
pkg/runner/step/confirm.go 24.44% 34 Missing ⚠️
pkg/runner/step/choose.go 56.33% 31 Missing ⚠️
pkg/runner/step/input.go 36.73% 31 Missing ⚠️
pkg/runner/step/write.go 26.82% 30 Missing ⚠️
cmd/cmd_utils.go 18.75% 25 Missing and 1 partial ⚠️
internal/exec/workflow_utils.go 63.49% 18 Missing and 5 partials ⚠️
pkg/runner/step/output_mode.go 88.30% 16 Missing and 4 partials ⚠️
pkg/runner/step/shell.go 80.72% 10 Missing and 6 partials ⚠️
... and 18 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1899      +/-   ##
==========================================
+ Coverage   78.61%   78.69%   +0.07%     
==========================================
  Files        1150     1184      +34     
  Lines      110981   113079    +2098     
==========================================
+ Hits        87253    88984    +1731     
- Misses      18884    19209     +325     
- Partials     4844     4886      +42     
Flag Coverage Δ
unittests 78.69% <81.13%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
errors/errors.go 100.00% <ø> (ø)
pkg/auth/cloud/aws/env.go 100.00% <100.00%> (ø)
pkg/pager/model.go 79.81% <100.00%> (+0.65%) ⬆️
pkg/pager/pager.go 81.94% <100.00%> (+2.57%) ⬆️
pkg/runner/step/alert.go 100.00% <100.00%> (ø)
pkg/runner/step/clear.go 100.00% <100.00%> (ø)
pkg/runner/step/env.go 100.00% <100.00%> (ø)
pkg/runner/step/exit.go 100.00% <100.00%> (ø)
pkg/runner/step/join.go 100.00% <100.00%> (ø)
pkg/runner/step/linebreak.go 100.00% <100.00%> (ø)
... and 37 more

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai

coderabbitai Bot commented Dec 20, 2025 •

Copy link
Copy Markdown
Contributor

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: 02bf21ae-b40e-46d2-9ad0-c21803bcbb5e

📥 Commits

Reviewing files that changed from the base of the PR and between 5f1f6ad and d92c2b5.

📒 Files selected for processing (7)
  • tests/snapshots/TestCLICommands_atmos_workflow_failure.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_on_shell_command.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_filepath.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_stack.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_invalid_step_type.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_shell_command_not_found.stderr.golden
  • tests/snapshots/TestCLICommands_workflow_retries_example.stderr.golden
💤 Files with no reviewable changes (7)
  • tests/snapshots/TestCLICommands_atmos_workflow_failure.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_invalid_step_type.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_on_shell_command.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_stack.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_filepath.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_shell_command_not_found.stderr.golden
  • tests/snapshots/TestCLICommands_workflow_retries_example.stderr.golden

📝 Walkthrough

Walkthrough

Adds a registry-based step execution engine with a reusable executor, enhances workflow UI (header/flags, progress, command rendering), introduces pager viewport constraints, publishes PRDs/docs, adds new sentinel errors, and updates CLI snapshots to use an Explanation section.

Changes

Extended Step Engine, Pager, and Workflow UI

Layer / File(s) Summary
Custom command dispatch via StepExecutor
cmd/cmd_utils.go
Routes custom command steps by type, reusing a StepExecutor and supporting extended types with env propagation.
Pager model: viewport constraints
pkg/pager/model.go
Adds maxHeight/maxWidth, clamps window sizes, and uses constrained viewport dimensions.
Pager API: NewWithViewport and wiring
pkg/pager/pager.go
Adds NewWithViewport and passes constraints to the model during Run.
PRD: Workflow step types system
docs/prd/workflow-step-types.md
Adds a full PRD for step types, schemas, output modes, and testing/plan.
PRD: Custom-command built-in override
docs/prd/custom-command-builtin-override.md
Documents opt-in override and invoke semantics for atmos steps.
Docs: Command registry behavior corrections
docs/prd/command-registry-pattern.md
Corrects collision behavior; built-ins preserved by default.
Sentinel errors for steps/workflows
errors/errors.go
Adds exported errors for step validation/TTY and workflow exit.
AtmosHandler tests
pkg/runner/step/atmos_test.go
Covers resolution helpers, result building, and subprocess execution paths.
Interactive handlers tests and TTY guard
pkg/runner/step/*_test.go
Validates registration/validation and fail-fast behavior without TTY.
Pager and output-mode writer tests
pkg/runner/step/*pager*_test.go, .../output_mode*_test.go
Exercises pager helpers and OutputModeWriter across modes.
SpinHandler tests
pkg/runner/step/spin_test.go
Tests execution options, timeouts, env/wd behavior, and integration.
Test harness for fake atmos
pkg/runner/step/testmain_test.go
Provides controlled atmos subprocess outputs for tests.
Progress renderer tests
pkg/workflow/progress_test.go
Verifies formatting, lifecycle, and disabled/nil behavior.
Show renderer tests
pkg/workflow/show_renderer_test.go
Tests header/flags formatting and single-run guard.
Workflow executor UI and extended steps
internal/exec/workflow_utils.go
Renders header/flags, progress, and commands; executes extended steps.
Golden snapshots: Explanation/Hints reorg
tests/snapshots/*.golden
Moves failed-command details to an Explanation section and updates hints.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI
  participant StepRegistry
  participant StepExecutor
  participant Shell/Atmos

  User->>CLI: run custom command
  CLI->>StepExecutor: create/reuse executor
  loop for each step
    StepExecutor->>StepRegistry: resolve handler by type
    alt shell/atmos
      StepExecutor->>Shell/Atmos: execute command (mode/viewport)
    else extended
      StepExecutor->>StepRegistry: handler.Execute(...)
    end
    StepExecutor->>StepExecutor: store result/env
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • cloudposse/atmos#1901 — Also modifies custom command execution flow in cmd/cmd_utils.go for step processing.
  • cloudposse/atmos#1660 — Related workflow_utils.go error handling changes affecting execution/failure paths.
  • cloudposse/atmos#1764 — Theme system groundwork referenced by updated UI rendering/styling.

Suggested reviewers

  • aknysh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/dev-263-add-input-type-to-atmos-workflows

@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: 15

🧹 Nitpick comments (26)
pkg/schema/workflow.go (1)

15-53: WorkflowStep schema extension looks solid.

Fields are well-organized by category with clear inline comments. The Timeout field as a string is a reasonable choice for YAML/JSON configs (e.g., "30s", "5m").

One note: consider documenting valid Output mode values ("viewport", "raw", "log", "none") in the comment on line 46, or referencing a constants file if one exists.

pkg/workflow/step/executor_test.go (1)

224-242: ListTypes test verifies registry categories.

Confirms all categories are present with sample type checks. Consider adding a count assertion to catch regressions if types are accidentally removed.

pkg/workflow/step/pager.go (1)

27-49: Execute implementation is well-structured.

  • Content resolution with error handling.
  • Conditional title resolution.
  • Error messages include step name for traceability.

The ctx parameter is unused. If pager.Run doesn't support context cancellation, this is acceptable. Otherwise, passing it through would enable timeout/cancellation support.

pkg/workflow/step/error.go (1)

26-38: Consider wrapping the ui.Error failure with step context.

Line 33-35: if ui.Error fails, the error is returned without step name context. Other handlers (e.g., pager.go line 45) wrap errors with step name for traceability.

🔎 Suggested improvement
-	if err := ui.Error(content); err != nil {
-		return nil, err
-	}
+	if err := ui.Error(content); err != nil {
+		return nil, fmt.Errorf("step '%s': failed to display error: %w", step.Name, err)
+	}

This would require adding "fmt" to imports.

pkg/workflow/step/info.go (1)

26-38: Same error wrapping consideration as ErrorHandler.

Line 33-35: the ui.Info error lacks step context. For consistency with pager.go and better debugging, consider wrapping.

🔎 Suggested improvement
-	if err := ui.Info(content); err != nil {
-		return nil, err
-	}
+	if err := ui.Info(content); err != nil {
+		return nil, fmt.Errorf("step '%s': failed to display info: %w", step.Name, err)
+	}

This would require adding "fmt" to imports.

pkg/workflow/step/file.go (2)

53-53: Consider using static errors from errors/errors.go for error wrapping.

Per the coding guidelines, errors should be wrapped using static errors defined in errors/errors.go rather than dynamic fmt.Errorf strings. For example, lines 53, 60, 90, 101, and 131 use dynamic error messages. Consider defining static errors like ErrFailedToResolvePath, ErrFailedToScanDirectory, ErrNoFilesFound, and ErrFileSelectionFailed in the errors package and wrapping them with context.

As per coding guidelines, all errors must be wrapped using static errors defined in errors/errors.go.

Also applies to: 60-60, 90-90, 101-101, 131-131


65-99: filepath.Walk error handling skips inaccessible files silently.

Lines 65-99 use filepath.Walk and return nil when encountering access errors (line 67), which silently skips files the user can't access. While this prevents the walk from failing entirely, users might be confused if expected files don't appear. Consider logging skipped files or accumulating warnings to surface later.

pkg/workflow/step/table.go (3)

51-56: Potential index out of bounds if Data is empty.

Line 53 accesses step.Data[0] without verifying that len(step.Data) > 0 in the condition. While line 51 checks len(step.Data) > 0, if Data passes validation as empty (when Content is present), this code path shouldn't be reached. Consider adding an explicit guard or comment clarifying the invariant.


83-83: TODO: Integration with existing table formatter.

The TODO on line 83 notes plans to integrate with pkg/list/format/table.go for lipgloss styling. The current tab-separated approach is functional but basic.

Would you like me to create an issue to track this integration work?


27-27: Use static errors for error wrapping.

Lines 27 and 90 use dynamic error messages with fmt.Errorf. Per coding guidelines, consider defining static errors in errors/errors.go (e.g., ErrTableDataRequired, ErrFailedToResolveTitle) and wrapping them with context.

As per coding guidelines, all errors must be wrapped using static errors defined in errors/errors.go.

Also applies to: 90-90

pkg/workflow/step/confirm.go (1)

75-75: Use static error for confirmation failure.

Line 75 uses fmt.Errorf with a dynamic message. Per coding guidelines, define a static error like ErrConfirmationFailed in errors/errors.go and wrap it with the step name context.

As per coding guidelines, all errors must be wrapped using static errors defined in errors/errors.go.

pkg/workflow/step/output_mode_test.go (1)

71-89: Concurrent write test assumes deterministic byte accumulation.

The test on line 88 asserts an exact length of 40 bytes (10 goroutines × 4 bytes each). While this validates accumulation, concurrent writes may have interleaving or buffering behaviors that could affect the exact output. Consider whether this test should focus on the presence of all data rather than exact byte count, or add a comment documenting the assumption.

pkg/workflow/step/spin.go (1)

68-72: Consider addressing the TODO for shell parsing.

strings.Fields will break on quoted arguments (e.g., echo "hello world"). The TODO is noted, but this could cause subtle bugs. A library like github.com/kballard/go-shellquote or github.com/google/shlex would handle this properly.

pkg/workflow/step/join.go (1)

31-56: Consider making the separator configurable.

Currently hardcoded to newline. A configurable separator (via a new field or reusing an existing one) would add flexibility. Not blocking—the current default is reasonable.

pkg/workflow/step/style.go (1)

3-9: Organize imports into three groups with blank lines.

Per coding guidelines, imports should be in three groups separated by blank lines: 1) Go stdlib, 2) 3rd-party, 3) Atmos packages.

Suggested import organization
 import (
 	"context"
+
 	"github.com/cloudposse/atmos/pkg/data"
 	"github.com/cloudposse/atmos/pkg/schema"
 	"github.com/cloudposse/atmos/pkg/ui/theme"
 )

Based on coding guidelines requiring three-group import organization.

pkg/workflow/step/markdown.go (1)

3-8: Organize imports into three groups with blank lines.

Imports should be separated into groups per coding guidelines: 1) Go stdlib, 2) 3rd-party, 3) Atmos packages.

Suggested import organization
 import (
 	"context"
+
 	"github.com/cloudposse/atmos/pkg/schema"
 	"github.com/cloudposse/atmos/pkg/ui"
 )

Based on coding guidelines.

pkg/workflow/step/atmos.go (1)

3-11: Organize imports with blank lines between groups.

Suggested organization
 import (
 	"context"
 	"fmt"
 	"os"
 	"os/exec"
 	"strings"
+
 	"github.com/cloudposse/atmos/pkg/schema"
 )

Based on coding guidelines.

pkg/workflow/step/warn.go (1)

3-8: Organize imports with blank lines between groups.

Suggested organization
 import (
 	"context"
+
 	"github.com/cloudposse/atmos/pkg/schema"
 	"github.com/cloudposse/atmos/pkg/ui"
 )

Based on coding guidelines.

pkg/workflow/step/filter.go (1)

3-14: Organize imports with blank lines between groups.

Suggested organization
 import (
 	"context"
 	"errors"
 	"fmt"
+
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/huh"
+
 	errUtils "github.com/cloudposse/atmos/errors"
 	uiutils "github.com/cloudposse/atmos/internal/tui/utils"
 	"github.com/cloudposse/atmos/pkg/schema"
 )

Based on coding guidelines.

pkg/workflow/step/input.go (1)

3-14: Organize imports with blank lines between groups.

Suggested organization
 import (
 	"context"
 	"errors"
 	"fmt"
+
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/huh"
+
 	errUtils "github.com/cloudposse/atmos/errors"
 	uiutils "github.com/cloudposse/atmos/internal/tui/utils"
 	"github.com/cloudposse/atmos/pkg/schema"
 )

Based on coding guidelines.

pkg/workflow/step/output_handlers_test.go (1)

3-10: Organize imports with blank lines between groups.

Suggested organization
 import (
 	"testing"
+
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
 	"github.com/cloudposse/atmos/pkg/schema"
 )

Based on coding guidelines.

pkg/workflow/step/shell.go (1)

3-12: Organize imports with blank lines between groups.

Suggested organization
 import (
 	"context"
 	"errors"
 	"fmt"
 	"os"
 	"os/exec"
 	"strings"
+
 	"github.com/cloudposse/atmos/pkg/schema"
 )

Based on coding guidelines.

pkg/workflow/step/interactive_handlers_test.go (2)

90-91: Malformed nolint directive.

The nolintlint comment on line 90 isn't a valid directive format. It should either be removed or properly formatted.

🔎 Proposed fix
-// nolintlint: dupl - Similar test patterns for different handlers.
 // nolint: dupl
 func TestConfirmHandlerValidation(t *testing.T) {

203-204: Same malformed nolint directive here.

Same issue as line 90 — the nolintlint comment isn't doing anything useful.

🔎 Proposed fix
-// nolintlint: dupl - Similar test patterns for different handlers.
 // nolint: dupl
 func TestWriteHandlerValidation(t *testing.T) {
pkg/workflow/step/registry.go (1)

42-46: Consider nil handler guard.

If a nil handler is passed, handler.GetName() will panic. Since this runs in init(), a panic is acceptable for fail-fast, but an explicit check could provide a clearer error message.

🔎 Optional defensive check
 func Register(handler StepHandler) {
+	if handler == nil {
+		panic("cannot register nil step handler")
+	}
 	registry.mu.Lock()
 	defer registry.mu.Unlock()
 	registry.handlers[handler.GetName()] = handler
 }
pkg/workflow/step/handler_base.go (1)

73-107: Unused context parameter.

The ctx parameter is passed but unused in all three Resolve* methods. This is fine for forward compatibility (future cancellation support), but you could add a _ = ctx or brief comment to silence linters if they flag it.

🔎 Optional: silence unused parameter warnings
 func (h BaseHandler) ResolveContent(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (string, error) {
+	_ = ctx // Reserved for future cancellation support.
 	if step.Content == "" {
 		return "", nil
 	}

Comment thread pkg/runner/step/atmos.go
Comment thread pkg/workflow/step/atmos.go Outdated
Comment thread pkg/runner/step/atmos.go
Comment thread pkg/workflow/step/choose.go Outdated
Comment thread pkg/runner/step/executor.go
Comment thread pkg/runner/step/shell.go
Comment thread pkg/runner/step/shell.go
Comment thread pkg/workflow/step/spin.go Outdated
Comment thread pkg/runner/step/style.go
Comment thread pkg/workflow/step/warn.go Outdated
@osterman Erik Osterman (Cloud Posse) (osterman) added the minor New features that do not break anything label Dec 20, 2025
@github-actions

Copy link
Copy Markdown

Warning

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-20-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

@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: 1

♻️ Duplicate comments (6)
pkg/workflow/step/atmos.go (3)

30-42: Add performance tracking to public Execute method.

Missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *AtmosHandler) Execute(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (*StepResult, error) {
+	defer perf.Track(nil, "step.AtmosHandler.Execute")()
+
 	opts, err := h.prepareExecution(ctx, step, vars)

Based on coding guidelines.


165-176: Add performance tracking to public ExecuteWithWorkflow method.

Missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *AtmosHandler) ExecuteWithWorkflow(ctx context.Context, step *schema.WorkflowStep, vars *Variables, workflow *schema.WorkflowDefinition) (*StepResult, error) {
+	defer perf.Track(nil, "step.AtmosHandler.ExecuteWithWorkflow")()
+
 	opts, err := h.prepareExecution(ctx, step, vars)

Based on coding guidelines.


179-194: Remove unreachable dead code.

Lines 189-191 are unreachable because line 181 already handles arg == "-s" and returns true. The final check for a following value is never reached.

Remove dead code
 func containsStackFlag(args []string) bool {
 	for i, arg := range args {
 		if arg == "-s" || arg == "--stack" {
 			return true
 		}
 		// Check for -s=value or --stack=value.
 		if strings.HasPrefix(arg, "-s=") || strings.HasPrefix(arg, "--stack=") {
 			return true
 		}
-		// Check if next arg would be stack value for -s.
-		if arg == "-s" && i+1 < len(args) {
-			return true
-		}
 	}
 	return false
 }
pkg/workflow/step/filter.go (1)

42-68: Add performance tracking to public Execute method.

Missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *FilterHandler) Execute(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (*StepResult, error) {
+	defer perf.Track(nil, "step.FilterHandler.Execute")()
+
 	if err := h.CheckTTY(step); err != nil {

Based on coding guidelines.

pkg/workflow/step/choose.go (1)

100-109: Default selection not applied.

The call to opt.Selected(true) returns a new option with the selected state but doesn't mutate the existing option. Since the returned value isn't assigned back, the default selection is lost.

Proposed fix
 func (h *ChooseHandler) runSelectForm(stepName, prompt string, options []string, defaultVal string) (*StepResult, error) {
 	var choice string
-	huhOptions := huh.NewOptions(options...)
-	for _, opt := range huhOptions {
+	huhOptions := make([]huh.Option[string], len(options))
+	for i, optVal := range options {
+		opt := huh.NewOption(optVal, optVal)
-		if opt.Value == defaultVal {
-			opt.Selected(true)
-			break
+		if optVal == defaultVal {
+			opt = opt.Selected(true)
 		}
+		huhOptions[i] = opt
 	}
pkg/workflow/step/executor.go (1)

103-120: RunAll still uses dynamic error for step failure.

Line 115 creates fmt.Errorf("step '%s' failed: %w", ...). Per past review and coding guidelines, this should wrap a static error like ErrWorkflowStepFailed.

Recommended fix
-			return fmt.Errorf("step '%s' failed: %w", step.Name, err)
+			return errUtils.Build(errUtils.ErrWorkflowStepFailed).
+				WithContext("step", step.Name).
+				WithCause(err).
+				Err()

This assumes ErrWorkflowStepFailed exists in errors/errors.go (per learnings, it should).

🧹 Nitpick comments (8)
examples/demo-interactive-workflows/README.md (1)

145-145: Add closing punctuation.

The final line should end with a period for consistency with documentation standards.

🔎 Proposed fix
-- Use environment variables instead of prompts
+- Use environment variables instead of prompts.
pkg/workflow/step/log.go (1)

64-71: Consider logging template resolution failures.

When vars.Resolve(value) fails, the error is silently discarded and the original value is used. While this provides a fallback, it could mask configuration issues where template variables are misspelled or undefined.

Consider logging the error at debug level so issues are discoverable:

🔎 Proposed enhancement
 	for key, value := range step.Fields {
 		// Resolve template variables in field values.
 		resolvedValue, err := vars.Resolve(value)
 		if err != nil {
-			// On error, use the original value.
+			// On error, use the original value but log for debugging.
+			log.Debug("Failed to resolve template in log field", "key", key, "value", value, "error", err.Error())
 			resolvedValue = value
 		}
 		keyvals = append(keyvals, key, resolvedValue)
 	}
pkg/workflow/step/linebreak.go (1)

29-41: Add performance tracking to public Execute method.

The Execute method is missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *LinebreakHandler) Execute(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (*StepResult, error) {
+	defer perf.Track(nil, "step.LinebreakHandler.Execute")()
+
 	count := step.Count

Based on coding guidelines.

pkg/workflow/step/choose.go (1)

42-63: Add performance tracking to public Execute method.

Missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *ChooseHandler) Execute(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (*StepResult, error) {
+	defer perf.Track(nil, "step.ChooseHandler.Execute")()
+
 	if err := h.CheckTTY(step); err != nil {

Based on coding guidelines.

pkg/workflow/step/pager.go (1)

34-70: Add performance tracking to public Execute method.

Missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *PagerHandler) Execute(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (*StepResult, error) {
+	defer perf.Track(nil, "step.PagerHandler.Execute")()
+
 	var content string

Based on coding guidelines.

pkg/workflow/step/file.go (1)

36-73: Add performance tracking to public Execute method.

Missing the required defer perf.Track() call per coding guidelines.

Add performance tracking
 func (h *FileHandler) Execute(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (*StepResult, error) {
+	defer perf.Track(nil, "step.FileHandler.Execute")()
+
 	if err := h.CheckTTY(step); err != nil {

Based on coding guidelines.

pkg/workflow/step/handler_base.go (1)

76-110: Unused context parameter in Resolve methods.

The ctx parameter is unused in ResolveContent, ResolvePrompt, and ResolveCommand. If it's for future cancellation support or interface consistency, consider adding a brief comment. Otherwise, these could be simplified.

Option: Document intent or remove unused param

If ctx is for future use:

// ResolveContent resolves Go templates in the content field.
// The context is included for future cancellation support.
func (h BaseHandler) ResolveContent(ctx context.Context, step *schema.WorkflowStep, vars *Variables) (string, error) {

Or if not needed, remove it from the signature (would require updating callers).

pkg/workflow/step/output_mode.go (1)

222-236: StreamingOutputWriter silently ignores write errors.

Line 232 discards the error from fmt.Fprintf. If the target is unavailable, this fails silently. Consider at minimum logging a warning or returning the error.

Option: Handle or log write errors
 	// Write with prefix to target.
 	if w.target != nil {
-		_, _ = fmt.Fprintf(w.target, "%s %s", w.prefix, string(p))
+		if _, writeErr := fmt.Fprintf(w.target, "%s %s", w.prefix, string(p)); writeErr != nil {
+			// Log at debug level or accumulate for later inspection.
+		}
 	}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a82ae17 and 5a30c93.

📒 Files selected for processing (34)
  • errors/errors.go (1 hunks)
  • examples/demo-interactive-workflows/README.md (1 hunks)
  • examples/demo-interactive-workflows/atmos.yaml (1 hunks)
  • examples/demo-interactive-workflows/stacks/deploy/dev.yaml (1 hunks)
  • examples/demo-interactive-workflows/stacks/deploy/prod.yaml (1 hunks)
  • examples/demo-interactive-workflows/stacks/deploy/staging.yaml (1 hunks)
  • examples/demo-interactive-workflows/stacks/workflows/interactive.yaml (1 hunks)
  • internal/exec/workflow_utils.go (5 hunks)
  • pkg/schema/workflow.go (1 hunks)
  • pkg/ui/markdown/styles.go (1 hunks)
  • pkg/ui/theme/converter.go (1 hunks)
  • pkg/ui/theme/styles.go (3 hunks)
  • pkg/workflow/step/atmos.go (1 hunks)
  • pkg/workflow/step/choose.go (1 hunks)
  • pkg/workflow/step/executor.go (1 hunks)
  • pkg/workflow/step/executor_test.go (1 hunks)
  • pkg/workflow/step/file.go (1 hunks)
  • pkg/workflow/step/filter.go (1 hunks)
  • pkg/workflow/step/handler_base.go (1 hunks)
  • pkg/workflow/step/interactive_handlers_test.go (1 hunks)
  • pkg/workflow/step/join.go (1 hunks)
  • pkg/workflow/step/linebreak.go (1 hunks)
  • pkg/workflow/step/log.go (1 hunks)
  • pkg/workflow/step/output_handlers_test.go (1 hunks)
  • pkg/workflow/step/output_mode.go (1 hunks)
  • pkg/workflow/step/pager.go (1 hunks)
  • pkg/workflow/step/shell.go (1 hunks)
  • pkg/workflow/step/spin.go (1 hunks)
  • pkg/workflow/step/style.go (1 hunks)
  • pkg/workflow/step/table.go (1 hunks)
  • pkg/workflow/step/variables.go (1 hunks)
  • pkg/workflow/step/variables_test.go (1 hunks)
  • website/docs/cli/commands/workflow.mdx (1 hunks)
  • website/docs/workflows/workflows.mdx (2 hunks)
✅ Files skipped from review due to trivial changes (4)
  • examples/demo-interactive-workflows/atmos.yaml
  • examples/demo-interactive-workflows/stacks/deploy/staging.yaml
  • website/docs/workflows/workflows.mdx
  • examples/demo-interactive-workflows/stacks/deploy/dev.yaml
🚧 Files skipped from review as they are similar to previous changes (7)
  • pkg/workflow/step/variables_test.go
  • pkg/workflow/step/join.go
  • pkg/workflow/step/interactive_handlers_test.go
  • pkg/workflow/step/shell.go
  • pkg/workflow/step/variables.go
  • pkg/workflow/step/table.go
  • pkg/workflow/step/style.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • pkg/ui/theme/converter.go
  • pkg/ui/markdown/styles.go
  • pkg/workflow/step/spin.go
  • pkg/ui/theme/styles.go
  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/choose.go
  • pkg/workflow/step/linebreak.go
  • errors/errors.go
  • pkg/workflow/step/pager.go
  • pkg/workflow/step/file.go
  • pkg/workflow/step/filter.go
  • internal/exec/workflow_utils.go
  • pkg/workflow/step/atmos.go
  • pkg/workflow/step/log.go
  • pkg/workflow/step/output_mode.go
  • pkg/workflow/step/handler_base.go
  • pkg/workflow/step/output_handlers_test.go
  • pkg/workflow/step/executor.go
  • pkg/schema/workflow.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/cli/commands/workflow.mdx
website/docs/cli/commands/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

All CLI commands/flags need Docusaurus documentation in website/docs/cli/commands/ with specific structure: frontmatter, Intro component, Screengrab component, Usage section, Arguments/Flags using

/
, and Examples section

Files:

  • website/docs/cli/commands/workflow.mdx
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/output_handlers_test.go
🧠 Learnings (56)
📓 Common learnings
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • examples/demo-interactive-workflows/stacks/workflows/interactive.yaml
  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/choose.go
  • pkg/workflow/step/linebreak.go
  • errors/errors.go
  • examples/demo-interactive-workflows/README.md
  • internal/exec/workflow_utils.go
  • pkg/workflow/step/atmos.go
  • pkg/workflow/step/log.go
  • pkg/workflow/step/output_mode.go
  • pkg/workflow/step/handler_base.go
  • pkg/workflow/step/output_handlers_test.go
  • pkg/workflow/step/executor.go
  • pkg/schema/workflow.go
📚 Learning: 2025-12-13T06:10:25.156Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.

Applied to files:

  • examples/demo-interactive-workflows/stacks/workflows/interactive.yaml
  • pkg/workflow/step/spin.go
  • pkg/workflow/step/executor_test.go
  • errors/errors.go
  • examples/demo-interactive-workflows/README.md
  • internal/exec/workflow_utils.go
  • pkg/workflow/step/atmos.go
  • pkg/workflow/step/output_mode.go
  • pkg/workflow/step/handler_base.go
  • pkg/workflow/step/executor.go
  • pkg/schema/workflow.go
📚 Learning: 2025-10-11T19:12:38.832Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: tests/snapshots/TestCLICommands_atmos_workflow_invalid_step_type.stderr.golden:0-0
Timestamp: 2025-10-11T19:12:38.832Z
Learning: Usage Examples sections in error output are appropriate for command usage errors (incorrect syntax, missing arguments, invalid flags) but not for configuration validation errors (malformed workflow files, invalid settings in atmos.yaml). Configuration errors should focus on explaining what's wrong with the config, not command usage patterns.

Applied to files:

  • website/docs/cli/commands/workflow.mdx
  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.

Applied to files:

  • pkg/workflow/step/spin.go
📚 Learning: 2025-12-13T04:37:25.223Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/root.go:0-0
Timestamp: 2025-12-13T04:37:25.223Z
Learning: In Atmos cmd/root.go Execute(), after cfg.InitCliConfig, we must call both toolchainCmd.SetAtmosConfig(&atmosConfig) and toolchain.SetAtmosConfig(&atmosConfig) so the CLI wrapper and the toolchain package receive configuration; missing either can cause nil-pointer panics in toolchain path resolution.

Applied to files:

  • pkg/workflow/step/spin.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2025-11-11T03:47:45.878Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/add_test.go:67-77
Timestamp: 2025-11-11T03:47:45.878Z
Learning: In the cloudposse/atmos codebase, tests should prefer t.Setenv for environment variable setup/teardown instead of os.Setenv/Unsetenv to ensure test-scoped isolation.

Applied to files:

  • pkg/workflow/step/spin.go
📚 Learning: 2025-01-09T22:37:01.004Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform_commands.go:260-265
Timestamp: 2025-01-09T22:37:01.004Z
Learning: In the terraform commands implementation (cmd/terraform_commands.go), the direct use of `os.Args[2:]` for argument handling is intentionally preserved to avoid extensive refactoring. While it could be improved to use cobra's argument parsing, such changes should be handled in a dedicated PR to maintain focus and minimize risk.

Applied to files:

  • pkg/workflow/step/spin.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • pkg/workflow/step/spin.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.

Applied to files:

  • pkg/workflow/step/spin.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Use colors from pkg/ui/theme/colors.go for all UI output

Applied to files:

  • pkg/ui/theme/styles.go
📚 Learning: 2024-10-31T19:25:41.298Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:233-235
Timestamp: 2024-10-31T19:25:41.298Z
Learning: When specifying color values in functions like `confirmDeleteTerraformLocal` in `internal/exec/terraform_clean.go`, avoid hardcoding color values. Instead, use predefined color constants or allow customization through configuration settings to improve accessibility and user experience across different terminals and themes.

Applied to files:

  • pkg/ui/theme/styles.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • pkg/ui/theme/styles.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/ui/theme/styles.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/output_handlers_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/output_handlers_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/output_handlers_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/output_handlers_test.go
📚 Learning: 2025-12-13T06:10:13.688Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: errors/errors.go:184-203
Timestamp: 2025-12-13T06:10:13.688Z
Learning: cloudposse/atmos: For toolchain work, duplicate/unused error sentinels in errors/errors.go should be cleaned up in a separate refactor PR and not block feature PRs; canonical toolchain sentinels live under toolchain/registry with re-exports in toolchain/errors.go.

Applied to files:

  • errors/errors.go
  • pkg/workflow/step/executor.go
📚 Learning: 2024-12-12T17:13:53.409Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 848
File: pkg/utils/doc_utils.go:19-22
Timestamp: 2024-12-12T17:13:53.409Z
Learning: In `pkg/utils/doc_utils.go`, the `DisplayDocs` function uses the `PAGER` environment variable, which is intentionally user-configurable to allow users to specify custom pager commands that fit their workflow; adding validation to restrict it is not desired.

Applied to files:

  • pkg/workflow/step/pager.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to README.md : Update README.md with new commands and features

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-11-07T14:52:55.217Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1761
File: docs/prd/claude-agent-architecture.md:331-439
Timestamp: 2025-11-07T14:52:55.217Z
Learning: In the cloudposse/atmos repository, Claude agents are used as interactive tools, not in automated/headless CI/CD contexts. Agent documentation and patterns should assume synchronous human interaction.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-10-11T19:11:58.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:0-0
Timestamp: 2025-10-11T19:11:58.965Z
Learning: For terraform apply interactivity checks in Atmos (internal/exec/terraform.go), use stdin TTY detection (e.g., `IsTTYSupportForStdin()` or checking `os.Stdin`) to determine if user prompts are possible. This is distinct from stdout/stderr TTY checks used for output display (like TUI rendering). User input requires stdin to be a TTY; output display requires stdout/stderr to be a TTY.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2024-11-12T13:06:56.194Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: website/docs/cheatsheets/vendoring.mdx:70-70
Timestamp: 2024-11-12T13:06:56.194Z
Learning: In `atmos vendor pull --everything`, the `--everything` flag uses the TTY for TUI but is not interactive.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-11-30T04:16:24.155Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:34-48
Timestamp: 2025-11-30T04:16:24.155Z
Learning: In the cloudposse/atmos repository, the `defer perf.Track()` guideline applies to functions that perform meaningful work (I/O, computation, external calls), but explicitly excludes trivial accessors/mutators (e.g., simple getters, setters with single integer increments, string joins, or map appends) where the tracking overhead would exceed the actual method cost and provide no actionable performance data. Hot-path methods called in tight loops should especially avoid perf.Track() if they perform only trivial operations.

Applied to files:

  • pkg/workflow/step/filter.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2025-11-30T04:16:01.899Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:50-59
Timestamp: 2025-11-30T04:16:01.899Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` should NOT be added to trivial O(1) getter methods that only return field references or check map lengths (e.g., `GetDeferredValues()`, `HasDeferredValues()`). The guideline to add perf tracking to "all public functions" applies to functions that do meaningful work (I/O, computation, external calls), not to trivial accessors where the tracking overhead would exceed the operation time and pollute performance reports.

Applied to files:

  • pkg/workflow/step/filter.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions for performance tracking; use nil if no atmosConfig param

Applied to files:

  • pkg/workflow/step/filter.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.

Applied to files:

  • pkg/workflow/step/filter.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning the error instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions.

Applied to files:

  • internal/exec/workflow_utils.go
  • pkg/workflow/step/executor.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • internal/exec/workflow_utils.go
  • pkg/workflow/step/atmos.go
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • internal/exec/workflow_utils.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • internal/exec/workflow_utils.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.

Applied to files:

  • internal/exec/workflow_utils.go
📚 Learning: 2025-02-03T06:00:11.419Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/describe_config.go:20-20
Timestamp: 2025-02-03T06:00:11.419Z
Learning: Commands should use `PrintErrorMarkdownAndExit` with empty title and suggestion (`"", err, ""`) for general error handling. Specific titles like "Invalid Usage" or "File Not Found" should only be used for validation or specific error scenarios.

Applied to files:

  • internal/exec/workflow_utils.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.

Applied to files:

  • internal/exec/workflow_utils.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: The user confirmed that the errors package has an error string wrapping format, contradicting the previous learning about ErrWrappingFormat being invalid. The current usage of fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) appears to be the correct pattern.

Applied to files:

  • internal/exec/workflow_utils.go
  • pkg/workflow/step/executor.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • pkg/workflow/step/atmos.go
  • pkg/workflow/step/executor.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-02-09T14:38:53.443Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/cmd_utils.go:0-0
Timestamp: 2025-02-09T14:38:53.443Z
Learning: Error handling for RegisterFlagCompletionFunc in AddStackCompletion is not required as the errors are non-critical for tab completion functionality.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • pkg/workflow/step/atmos.go
  • pkg/workflow/step/executor.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • pkg/workflow/step/atmos.go
📚 Learning: 2025-02-06T13:38:07.216Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/copy_glob.go:0-0
Timestamp: 2025-02-06T13:38:07.216Z
Learning: The `u.LogTrace` function in the `cloudposse/atmos` repository accepts `atmosConfig` as its first parameter, followed by the message string.

Applied to files:

  • pkg/workflow/step/log.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Separate I/O (streams) from UI (formatting): use I/O Layer (pkg/io/) for stream access and UI Layer (pkg/ui/) for formatting; use data.Write/Writeln/WriteJSON/WriteYAML for pipeable output to stdout and ui.Write/Success/Error/Warning/Info for human messages to stderr

Applied to files:

  • pkg/workflow/step/output_mode.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly

Applied to files:

  • pkg/workflow/step/executor.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using `fmt.Errorf("context: %w", err)`, and consider using custom error types for domain-specific errors

Applied to files:

  • pkg/workflow/step/executor.go
📚 Learning: 2024-10-12T18:38:28.458Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 715
File: pkg/logger/logger.go:21-32
Timestamp: 2024-10-12T18:38:28.458Z
Learning: In Go code, avoid prefixing struct names with 'I' (e.g., `IError`) as it can be confusing, suggesting an interface. Use descriptive names for structs to improve code clarity.

Applied to files:

  • pkg/workflow/step/executor.go
📚 Learning: 2025-04-04T02:03:21.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:71-72
Timestamp: 2025-04-04T02:03:21.906Z
Learning: The codebase currently uses `log.Fatal` for error handling in library functions, which terminates the program. There is a plan to refactor this approach in a separate PR to improve API design by returning error messages instead of terminating execution.

Applied to files:

  • pkg/workflow/step/executor.go
🧬 Code graph analysis (10)
pkg/workflow/step/choose.go (4)
pkg/workflow/step/handler_base.go (2)
  • BaseHandler (13-17)
  • NewBaseHandler (20-26)
pkg/workflow/step/registry.go (1)
  • Register (42-46)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
errors/errors.go (2)
  • ErrStepOptionsRequired (448-448)
  • ErrUserAborted (555-555)
pkg/workflow/step/linebreak.go (4)
pkg/workflow/step/handler_base.go (2)
  • BaseHandler (13-17)
  • NewBaseHandler (20-26)
pkg/workflow/step/types.go (2)
  • CategoryUI (12-12)
  • NewStepResult (46-51)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
pkg/workflow/step/variables.go (1)
  • Variables (12-17)
pkg/workflow/step/file.go (5)
pkg/workflow/step/registry.go (1)
  • Register (42-46)
pkg/workflow/step/types.go (3)
  • CategoryInteractive (8-8)
  • StepResult (32-43)
  • NewStepResult (46-51)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
pkg/workflow/step/variables.go (1)
  • Variables (12-17)
errors/errors.go (2)
  • ErrStepNoFilesFound (452-452)
  • ErrUserAborted (555-555)
internal/exec/workflow_utils.go (4)
pkg/workflow/step/executor.go (3)
  • IsExtendedStepType (134-149)
  • StepExecutor (13-16)
  • NewStepExecutor (19-23)
errors/errors.go (1)
  • ErrInvalidWorkflowStepType (441-441)
errors/exit_code.go (1)
  • WithExitCode (40-48)
pkg/schema/workflow.go (2)
  • WorkflowStep (16-75)
  • WorkflowDefinition (78-88)
pkg/workflow/step/atmos.go (4)
pkg/workflow/step/handler_base.go (2)
  • BaseHandler (13-17)
  • NewBaseHandler (20-26)
pkg/workflow/step/registry.go (1)
  • Register (42-46)
pkg/workflow/step/variables.go (1)
  • Variables (12-17)
pkg/workflow/step/output_mode.go (2)
  • GetOutputMode (175-188)
  • GetViewportConfig (191-203)
pkg/workflow/step/log.go (5)
pkg/workflow/step/handler_base.go (2)
  • BaseHandler (13-17)
  • NewBaseHandler (20-26)
pkg/workflow/step/types.go (2)
  • CategoryOutput (10-10)
  • NewStepResult (46-51)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
pkg/workflow/step/variables.go (1)
  • Variables (12-17)
pkg/logger/log.go (9)
  • Level (203-203)
  • TraceLevel (211-211)
  • Trace (14-16)
  • DebugLevel (213-213)
  • Debug (24-26)
  • WarnLevel (217-217)
  • Warn (44-46)
  • ErrorLevel (219-219)
  • InfoLevel (215-215)
pkg/workflow/step/handler_base.go (5)
pkg/workflow/step/types.go (1)
  • StepCategory (4-4)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
errors/builder.go (1)
  • Build (24-37)
errors/errors.go (2)
  • ErrStepTTYRequired (454-454)
  • ErrStepFieldRequired (453-453)
pkg/workflow/step/variables.go (1)
  • Variables (12-17)
pkg/workflow/step/output_handlers_test.go (3)
pkg/workflow/step/types.go (2)
  • StepCategory (4-4)
  • CategoryOutput (10-10)
pkg/workflow/step/registry.go (2)
  • Get (49-54)
  • ListByCategory (68-77)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
pkg/workflow/step/executor.go (5)
pkg/workflow/step/variables.go (2)
  • Variables (12-17)
  • NewVariables (20-28)
pkg/schema/workflow.go (2)
  • WorkflowDefinition (78-88)
  • WorkflowStep (16-75)
pkg/workflow/step/types.go (2)
  • StepResult (32-43)
  • StepCategory (4-4)
pkg/workflow/step/registry.go (3)
  • Get (49-54)
  • StepHandler (13-28)
  • ListByCategory (68-77)
errors/errors.go (1)
  • ErrUnknownStepType (447-447)
pkg/schema/workflow.go (1)
pkg/schema/schema.go (1)
  • RetryConfig (784-792)
🪛 LanguageTool
examples/demo-interactive-workflows/README.md

[typographical] ~118-~118: To join two clauses or introduce examples, consider using an em dash.
Context: ...Variables - {{ .steps.<name>.value }} - Primary value from step - `{{ .steps.<na...

(DASH_RULE)


[grammar] ~145-~145: Please add a punctuation mark at the end of paragraph.
Context: ... - Use environment variables instead of prompts

(PUNCTUATION_PARAGRAPH_END)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Summary

Comment thread pkg/runner/step/spin.go Outdated

@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)
pkg/workflow/step/toast.go (1)

27-52: Solid implementation with clear level handling.

The case-insensitive level matching and sensible Info default provide good UX. The explicit handling of "warn" as an alias for "warning" is thoughtful.

Optional: Make empty string handling explicit

For clarity, you could explicitly handle the empty string case:

 	// Display based on level (default to info).
 	switch strings.ToLower(step.Level) {
 	case "success":
 		err = ui.Success(content)
 	case "warning", "warn":
 		err = ui.Warning(content)
 	case "error":
 		err = ui.Error(content)
-	default:
-		// Default to info for "", "info", or any other value.
+	case "", "info":
 		err = ui.Info(content)
+	default:
+		// Treat unknown levels as info.
+		err = ui.Info(content)
 	}

This makes the intent clearer that both empty and "info" are treated identically.

examples/demo-interactive-workflows/README.md (1)

125-145: Good coverage of output modes and CI considerations.

The output mode examples and CI guidance are practical.

Optional: Add missing period for consistency

Line 145 is missing a closing period:

 - Use `--dry-run` to preview workflows
 - Set default values in configuration
-- Use environment variables instead of prompts
+- Use environment variables instead of prompts.
pkg/workflow/step/executor_test.go (1)

33-41: Consider testing SetWorkflow behavior.

The test only verifies no panic occurs when calling SetWorkflow. Consider either testing that the workflow is actually stored/accessible or removing this test case if there's genuinely no observable behavior to verify.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5a30c93 and aa405ec.

📒 Files selected for processing (6)
  • examples/demo-interactive-workflows/README.md (1 hunks)
  • examples/demo-interactive-workflows/stacks/workflows/interactive.yaml (1 hunks)
  • pkg/workflow/step/executor_test.go (1 hunks)
  • pkg/workflow/step/pager.go (1 hunks)
  • pkg/workflow/step/toast.go (1 hunks)
  • pkg/workflow/step/ui_handlers_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/workflow/step/ui_handlers_test.go
  • examples/demo-interactive-workflows/stacks/workflows/interactive.yaml
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/toast.go
  • pkg/workflow/step/pager.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • pkg/workflow/step/executor_test.go
🧠 Learnings (13)
📓 Common learnings
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.
📚 Learning: 2025-12-13T06:10:25.156Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.

Applied to files:

  • pkg/workflow/step/executor_test.go
  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • pkg/workflow/step/executor_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/workflow/step/executor_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • pkg/workflow/step/executor_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • pkg/workflow/step/executor_test.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • pkg/workflow/step/executor_test.go
  • pkg/workflow/step/pager.go
  • examples/demo-interactive-workflows/README.md
📚 Learning: 2024-12-12T17:13:53.409Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 848
File: pkg/utils/doc_utils.go:19-22
Timestamp: 2024-12-12T17:13:53.409Z
Learning: In `pkg/utils/doc_utils.go`, the `DisplayDocs` function uses the `PAGER` environment variable, which is intentionally user-configurable to allow users to specify custom pager commands that fit their workflow; adding validation to restrict it is not desired.

Applied to files:

  • pkg/workflow/step/pager.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to README.md : Update README.md with new commands and features

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-11-07T14:52:55.217Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1761
File: docs/prd/claude-agent-architecture.md:331-439
Timestamp: 2025-11-07T14:52:55.217Z
Learning: In the cloudposse/atmos repository, Claude agents are used as interactive tools, not in automated/headless CI/CD contexts. Agent documentation and patterns should assume synchronous human interaction.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-10-11T19:11:58.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:0-0
Timestamp: 2025-10-11T19:11:58.965Z
Learning: For terraform apply interactivity checks in Atmos (internal/exec/terraform.go), use stdin TTY detection (e.g., `IsTTYSupportForStdin()` or checking `os.Stdin`) to determine if user prompts are possible. This is distinct from stdout/stderr TTY checks used for output display (like TUI rendering). User input requires stdin to be a TTY; output display requires stdout/stderr to be a TTY.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2024-11-12T13:06:56.194Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: website/docs/cheatsheets/vendoring.mdx:70-70
Timestamp: 2024-11-12T13:06:56.194Z
Learning: In `atmos vendor pull --everything`, the `--everything` flag uses the TTY for TUI but is not interactive.

Applied to files:

  • examples/demo-interactive-workflows/README.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • examples/demo-interactive-workflows/README.md
🧬 Code graph analysis (3)
pkg/workflow/step/executor_test.go (5)
pkg/workflow/step/executor.go (6)
  • NewStepExecutor (19-23)
  • NewStepExecutorWithVars (26-30)
  • IsExtendedStepType (134-149)
  • ValidateStep (152-167)
  • ValidateWorkflow (186-204)
  • ListTypes (170-183)
pkg/workflow/step/variables.go (2)
  • Variables (12-17)
  • NewVariables (20-28)
pkg/workflow/step/types.go (1)
  • NewStepResult (46-51)
pkg/schema/workflow.go (2)
  • WorkflowDefinition (78-88)
  • WorkflowStep (16-75)
pkg/workflow/step/registry.go (1)
  • Get (49-54)
pkg/workflow/step/toast.go (5)
pkg/workflow/step/handler_base.go (2)
  • BaseHandler (13-17)
  • NewBaseHandler (20-26)
pkg/workflow/step/types.go (1)
  • CategoryUI (12-12)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
pkg/workflow/step/variables.go (1)
  • Variables (12-17)
pkg/ui/formatter.go (2)
  • Success (193-200)
  • Warning (237-244)
pkg/workflow/step/pager.go (6)
pkg/workflow/step/registry.go (1)
  • Register (42-46)
pkg/workflow/step/types.go (2)
  • StepResult (32-43)
  • NewStepResult (46-51)
pkg/schema/workflow.go (1)
  • WorkflowStep (16-75)
pkg/pager/pager.go (1)
  • NewWithAtmosConfig (27-31)
pkg/ui/theme/converter.go (1)
  • GetGlamourStyleForTheme (255-263)
pkg/ui/theme/styles.go (1)
  • DefaultThemeName (11-11)
🪛 LanguageTool
examples/demo-interactive-workflows/README.md

[typographical] ~118-~118: To join two clauses or introduce examples, consider using an em dash.
Context: ...Variables - {{ .steps.<name>.value }} - Primary value from step - `{{ .steps.<na...

(DASH_RULE)


[grammar] ~145-~145: Please add a punctuation mark at the end of paragraph.
Context: ... - Use environment variables instead of prompts

(PUNCTUATION_PARAGRAPH_END)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (15)
pkg/workflow/step/toast.go (2)

11-20: LGTM—clean handler registration.

The ToastHandler correctly registers as CategoryUI with requiresTTY=false, making toast notifications available in both interactive and non-interactive contexts. The pattern aligns well with other UI step handlers.


22-25: Validation is appropriate.

Correctly enforces the content requirement using the base validation helper.

pkg/workflow/step/pager.go (5)

17-26: Proper registration as output category.

Correctly positioned under CategoryOutput with appropriate TTY requirements for a pager step.


28-35: Flexible validation for content sources.

Correctly allows either inline content or file path, covering both use cases.


37-63: Clean execution flow with graceful degradation.

The pipeline (load → render → display) is well-structured. Silently falling back to unrendered content when markdown rendering fails (line 46) provides good UX—the pager still works even if styling fails.


65-83: Well-structured content loading.

Cleanly handles both inline and file-based content sources. Returning the resolved path enables accurate markdown detection downstream.


101-140: Helper methods are well-implemented.

The markdown detection logic (explicit flag → extension auto-detect) provides good flexibility. Theme-aware rendering integrates nicely with Atmos styling. File reading has appropriate error context.

examples/demo-interactive-workflows/README.md (3)

1-23: Strong introduction with clear prerequisites.

The TTY requirement callout is helpful for users. Quick start commands provide immediate value.


25-80: Excellent workflow documentation.

The progression from simple (deploy) to complex (full-deploy) helps users learn incrementally. Each workflow's purpose is immediately clear.


81-124: Comprehensive reference for step types and variables.

The step types table provides quick lookup. The variable passing examples with Go templates are clear and practical. The available template variables list serves as a good reference.

pkg/workflow/step/executor_test.go (5)

89-125: Excellent table-driven test coverage.

Comprehensive coverage of legacy vs extended step types with clear test cases. Good use of table-driven pattern per coding guidelines.


172-219: Good workflow validation coverage.

The test cases cover validation scenarios comprehensively, including valid workflows, invalid steps, empty workflows, and generated step names. The approach of checking error count is appropriate for ValidateWorkflow's []error return type.


221-239: LGTM.

Test provides good coverage of the ListTypes functionality, verifying all categories and spot-checking expected types in each.


243-315: Strong integration test coverage for variable passing.

These tests effectively verify the variable passing mechanism between steps, covering value access, metadata, environment variables, multi-value scenarios, and state flags. The approach of simulating results is appropriate for testing variable resolution independently of handler execution.


330-346: LGTM.

Clean test of the fluent API pattern, verifying all chainable methods work correctly.

Comment thread pkg/runner/step/executor_test.go
Comment thread pkg/runner/step/executor_test.go
Comment thread pkg/runner/step/executor_test.go
Comment thread pkg/runner/step/pager.go
@mergify

mergify Bot commented Dec 22, 2025

Copy link
Copy Markdown
Contributor

💥 This pull request now has conflicts. Could you fix it Erik Osterman (Cloud Posse) (@osterman)? 🙏

@mergify mergify Bot added conflict This PR has conflicts and removed conflict This PR has conflicts labels Dec 22, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Dec 22, 2025
…de claims

Add docs/prd/custom-command-builtin-override.md specifying how a step-based
custom command can override a user-facing built-in (opt-in `override: true`)
and call the native built-in via an `invoke: built-in` step modifier on
`type: atmos` steps — cycle-proof by invoking the retained handler in-process
(no ATMOS_REEXEC_DEPTH counter).

Correct command-registry-pattern.md (Scenario 1 / Why This Works / FAQ) to
reflect shipped behavior since #2191 (built-in preserved, custom steps ignored
on collision) and document `invoke:` on the atmos step in workflow-step-types.md.

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

@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: 2

🤖 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 `@docs/prd/command-registry-pattern.md`:
- Around line 716-717: Update the "Nested custom commands → always added as
subcommands to parent" bullet to explicitly document collision behavior: state
that when a nested custom command name collides with an existing command the
registry reuses the existing command (does not create a new subcommand) and will
ignore/skip any custom `steps` from the colliding definition; reference this
collision behavior in the key behaviors section and add a short note advising
contributors to use unique names or explicitly override the existing command
through the registry API if they intend to replace steps.

In `@docs/prd/workflow-step-types.md`:
- Around line 1012-1014: The WorkflowStep schema block is missing the new invoke
field; update the WorkflowStep schema (the JSON/YAML schema object named
WorkflowStep) to include an "invoke" property (type: string, enum:
["exec","built-in"], default: "exec") with a short description matching the docs
text about exec vs built-in and note the default; also update any example
WorkflowStep definitions in the same doc to show the new invoke key so the
schema and examples remain consistent with the introduced invoke behavior.
🪄 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: 36d72d73-afa2-45a2-b04a-6496fcb0500e

📥 Commits

Reviewing files that changed from the base of the PR and between 619a845 and 6fe1336.

📒 Files selected for processing (3)
  • docs/prd/command-registry-pattern.md
  • docs/prd/custom-command-builtin-override.md
  • docs/prd/workflow-step-types.md

Comment thread docs/prd/command-registry-pattern.md Outdated
Comment thread docs/prd/workflow-step-types.md
Andriy Knysh (aknysh) and others added 5 commits May 29, 2026 23:03
…te tests

Address CodeRabbit feedback on PR #1899:
- command-registry-pattern.md: split the nested custom-command bullet to call
  out the name-collision case (findSubcommand reuses the existing command and
  ignores custom steps with a warning at every level, not just top-level).
- workflow-step-types.md: add the `invoke` field to the WorkflowStep schema
  block for consistency with the atmos step reference.

Increase pkg/runner/step coverage 78.9% -> 82.3% with hang-safe Execute tests:
- spin: full Execute orchestration (non-TTY runs the command directly).
- input/confirm/choose/write/filter/file: fail-fast Execute contract.
- pager: Execute error paths before the pager launches.
- atmos: Execute resolution errors before re-exec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add unit tests for the new workflow step-type subsystem to clear the
Codecov patch target (was 73.94%, target 80%).

- pkg/workflow/progress_test.go: inject a fake terminal.Terminal to cover
  formatProgressLine, renderers, Done/IsEnabled, and nil/disabled guards
  (8.6% -> ~100%).
- pkg/workflow/show_renderer_test.go: cover formatHeader, formatFlags
  (sort + styled/nil branches), and RenderHeaderIfNeeded paths (17% -> 100%).
- pkg/runner/step/interactive_execute_test.go: assert each interactive
  Execute returns ErrStepTTYRequired under go test (no TTY), covering the
  CheckTTY guard for confirm/write/input/choose/filter/file.
- pkg/runner/step/testmain_test.go + atmos_test.go: a sentinel-gated
  TestMain lets the test binary impersonate atmos so Execute,
  runAtmosCommand, and ExecuteWithWorkflow are tested cross-platform
  (0% -> ~85%).

Package coverage: pkg/workflow 76.5% -> 96.9%, pkg/runner/step 78.9% -> 82.3%.
No production code changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…o-atmos-workflows' into feature/dev-263-add-input-type-to-atmos-workflows

@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: 2

🤖 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 `@pkg/runner/step/interactive_execute_test.go`:
- Around line 27-39: TestInteractiveHandlers_ExecuteWithoutTTY can hang when
running from an interactive terminal; add a pre-check at the start of that test
(before calling handler.Execute or asserting errUtils.ErrStepTTYRequired) to
detect if both terminal.IsTTY(terminal.Stdin) and
terminal.IsTTY(terminal.Stdout) are true and skip the test in that case (use
t.Skip or equivalent), so the test exercises BaseHandler.CheckTTY and
handler.Execute safely without blocking on the interactive prompt.

In `@pkg/workflow/progress_test.go`:
- Line 16: Several multi-line comment lines in progress_test.go are missing
terminal periods; update each multi-line comment (e.g., the line "// Only Width
returns a configurable value; the remaining methods are no-ops" and the comments
at the other flagged locations) so every line ends with a period. Locate the
comment lines around the test functions in progress_test.go (including the lines
referenced at 32, 114, 172, 186) and append a period to the end of each comment
line so they comply with the godot linter.
🪄 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: 1522650b-65d3-4570-b0a5-d8219327a4e0

📥 Commits

Reviewing files that changed from the base of the PR and between aedcc8a and 13f468e.

📒 Files selected for processing (18)
  • docs/prd/command-registry-pattern.md
  • docs/prd/workflow-step-types.md
  • pkg/runner/step/atmos_test.go
  • pkg/runner/step/interactive_execute_test.go
  • pkg/runner/step/interactive_handlers_test.go
  • pkg/runner/step/pager_test.go
  • pkg/runner/step/spin_test.go
  • pkg/runner/step/testmain_test.go
  • pkg/workflow/progress_test.go
  • pkg/workflow/show_renderer_test.go
  • tests/snapshots/TestCLICommands_atmos_workflow_failure.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_on_shell_command.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_filepath.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_stack.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_invalid_step_type.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_shell_command_not_found.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_shell_pass.stderr.golden
  • tests/snapshots/TestCLICommands_workflow_retries_example.stderr.golden
✅ Files skipped from review due to trivial changes (8)
  • tests/snapshots/TestCLICommands_workflow_retries_example.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_invalid_step_type.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_stack.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_with_filepath.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_workflow_shell_command_not_found.stderr.golden
  • docs/prd/command-registry-pattern.md
  • tests/snapshots/TestCLICommands_atmos_workflow_failure_on_shell_command.stderr.golden
  • docs/prd/workflow-step-types.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/runner/step/pager_test.go
  • pkg/runner/step/spin_test.go

Comment thread pkg/runner/step/interactive_execute_test.go
Comment thread pkg/workflow/progress_test.go
Address CodeRabbit feedback on PR #1899: TestInteractiveHandlers_ExecuteWithoutTTY
asserts ErrStepTTYRequired, but CheckTTY only triggers when stdin or stdout is
not a TTY. Run from an interactive terminal (both TTYs), Execute would fall
through and block on the huh prompt, hanging the test. Add a pre-check that skips
in that case; the hang-proof sibling TestInteractiveHandlersExecuteFailFast
covers the TTY-present path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 30, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 30, 2026
The workflow executor printed the bare step label (e.g. "step1") to stderr
on every run when the progress bar was disabled, breaking backward
compatibility — the show.* features are documented as opt-in (default false).
Gate the label print on show.count so default output is unchanged while the
count feature still works in non-progress/non-TTY mode.

Also regenerate the workflow-retries snapshot to match the intended
WithExplanationf error formatting (## Explanation before ## Hints), and add
the invoke field to the WorkflowStep schema block in the PRD for consistency
with the documented exec/built-in behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 30, 2026
@atmos-pro

atmos-pro Bot commented May 30, 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 commented Jun 2, 2026

Copy link
Copy Markdown

These changes were released in v1.221.0-rc.2.

This branch was successfully deployed

1 active deployment
preview — d92c2b59 Deployed May 30, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/xxl

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants