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/unreleased/BUG FIXES-20260210-153921.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'helper/resource: Test steps in `Config` mode using the `TF_ACC_REFRESH_AFTER_APPLY` compatibility flag will now force post-apply plans to refresh.'
time: 2026-02-10T15:39:21.121944-05:00
custom:
Issue: "602"
6 changes: 6 additions & 0 deletions .changes/unreleased/BUG FIXES-20260210-154312.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: BUG FIXES
body: 'helper/resource: Test steps in `Config` mode using `Destroy: true` and `Check` functions will now create an additional destroy plan prior to
running `terraform apply` to avoid a potential "Saved Plan is Stale" error from Terraform.'
time: 2026-02-10T15:43:12.029656-05:00
custom:
Issue: "602"
5 changes: 5 additions & 0 deletions .changes/unreleased/BUG FIXES-20260210-154602.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'helper/resource: Test steps in `Config` mode using the `TF_ACC_REFRESH_AFTER_APPLY` compatibility flag will not refresh if `ExpectNonEmptyPlan` is true.'
time: 2026-02-10T15:46:02.221648-05:00
custom:
Issue: "602"
1 change: 1 addition & 0 deletions .github/workflows/ci-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
name: test (Go ${{ matrix.go-version }} / TF ${{ matrix.terraform }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
go-version: [ '1.25', '1.24' ]
terraform: ${{ fromJSON(vars.TF_VERSIONS_PROTOCOL_V5) }}
Expand Down
2 changes: 1 addition & 1 deletion helper/resource/testing_new_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint
return wd.CreatePlan(ctx, opts...)
})
if err != nil {
return fmt.Errorf("Error running pre-apply plan: %w", err)
return fmt.Errorf("Error running destroy plan after step.Check shimmed state was retrieved: %w", err)
}
}

Expand Down
56 changes: 56 additions & 0 deletions helper/resource/testing_new_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

Expand Down Expand Up @@ -906,3 +907,58 @@ func Test_PostApplyFunc_Called(t *testing.T) {
t.Error("expected ConfigStateChecks spy1 to be called at least once")
}
}

// This regression test ensures that the combination of Config, Destroy, and Check never result in
// a "Saved Plan is Stale" error message, which occurs when the state serial does not match the plan.
//
// This can occur when the refresh that is only done to produce the shimmed "Check" state produces a new state serial.
// Running a fresh plan after refreshing solves that issue, which was introduced in: https://github.com/hashicorp/terraform-plugin-testing/pull/602
func Test_Destroy_Checks_Avoid_Stale_Plan(t *testing.T) {
t.Parallel()

UnitTest(t, TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_0_0), // ProtoV6ProviderFactories
},
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
"test": providerserver.NewProviderServer(testprovider.Provider{
Resources: map[string]testprovider.Resource{
"test_resource": {
CreateResponse: &resource.CreateResponse{
NewState: tftypes.NewValue(
tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"id": tftypes.String,
},
},
map[string]tftypes.Value{
"id": tftypes.NewValue(tftypes.String, "test"),
},
),
},
SchemaResponse: &resource.SchemaResponse{
Schema: &tfprotov6.Schema{
Block: &tfprotov6.SchemaBlock{
Attributes: []*tfprotov6.SchemaAttribute{
{
Name: "id",
Type: tftypes.String,
Computed: true,
},
},
},
},
},
},
},
}),
},
Steps: []TestStep{
{
Config: `resource "test_resource" "test" {}`,
Destroy: true,
Check: func(s *terraform.State) error { return nil },
},
},
})
}
Loading