diff --git a/.github/actions/test-go-tfe/action.yml b/.github/actions/test-go-tfe/action.yml index 34ec1b28c..19081eea3 100644 --- a/.github/actions/test-go-tfe/action.yml +++ b/.github/actions/test-go-tfe/action.yml @@ -110,6 +110,8 @@ runs: GITHUB_POLICY_SET_IDENTIFIER: "svc-team-tf-core-cloud/test-policy-set" GITHUB_REGISTRY_MODULE_IDENTIFIER: "svc-team-tf-core-cloud/terraform-random-module" GITHUB_REGISTRY_NO_CODE_MODULE_IDENTIFIER: "hashicorp/terraform-random-no-code-module" + GITHUB_STACK_IDENTIFIER: "svc-team-tf-core-cloud/tf-stacks-pet-nulls" + GITHUB_STACK_REPO_BRANCH: "diags" OAUTH_CLIENT_GITHUB_TOKEN: "${{ inputs.oauth-client-github-token }}" SKIP_HYOK_INTEGRATION_TESTS: "${{ inputs.skip-hyok-integration-tests }}" HYOK_ORGANIZATION_NAME: "${{ inputs.hyok-organization-name }}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 3acf0f87b..f93050d0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ ## Enhancements * Adds the `Size` field to `StateVersion` by @shaunakone [#1280](https://github.com/hashicorp/go-tfe/pull/1280) * Upgrade go version from `1.24` to `1.25` by @uk1288 [#1297](https://github.com/hashicorp/go-tfe/pull/1297) +* Unskip stacks integration tests and remove diagnostics#acknowledge in preparation for stacks tfe release by @aaabdelgany [#1298](https://github.com/hashicorp/go-tfe/pull/1298) # v1.101.0 diff --git a/docs/TESTS.md b/docs/TESTS.md index d2830da45..b913c7a6c 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -56,6 +56,8 @@ Tests are run against an actual backend so they require a valid backend address $ GITHUB_APP_INSTALLATION_ID=ghain-xxxx TFE_ADDRESS= https://tfe.local TFE_TOKEN=xxx GITHUB_POLICY_SET_IDENTIFIER=username/repository GITHUB_REGISTRY_MODULE_IDENTIFIER=username/repository go test -run "(GHA|GithubApp)" -v ./... ``` 8. `GITHUB_REGISTRY_NO_CODE_MODULE_IDENTIFIER` - Required for running tests for workspaces using no-code modules. +9. `GITHUB_STACK_IDENTIFIER` - Required for running tests against vcs backed stacks. +10. `GITHUB_STACK_REPO_BRANCH` - Required for running tests against specific branches of vcs backed stacks. ## 3. Make sure run queue settings are correct diff --git a/stack_configuration_integration_test.go b/stack_configuration_integration_test.go index d5ef55383..f681591f2 100644 --- a/stack_configuration_integration_test.go +++ b/stack_configuration_integration_test.go @@ -14,7 +14,6 @@ import ( func TestStackConfigurationList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -28,7 +27,7 @@ func TestStackConfigurationList(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack-list", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -82,7 +81,6 @@ func TestStackConfigurationList(t *testing.T) { func TestStackConfigurationCreateUploadAndRead(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -127,7 +125,6 @@ func TestStackConfigurationCreateUploadAndRead(t *testing.T) { func TestStackConfigurationDiagnostics(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -144,9 +141,9 @@ func TestStackConfigurationDiagnostics(t *testing.T) { Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "ctrombley/linked-stacks-demo-network", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, - Branch: "diagnostics", // This branch will produce diagnostics + Branch: stackVCSRepoBranch(t), }, }) require.NoError(t, err) @@ -174,13 +171,10 @@ func TestStackConfigurationDiagnostics(t *testing.T) { assert.NotEmpty(t, diag.Summary) assert.NotEmpty(t, diag.Detail) assert.NotEmpty(t, diag.Diags) - assert.False(t, diag.Acknowledged) - assert.Nil(t, diag.AcknowledgedAt) assert.NotZero(t, diag.CreatedAt) assert.Nil(t, diag.StackDeploymentStep) assert.NotNil(t, diag.StackConfiguration) - assert.Nil(t, diag.AcknowledgedBy) }) t.Run("Diagnostics with invalid ID", func(t *testing.T) { diff --git a/stack_configuration_summary_integration_test.go b/stack_configuration_summary_integration_test.go index 40301fd8c..a72491561 100644 --- a/stack_configuration_summary_integration_test.go +++ b/stack_configuration_summary_integration_test.go @@ -14,7 +14,6 @@ import ( func TestStackConfigurationSummaryList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -28,7 +27,7 @@ func TestStackConfigurationSummaryList(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "aa-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -40,7 +39,7 @@ func TestStackConfigurationSummaryList(t *testing.T) { stack2, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "bb-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ diff --git a/stack_deployment_groups_integration_test.go b/stack_deployment_groups_integration_test.go index 4a835258f..c160248d0 100644 --- a/stack_deployment_groups_integration_test.go +++ b/stack_deployment_groups_integration_test.go @@ -13,7 +13,6 @@ import ( func TestStackDeploymentGroupsList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -27,7 +26,7 @@ func TestStackDeploymentGroupsList(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -80,7 +79,6 @@ func TestStackDeploymentGroupsList(t *testing.T) { func TestStackDeploymentGroupsRead(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -94,7 +92,7 @@ func TestStackDeploymentGroupsRead(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -133,7 +131,6 @@ func TestStackDeploymentGroupsRead(t *testing.T) { func TestStackDeploymentGroupsApproveAllPlans(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -147,7 +144,7 @@ func TestStackDeploymentGroupsApproveAllPlans(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -181,7 +178,6 @@ func TestStackDeploymentGroupsApproveAllPlans(t *testing.T) { func TestStackDeploymentGroupsRerun(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -195,7 +191,7 @@ func TestStackDeploymentGroupsRerun(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, diff --git a/stack_deployment_groups_summary_integration_test.go b/stack_deployment_groups_summary_integration_test.go index 0b4b74cca..faed5addb 100644 --- a/stack_deployment_groups_summary_integration_test.go +++ b/stack_deployment_groups_summary_integration_test.go @@ -13,7 +13,6 @@ import ( func TestStackDeploymentGroupSummaryList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -27,7 +26,7 @@ func TestStackDeploymentGroupSummaryList(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "aa-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -39,7 +38,7 @@ func TestStackDeploymentGroupSummaryList(t *testing.T) { stack2, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "bb-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ diff --git a/stack_deployment_integration_test.go b/stack_deployment_integration_test.go index 6d0f38711..9901315cb 100644 --- a/stack_deployment_integration_test.go +++ b/stack_deployment_integration_test.go @@ -9,7 +9,6 @@ import ( func TestStackDeploymentsList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -23,7 +22,7 @@ func TestStackDeploymentsList(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "aa-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ diff --git a/stack_deployment_runs_integration_test.go b/stack_deployment_runs_integration_test.go index 97111a300..5fe7ca195 100644 --- a/stack_deployment_runs_integration_test.go +++ b/stack_deployment_runs_integration_test.go @@ -14,7 +14,6 @@ import ( func TestStackDeploymentRunsList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -28,7 +27,7 @@ func TestStackDeploymentRunsList(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -99,7 +98,6 @@ func TestStackDeploymentRunsList(t *testing.T) { func TestStackDeploymentRunsRead(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -114,7 +112,7 @@ func TestStackDeploymentRunsRead(t *testing.T) { Project: orgTest.DefaultProject, Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -171,7 +169,6 @@ func TestStackDeploymentRunsRead(t *testing.T) { func TestStackDeploymentRunsApproveAllPlans(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -186,7 +183,7 @@ func TestStackDeploymentRunsApproveAllPlans(t *testing.T) { Project: orgTest.DefaultProject, Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -225,7 +222,6 @@ func TestStackDeploymentRunsApproveAllPlans(t *testing.T) { func TestStackDeploymentRunsCancel(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -240,7 +236,7 @@ func TestStackDeploymentRunsCancel(t *testing.T) { Project: orgTest.DefaultProject, Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, diff --git a/stack_deployment_steps_integration_test.go b/stack_deployment_steps_integration_test.go index 2051c27e9..7acf2528a 100644 --- a/stack_deployment_steps_integration_test.go +++ b/stack_deployment_steps_integration_test.go @@ -15,7 +15,6 @@ import ( func TestStackDeploymentStepsList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -30,7 +29,7 @@ func TestStackDeploymentStepsList(t *testing.T) { Project: orgTest.DefaultProject, Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -68,8 +67,9 @@ func TestStackDeploymentStepsList(t *testing.T) { t.Parallel() steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, nil) - assert.NoError(t, err) - assert.NotEmpty(t, steps) + require.NoError(t, err) + require.NotNil(t, steps) + require.NotEmpty(t, steps.Items) step := steps.Items[0] @@ -90,8 +90,9 @@ func TestStackDeploymentStepsList(t *testing.T) { PageSize: 10, }, }) - assert.NoError(t, err) - assert.NotEmpty(t, steps) + require.NoError(t, err) + require.NotNil(t, steps) + require.NotEmpty(t, steps.Items) step := steps.Items[0] @@ -106,7 +107,6 @@ func TestStackDeploymentStepsList(t *testing.T) { func TestStackDeploymentStepsRead(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -121,7 +121,7 @@ func TestStackDeploymentStepsRead(t *testing.T) { Project: orgTest.DefaultProject, Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -148,9 +148,7 @@ func TestStackDeploymentStepsRead(t *testing.T) { sdr := stackDeploymentRuns.Items[0] - steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, nil) - assert.NoError(t, err) - assert.NotEmpty(t, steps) + steps := pollStackDeploymentSteps(t, ctx, client, sdr.ID) step := steps.Items[0] @@ -170,7 +168,6 @@ func TestStackDeploymentStepsRead(t *testing.T) { func TestStackDeploymentStepsAdvance(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -185,7 +182,7 @@ func TestStackDeploymentStepsAdvance(t *testing.T) { Project: orgTest.DefaultProject, Name: "testing-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -212,9 +209,7 @@ func TestStackDeploymentStepsAdvance(t *testing.T) { sdr := stackDeploymentRuns.Items[0] - steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, nil) - assert.NoError(t, err) - assert.NotEmpty(t, steps) + steps := pollStackDeploymentSteps(t, ctx, client, sdr.ID) step := steps.Items[0] step = pollStackDeploymentStepStatus(t, ctx, client, step.ID, "pending_operator") @@ -227,7 +222,7 @@ func TestStackDeploymentStepsAdvance(t *testing.T) { // Verify that the step status has changed to "completed" sds, err := client.StackDeploymentSteps.Read(ctx, step.ID) assert.NoError(t, err) - assert.Equal(t, "completed", sds.Status) + assert.Equal(t, DeploymentStepStatusCompleted, sds.Status) }) t.Run("Advance with invalid ID", func(t *testing.T) { @@ -237,6 +232,8 @@ func TestStackDeploymentStepsAdvance(t *testing.T) { } func pollStackDeploymentStepStatus(t *testing.T, ctx context.Context, client *Client, stackDeploymentStepID, status string) (deploymentStep *StackDeploymentStep) { + t.Helper() + // pollStackDeploymentStepStatus will poll the given stack deployment step until its status changes or the deadline is reached. ctx, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) defer cancel() @@ -271,7 +268,6 @@ func pollStackDeploymentStepStatus(t *testing.T, ctx context.Context, client *Cl func TestStackDeploymentStepsDiagnosticsArtifacts(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -288,7 +284,7 @@ func TestStackDeploymentStepsDiagnosticsArtifacts(t *testing.T) { Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -314,9 +310,7 @@ func TestStackDeploymentStepsDiagnosticsArtifacts(t *testing.T) { require.NotEmpty(t, stackDeploymentRuns) sdr := stackDeploymentRuns.Items[0] - steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, nil) - assert.NoError(t, err) - assert.NotEmpty(t, steps) + steps := pollStackDeploymentSteps(t, ctx, client, sdr.ID) step := steps.Items[0] step = pollStackDeploymentStepStatus(t, ctx, client, step.ID, "pending_operator") diff --git a/stack_diagnostic.go b/stack_diagnostic.go index d1e251ddf..86bcedd2a 100644 --- a/stack_diagnostic.go +++ b/stack_diagnostic.go @@ -11,10 +11,8 @@ import ( ) type StackDiagnostics interface { - // Read retrieves a stack diagnostic by its ID. + // Read retrieves a stack diagnostic associated with a stack configuration by its ID. Read(ctx context.Context, stackConfigurationID string) (*StackDiagnostic, error) - // Acknowledge marks a diagnostic as acknowledged. - Acknowledge(ctx context.Context, stackDiagnosticID string) error } // StackDiagnostic represents any sourcebundle.Diagnostic value. The simplest form has @@ -22,19 +20,16 @@ type StackDiagnostics interface { // information about the source of the diagnostic, this is represented in the // range field. type StackDiagnostic struct { - ID string `jsonapi:"primary,stack-diagnostics"` - Severity string `jsonapi:"attr,severity"` - Summary string `jsonapi:"attr,summary"` - Detail string `jsonapi:"attr,detail"` - Diags []*StackDiagnosticSummary `jsonapi:"attr,diags"` - Acknowledged bool `jsonapi:"attr,acknowledged"` - AcknowledgedAt *time.Time `jsonapi:"attr,acknowledged-at,iso8601"` - CreatedAt *time.Time `jsonapi:"attr,created-at,iso8601"` + ID string `jsonapi:"primary,stack-diagnostics"` + Severity string `jsonapi:"attr,severity"` + Summary string `jsonapi:"attr,summary"` + Detail string `jsonapi:"attr,detail"` + Diags []*StackDiagnosticSummary `jsonapi:"attr,diags"` + CreatedAt *time.Time `jsonapi:"attr,created-at,iso8601"` // Relationships StackDeploymentStep *StackDeploymentStep `jsonapi:"relation,stack-deployment-step"` StackConfiguration *StackConfiguration `jsonapi:"relation,stack-configuration"` - AcknowledgedBy *User `jsonapi:"relation,acknowledged-by"` } type StackDiagnosticSummary struct { @@ -110,18 +105,3 @@ func (s stackDiagnostics) Read(ctx context.Context, stackDiagnosticID string) (* return &diagnostics, nil } - -// Acknowledge marks a diagnostic as acknowledged. -func (s stackDiagnostics) Acknowledge(ctx context.Context, stackDiagnosticID string) error { - req, err := s.client.NewRequest("POST", fmt.Sprintf("stack-diagnostics/%s/acknowledge", url.PathEscape(stackDiagnosticID)), nil) - if err != nil { - return err - } - - diagnostic := StackDiagnostic{} - if err := req.Do(ctx, &diagnostic); err != nil { - return err - } - - return nil -} diff --git a/stack_diagnostic_integration_test.go b/stack_diagnostic_integration_test.go index b18c33dbe..d817da37b 100644 --- a/stack_diagnostic_integration_test.go +++ b/stack_diagnostic_integration_test.go @@ -8,9 +8,8 @@ import ( "github.com/stretchr/testify/require" ) -func TestStackDiagnosticsReadAcknowledge(t *testing.T) { +func TestStackDiagnosticsRead(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -24,8 +23,8 @@ func TestStackDiagnosticsReadAcknowledge(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "cc-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "ctrombley/linked-stacks-demo-network", - Branch: "diagnostics", + Identifier: stackVCSRepoIdentifier(t), + Branch: stackVCSRepoBranch(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -50,75 +49,39 @@ func TestStackDiagnosticsReadAcknowledge(t *testing.T) { assert.NoError(t, err) require.NotEmpty(t, diags.Items) - diag := diags.Items[0] + expectedDiag := diags.Items[0] t.Run("Read with valid ID", func(t *testing.T) { - diag, err := client.StackDiagnostics.Read(ctx, diag.ID) + diag, err := client.StackDiagnostics.Read(ctx, expectedDiag.ID) require.NoError(t, err) assert.NotNil(t, diag) - assert.NotEmpty(t, diag.ID) - assert.NotEmpty(t, diag.Severity) - assert.NotEmpty(t, diag.Summary) - assert.NotEmpty(t, diag.Detail) - assert.NotEmpty(t, diag.Diags) - - for _, d := range diag.Diags { - assert.NotEmpty(t, d.Detail) - assert.NotEmpty(t, d.Severity) - assert.NotEmpty(t, d.Summary) - assert.Empty(t, d.Origin) - - require.NotNil(t, d.Range) - assert.NotEmpty(t, d.Range.Filename) - assert.NotEmpty(t, d.Range.Source) - - require.NotNil(t, d.Range.Start) - assert.NotZero(t, d.Range.Start.Line) - assert.NotZero(t, d.Range.Start.Column) - assert.NotZero(t, d.Range.Start.Byte) - - require.NotNil(t, d.Range.End) - assert.NotZero(t, d.Range.End.Line) - assert.NotZero(t, d.Range.End.Column) - assert.NotZero(t, d.Range.End.Byte) - - require.NotNil(t, d.Snippet) - assert.NotEmpty(t, d.Snippet.Code) - assert.Empty(t, d.Snippet.Values) - assert.Nil(t, d.Snippet.Context) - assert.Zero(t, d.Snippet.HighlightStartOffset) - assert.NotZero(t, d.Snippet.HighlightEndOffset) + assert.Equal(t, expectedDiag.ID, diag.ID) + assert.Equal(t, expectedDiag.Severity, diag.Severity) + assert.Equal(t, expectedDiag.Summary, diag.Summary) + assert.Equal(t, expectedDiag.Detail, diag.Detail) + assert.Equal(t, expectedDiag.CreatedAt, diag.CreatedAt) + require.Len(t, diag.Diags, len(expectedDiag.Diags)) + + for i, d := range diag.Diags { + expectedNestedDiag := expectedDiag.Diags[i] + assert.Equal(t, expectedNestedDiag.Severity, d.Severity) + assert.Equal(t, expectedNestedDiag.Summary, d.Summary) + assert.Equal(t, expectedNestedDiag.Detail, d.Detail) + assert.Equal(t, expectedNestedDiag.Origin, d.Origin) + assert.Equal(t, expectedNestedDiag.Range, d.Range) + assert.Equal(t, expectedNestedDiag.Snippet, d.Snippet) } - assert.False(t, diag.Acknowledged) - assert.Nil(t, diag.AcknowledgedAt) assert.NotZero(t, diag.CreatedAt) - - assert.Nil(t, diag.StackDeploymentStep) - assert.NotNil(t, diag.StackConfiguration) - assert.Nil(t, diag.AcknowledgedBy) + assert.Equal(t, expectedDiag.StackDeploymentStep, diag.StackDeploymentStep) + require.NotNil(t, diag.StackConfiguration) + require.NotNil(t, expectedDiag.StackConfiguration) + assert.Equal(t, expectedDiag.StackConfiguration.ID, diag.StackConfiguration.ID) }) t.Run("Read with invalid ID", func(t *testing.T) { _, err := client.StackDiagnostics.Read(ctx, "") require.Error(t, err) }) - - t.Run("Acknowledge with valid ID", func(t *testing.T) { - err := client.StackDiagnostics.Acknowledge(ctx, diag.ID) - require.NoError(t, err) - - diag, err := client.StackDiagnostics.Read(ctx, diag.ID) - require.NoError(t, err) - assert.NotNil(t, diag) - assert.True(t, diag.Acknowledged) - assert.NotNil(t, diag.AcknowledgedAt) - assert.NotNil(t, diag.AcknowledgedBy) - }) - - t.Run("Acknowledge with invalid ID", func(t *testing.T) { - err := client.StackDiagnostics.Acknowledge(ctx, "") - require.Error(t, err) - }) } diff --git a/stack_integration_test.go b/stack_integration_test.go index 8239fc713..c2a87d8ef 100644 --- a/stack_integration_test.go +++ b/stack_integration_test.go @@ -14,7 +14,6 @@ import ( func TestStackCreateAndList(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -33,7 +32,7 @@ func TestStackCreateAndList(t *testing.T) { stack1, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "aa-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -50,7 +49,7 @@ func TestStackCreateAndList(t *testing.T) { stack2, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "zz-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -138,7 +137,6 @@ func TestStackCreateAndList(t *testing.T) { func TestStackReadUpdateDelete(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -157,7 +155,7 @@ func TestStackReadUpdateDelete(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -196,7 +194,7 @@ func TestStackReadUpdateDelete(t *testing.T) { stackUpdated, err := client.Stacks.Update(ctx, stack.ID, StackUpdateOptions{ Description: String("updated description"), VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -227,7 +225,6 @@ func TestStackReadUpdateDelete(t *testing.T) { func TestStackRemoveVCSBacking(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -241,7 +238,7 @@ func TestStackRemoveVCSBacking(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -274,7 +271,6 @@ func TestStackRemoveVCSBacking(t *testing.T) { func TestStackReadUpdateForceDelete(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -288,7 +284,7 @@ func TestStackReadUpdateForceDelete(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -314,7 +310,7 @@ func TestStackReadUpdateForceDelete(t *testing.T) { stackUpdated, err := client.Stacks.Update(ctx, stack.ID, StackUpdateOptions{ Description: String("updated description"), VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, Branch: "main", }, @@ -440,6 +436,45 @@ func pollStackDeploymentRunStatus(t *testing.T, ctx context.Context, client *Cli } } +func pollStackDeploymentSteps(t *testing.T, ctx context.Context, client *Client, stackDeploymentRunID string) (steps *StackDeploymentStepList) { + t.Helper() + + ctx, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) + defer cancel() + + deadline, _ := ctx.Deadline() + t.Logf("Polling stack deployment run %q for deployment steps with deadline of %s", stackDeploymentRunID, deadline) + + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + + for finished := false; !finished; { + t.Log("...") + select { + case <-ctx.Done(): + t.Fatalf("Stack deployment run %q had no deployment steps at deadline", stackDeploymentRunID) + case <-ticker.C: + var err error + steps, err = client.StackDeploymentSteps.List(ctx, stackDeploymentRunID, nil) + if err != nil { + t.Fatalf("Failed to read stack deployment steps for run %q: %s", stackDeploymentRunID, err) + } + + count := 0 + if steps != nil { + count = len(steps.Items) + } + + t.Logf("Stack deployment run %q had %d deployment steps", stackDeploymentRunID, count) + if count > 0 { + finished = true + } + } + } + + return steps +} + func pollStackConfigurationStatus(t *testing.T, ctx context.Context, client *Client, stackConfigID, status string) (stackConfig *StackConfiguration) { // pollStackDeployments will poll the given stack until it has deployments or the deadline is reached. ctx, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) diff --git a/stack_state_integration_test.go b/stack_state_integration_test.go index 64730d90a..4b561b72a 100644 --- a/stack_state_integration_test.go +++ b/stack_state_integration_test.go @@ -11,7 +11,6 @@ import ( func TestStackStateListReadDescription(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -22,7 +21,7 @@ func TestStackStateListReadDescription(t *testing.T) { stack, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "aa-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -34,7 +33,7 @@ func TestStackStateListReadDescription(t *testing.T) { stack2, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "bb-test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -90,19 +89,14 @@ func TestStackStateListReadDescription(t *testing.T) { assert.NotEmpty(t, state.ID) - // Assert attribute presence - assert.NotZero(t, state.Generation) + // Assert consistently populated attributes. assert.NotEmpty(t, state.Status) - assert.NotEmpty(t, state.Deployment) - assert.NotNil(t, state.Components) assert.True(t, state.IsCurrent) - assert.NotZero(t, state.ResourceInstanceCount) // Assert relationship presence assert.NotNil(t, state.Stack) assert.NotEmpty(t, state.Stack.ID) - assert.NotNil(t, state.StackDeploymentRun) - assert.NotEmpty(t, state.StackDeploymentRun) + assert.NotEmpty(t, state.StackDeploymentRun.ID) // Assert link presence assert.NotEmpty(t, state.Links) diff --git a/stack_test_helpers_test.go b/stack_test_helpers_test.go new file mode 100644 index 000000000..521686d7a --- /dev/null +++ b/stack_test_helpers_test.go @@ -0,0 +1,29 @@ +// Copyright IBM Corp. 2018, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package tfe + +import ( + "os" + "testing" +) + +func stackVCSRepoIdentifier(t *testing.T) string { + t.Helper() + + githubIdentifier := os.Getenv("GITHUB_STACK_IDENTIFIER") + if githubIdentifier == "" { + t.Skip("Export a valid GITHUB_STACK_IDENTIFIER before running this test") + } + + return githubIdentifier +} + +func stackVCSRepoBranch(t *testing.T) string { + githubBranch := os.Getenv("GITHUB_STACK_REPO_BRANCH") + if githubBranch == "" { + return "main" + } + + return githubBranch +} diff --git a/variable_set_test.go b/variable_set_test.go index 543c12624..306218b79 100644 --- a/variable_set_test.go +++ b/variable_set_test.go @@ -572,8 +572,6 @@ func TestVariableSetsApplyToAndRemoveFromProjects(t *testing.T) { } func TestVariableSetsApplyToAndRemoveFromStacks(t *testing.T) { - skipUnlessBeta(t) - client := testClient(t) ctx := context.Background() @@ -589,7 +587,7 @@ func TestVariableSetsApplyToAndRemoveFromStacks(t *testing.T) { stackTest1, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack-1", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -610,7 +608,7 @@ func TestVariableSetsApplyToAndRemoveFromStacks(t *testing.T) { stackTest2, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack-2", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{ @@ -749,7 +747,6 @@ func TestVariableSetsUpdateWorkspaces(t *testing.T) { func TestVariableSetsUpdateStacks(t *testing.T) { t.Parallel() - skipUnlessBeta(t) client := testClient(t) ctx := context.Background() @@ -766,7 +763,7 @@ func TestVariableSetsUpdateStacks(t *testing.T) { stackTest, err := client.Stacks.Create(ctx, StackCreateOptions{ Name: "test-stack", VCSRepo: &StackVCSRepoOptions{ - Identifier: "hashicorp-guides/pet-nulls-stack", + Identifier: stackVCSRepoIdentifier(t), OAuthTokenID: oauthClient.OAuthTokens[0].ID, }, Project: &Project{