Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/v1.15/BUG FIXES-20260105-170648.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'stacks: send progress events if the plan fails for better UI integration'
time: 2026-01-05T17:06:48.252069+01:00
custom:
Issue: "38039"
7 changes: 6 additions & 1 deletion internal/command/views/hook_count.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,15 @@ func (h *countHook) PostApply(id terraform.HookResourceIdentity, dk addrs.Depose
return terraform.HookActionContinue, nil
}

func (h *countHook) PostDiff(id terraform.HookResourceIdentity, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *countHook) PostDiff(id terraform.HookResourceIdentity, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value, err error) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()

// Skip counting if there was an error
if err != nil {
return terraform.HookActionContinue, nil
}

// We don't count anything for data resources
if id.Addr.Resource.Resource.Mode == addrs.DataResourceMode {
return terraform.HookActionContinue, nil
Expand Down
14 changes: 7 additions & 7 deletions internal/command/views/hook_count_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestCountHookPostDiff_DestroyDeposed(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), states.DeposedKey("deadbeef"), plans.Delete, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), states.DeposedKey("deadbeef"), plans.Delete, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down Expand Up @@ -77,7 +77,7 @@ func TestCountHookPostDiff_DestroyOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.Delete, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.Delete, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down Expand Up @@ -119,7 +119,7 @@ func TestCountHookPostDiff_AddOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.Create, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.Create, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down Expand Up @@ -164,7 +164,7 @@ func TestCountHookPostDiff_ChangeOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.Update, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.Update, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down Expand Up @@ -195,7 +195,7 @@ func TestCountHookPostDiff_Mixed(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, a, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, a, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down Expand Up @@ -227,7 +227,7 @@ func TestCountHookPostDiff_NoChange(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.NoOp, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, plans.NoOp, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down Expand Up @@ -259,7 +259,7 @@ func TestCountHookPostDiff_DataSource(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)

h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, a, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(testCountHookResourceID(addr), addrs.NotDeposed, a, cty.DynamicVal, cty.DynamicVal, nil)
}

expected := new(countHook)
Expand Down
29 changes: 20 additions & 9 deletions internal/rpcapi/stacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,9 @@ func (s *stacksServer) ApplyStackChanges(req *stacks.ApplyStackChanges_Request,
}
depsHnd := handle[*depsfile.Locks](req.DependencyLocksHandle)
var deps *depsfile.Locks
if !depsHnd.IsNil() {
if s.providerDependencyLockOverride != nil {
deps = s.providerDependencyLockOverride
} else if !depsHnd.IsNil() {
deps = s.handles.DependencyLocks(depsHnd)
if deps == nil {
return status.Error(codes.InvalidArgument, "the given dependency locks handle is invalid")
Expand All @@ -611,14 +613,23 @@ func (s *stacksServer) ApplyStackChanges(req *stacks.ApplyStackChanges_Request,
return status.Error(codes.InvalidArgument, "the given provider cache handle is invalid")
}
}
// NOTE: providerCache can be nil if no handle was provided, in which
// case the call can only use built-in providers. All code below
// must avoid panicking when providerCache is nil, but is allowed to
// return an InvalidArgument error in that case.
// (providerFactoriesForLocks explicitly supports a nil providerCache)
providerFactories, err := providerFactoriesForLocks(deps, providerCache)
if err != nil {
return status.Errorf(codes.InvalidArgument, "provider dependencies are inconsistent: %s", err)
var providerFactories map[addrs.Provider]providers.Factory
if s.providerCacheOverride != nil {
// This is only used in tests to side load providers without needing a
// real provider cache.
providerFactories = s.providerCacheOverride
} else {
// NOTE: providerCache can be nil if no handle was provided, in which
// case the call can only use built-in providers. All code below
// must avoid panicking when providerCache is nil, but is allowed to
// return an InvalidArgument error in that case.
// (providerFactoriesForLocks explicitly supports a nil providerCache)
var err error
// (providerFactoriesForLocks explicitly supports a nil providerCache)
providerFactories, err = providerFactoriesForLocks(deps, providerCache)
if err != nil {
return status.Errorf(codes.InvalidArgument, "provider dependencies are inconsistent: %s", err)
}
}

inputValues, err := externalInputValuesFromProto(req.InputValues)
Expand Down
Loading