diff --git a/internal/rpcapi/testdata/sourcebundle/action_invocations/action_invocations.tf b/internal/rpcapi/testdata/sourcebundle/action_invocations/action_invocations.tf new file mode 100644 index 0000000000..dbf571a4ee --- /dev/null +++ b/internal/rpcapi/testdata/sourcebundle/action_invocations/action_invocations.tf @@ -0,0 +1,26 @@ +terraform { + required_providers { + testing = { + source = "hashicorp/testing" + version = "0.1.0" + } + } +} + +resource "testing_resource" "this" { + id = "test" + value = "hello" + + lifecycle { + action_trigger { + events = [after_create] + actions = [action.testing_action.example] + } + } +} + +action "testing_action" "example" { + config { + message = "Test action invocation" + } +} diff --git a/internal/rpcapi/testdata/sourcebundle/action_invocations/action_invocations.tfcomponent.hcl b/internal/rpcapi/testdata/sourcebundle/action_invocations/action_invocations.tfcomponent.hcl new file mode 100644 index 0000000000..00ac98d1ca --- /dev/null +++ b/internal/rpcapi/testdata/sourcebundle/action_invocations/action_invocations.tfcomponent.hcl @@ -0,0 +1,15 @@ +required_providers { + testing = { + source = "hashicorp/testing" + version = "0.1.0" + } +} + +provider "testing" "default" {} + +component "self" { + source = "./" + providers = { + testing = provider.testing.default + } +} diff --git a/internal/rpcapi/testdata/sourcebundle/terraform-sources.json b/internal/rpcapi/testdata/sourcebundle/terraform-sources.json index 6421282d51..55b96909d0 100644 --- a/internal/rpcapi/testdata/sourcebundle/terraform-sources.json +++ b/internal/rpcapi/testdata/sourcebundle/terraform-sources.json @@ -45,6 +45,11 @@ "source": "git::https://example.com/empty.git", "local": "empty", "meta": {} + }, + { + "source": "git::https://example.com/action_invocations.git", + "local": "action_invocations", + "meta": {} } ] } diff --git a/internal/stacks/stackruntime/internal/stackeval/planning.go b/internal/stacks/stackruntime/internal/stackeval/planning.go index cbcb9d6ba5..3dc2c31b88 100644 --- a/internal/stacks/stackruntime/internal/stackeval/planning.go +++ b/internal/stacks/stackruntime/internal/stackeval/planning.go @@ -104,6 +104,11 @@ func ReportComponentInstance(ctx context.Context, plan *plans.Plan, h *Hooks, se }, }) } + + // Count action invocations + for range plan.Changes.ActionInvocations { + cic.ActionInvocation++ + } hookMore(ctx, seq, h.ReportComponentInstancePlanned, cic) } diff --git a/internal/stacks/stackruntime/testing/provider.go b/internal/stacks/stackruntime/testing/provider.go index 2359489bb6..cd30b4396b 100644 --- a/internal/stacks/stackruntime/testing/provider.go +++ b/internal/stacks/stackruntime/testing/provider.go @@ -113,6 +113,14 @@ var ( Nesting: configschema.NestingSingle, }, } + + TestingActionSchema = providers.ActionSchema{ + ConfigSchema: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "message": {Type: cty.String, Optional: true}, + }, + }, + } ) // MockProvider wraps the standard MockProvider with a simple in-memory @@ -223,6 +231,9 @@ func NewProviderWithData(t *testing.T, store *ResourceStore) *MockProvider { ReturnType: cty.DynamicPseudoType, }, }, + Actions: map[string]providers.ActionSchema{ + "testing_action": TestingActionSchema, + }, ServerCapabilities: providers.ServerCapabilities{ MoveResourceState: true, }, @@ -322,6 +333,29 @@ func NewProviderWithData(t *testing.T, store *ResourceStore) *MockProvider { }), } }, + PlanActionFn: func(request providers.PlanActionRequest) providers.PlanActionResponse { + // Simple action planning - no drift, just validation + return providers.PlanActionResponse{ + Diagnostics: tfdiags.Diagnostics{}, + } + }, + InvokeActionFn: func(request providers.InvokeActionRequest) providers.InvokeActionResponse { + // Simple action invocation - just emit a completed event + return providers.InvokeActionResponse{ + Events: func(yield func(providers.InvokeActionEvent) bool) { + yield(providers.InvokeActionEvent_Completed{ + Diagnostics: tfdiags.Diagnostics{}, + }) + }, + Diagnostics: tfdiags.Diagnostics{}, + } + }, + ValidateActionConfigFn: func(request providers.ValidateActionConfigRequest) providers.ValidateActionConfigResponse { + // No validation errors for testing actions + return providers.ValidateActionConfigResponse{ + Diagnostics: tfdiags.Diagnostics{}, + } + }, }, ResourceStore: store, }