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
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Unreleased

# Enhancements

## Enhancements
* Adds the `SpeculativeEnabled` field to the `StackCreateOptions` and `StackUpdateOptions` structs by @arunatibm [1279](https://github.com/hashicorp/go-tfe/pull/1279)
* Adds `Name` and `Provider` fields to `RegistryModuleCreateWithVCSConnectionOptions` to support explicit module naming for monorepos with non-standard repository names, by @jillirami [#1277](https://github.com/hashicorp/go-tfe/pull/1277)

# v1.100.0

Expand Down
8 changes: 8 additions & 0 deletions registry_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ type RegistryModuleCreateWithVCSConnectionOptions struct {
// https://jsonapi.org/format/#crud-creating
Type string `jsonapi:"primary,registry-modules"`

// Optional: The Name of the Module. If not provided, will be inferred from the VCS repository identifier.
// Required for monorepos with source_directory where the repository name doesn't follow the terraform-<provider>-<name> convention.
Name *string `jsonapi:"attr,name,omitempty"`

// Optional: The Name of the Provider. If not provided, will be inferred from the VCS repository identifier.
// Required for monorepos with source_directory where the repository name doesn't follow the terraform-<provider>-<name> convention.
Provider *string `jsonapi:"attr,provider,omitempty"`

// Required: VCS repository information
VCSRepo *RegistryModuleVCSRepoOptions `jsonapi:"attr,vcs-repo"`

Expand Down
150 changes: 150 additions & 0 deletions registry_module_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,156 @@ func TestRegistryModulesCreateMonorepoTagBasedWithVCSConnection(t *testing.T) {
})
}

func TestRegistryModulesCreateMonorepoNonStandardName(t *testing.T) {
t.Parallel()
skipUnlessBeta(t)

// This test uses a repository like "private-modules" or "monorepo" that doesn't
// follow the terraform-<provider>-<name> pattern, which would previously fail
// with "Name is invalid" error.
githubIdentifier := os.Getenv("GITHUB_REGISTRY_MODULE_IDENTIFIER")
if githubIdentifier == "" {
t.Skip("Export a valid GITHUB_REGISTRY_MODULE_IDENTIFIER before running this test")
}

githubBranch := os.Getenv("GITHUB_REGISTRY_MODULE_BRANCH")
if githubBranch == "" {
githubBranch = "main"
}

client := testClient(t)
ctx := context.Background()

orgTest, orgTestCleanup := createOrganization(t, client)
t.Cleanup(orgTestCleanup)

oauthTokenTest, oauthTokenTestCleanup := createOAuthToken(t, client, orgTest)
t.Cleanup(oauthTokenTestCleanup)

t.Run("with explicit name and provider for monorepo with tags", func(t *testing.T) {
sourceDirectory := "modules/nestedA"
moduleName := "nestedA"
moduleProvider := "aws"

options := RegistryModuleCreateWithVCSConnectionOptions{
Name: String(moduleName),
Provider: String(moduleProvider),
VCSRepo: &RegistryModuleVCSRepoOptions{
OrganizationName: String(orgTest.Name),
Identifier: String(githubIdentifier),
OAuthTokenID: String(oauthTokenTest.ID),
DisplayIdentifier: String(githubIdentifier),
SourceDirectory: String(sourceDirectory),
Tags: Bool(true),
},
}
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, moduleName, rm.Name)
assert.Equal(t, moduleProvider, rm.Provider)
assert.Equal(t, sourceDirectory, rm.VCSRepo.SourceDirectory)
assert.Equal(t, true, rm.VCSRepo.Tags)
})

t.Run("with explicit name and provider for monorepo with branch", func(t *testing.T) {
sourceDirectory := "modules/nestedB"
moduleName := "nestedB"
moduleProvider := "gcp"

options := RegistryModuleCreateWithVCSConnectionOptions{
Name: String(moduleName),
Provider: String(moduleProvider),
VCSRepo: &RegistryModuleVCSRepoOptions{
OrganizationName: String(orgTest.Name),
Identifier: String(githubIdentifier),
OAuthTokenID: String(oauthTokenTest.ID),
DisplayIdentifier: String(githubIdentifier),
Branch: String(githubBranch),
SourceDirectory: String(sourceDirectory),
},
}
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, moduleName, rm.Name)
assert.Equal(t, moduleProvider, rm.Provider)
assert.Equal(t, sourceDirectory, rm.VCSRepo.SourceDirectory)
assert.Equal(t, githubBranch, rm.VCSRepo.Branch)
assert.Equal(t, false, rm.VCSRepo.Tags)
})

t.Run("with explicit name and provider for deeply nested path", func(t *testing.T) {
sourceDirectory := "terraform/modules/aws/compute"
moduleName := "compute"
moduleProvider := "aws"

options := RegistryModuleCreateWithVCSConnectionOptions{
Name: String(moduleName),
Provider: String(moduleProvider),
VCSRepo: &RegistryModuleVCSRepoOptions{
OrganizationName: String(orgTest.Name),
Identifier: String(githubIdentifier),
OAuthTokenID: String(oauthTokenTest.ID),
DisplayIdentifier: String(githubIdentifier),
Branch: String(githubBranch),
SourceDirectory: String(sourceDirectory),
},
}
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, moduleName, rm.Name)
assert.Equal(t, moduleProvider, rm.Provider)
assert.Equal(t, sourceDirectory, rm.VCSRepo.SourceDirectory)
})

t.Run("with explicit name and provider for various providers", func(t *testing.T) {
testCases := []struct {
name string
moduleName string
moduleProvider string
sourceDirectory string
}{
{
name: "azurerm provider",
moduleName: "vnet",
moduleProvider: "azurerm",
sourceDirectory: "modules/azure-vnet",
},
{
name: "random provider",
moduleName: "pet",
moduleProvider: "random",
sourceDirectory: "modules/random-pet",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
options := RegistryModuleCreateWithVCSConnectionOptions{
Name: String(tc.moduleName),
Provider: String(tc.moduleProvider),
VCSRepo: &RegistryModuleVCSRepoOptions{
OrganizationName: String(orgTest.Name),
Identifier: String(githubIdentifier),
OAuthTokenID: String(oauthTokenTest.ID),
DisplayIdentifier: String(githubIdentifier),
Branch: String(githubBranch),
SourceDirectory: String(tc.sourceDirectory),
},
}
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, tc.moduleName, rm.Name)
assert.Equal(t, tc.moduleProvider, rm.Provider)
assert.Equal(t, tc.sourceDirectory, rm.VCSRepo.SourceDirectory)
})
}
})
}

func TestRegistryModulesCreateBranchBasedWithVCSConnectionWithTesting(t *testing.T) {
t.Parallel()
skipUnlessBeta(t)
Expand Down
Loading