Skip to content

Commit fbbc953

Browse files
committed
Support name and provider when display identifier unconventional
1 parent 45476cf commit fbbc953

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Unreleased
22

3+
## Enhancements
4+
* 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)
5+
36
# v1.99.0
47

58
## Enhancements

registry_module.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ type RegistryModuleCreateWithVCSConnectionOptions struct {
345345
// https://jsonapi.org/format/#crud-creating
346346
Type string `jsonapi:"primary,registry-modules"`
347347

348+
// Optional: The name of the module. If not provided, will be inferred from the VCS repository identifier.
349+
// This is particularly useful for monorepos with source_directory where the repository name
350+
// doesn't follow the terraform-<provider>-<name> convention.
351+
Name *string `jsonapi:"attr,name,omitempty"`
352+
353+
// Optional: The provider name. If not provided, will be inferred from the VCS repository identifier.
354+
// This is particularly useful for monorepos with source_directory where the repository name
355+
// doesn't follow the terraform-<provider>-<name> convention.
356+
Provider *string `jsonapi:"attr,provider,omitempty"`
357+
348358
// Required: VCS repository information
349359
VCSRepo *RegistryModuleVCSRepoOptions `jsonapi:"attr,vcs-repo"`
350360

registry_module_integration_test.go

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,160 @@ func TestRegistryModulesCreateMonorepoTagBasedWithVCSConnection(t *testing.T) {
11981198
})
11991199
}
12001200

1201+
// TestRegistryModulesCreateMonorepoNonStandardName tests creating registry modules from
1202+
// a monorepo that doesn't follow the terraform-<provider>-<name> naming convention.
1203+
// This test validates the fix for the issue where explicit Name and Provider fields are
1204+
// required when using source_directory with non-standard repository names.
1205+
func TestRegistryModulesCreateMonorepoNonStandardName(t *testing.T) {
1206+
t.Parallel()
1207+
skipUnlessBeta(t)
1208+
1209+
// This test uses a repository like "private-modules" or "monorepo" that doesn't
1210+
// follow the terraform-<provider>-<name> pattern, which would previously fail
1211+
// with "Name is invalid" error.
1212+
githubIdentifier := os.Getenv("GITHUB_REGISTRY_MODULE_IDENTIFIER")
1213+
if githubIdentifier == "" {
1214+
t.Skip("Export a valid GITHUB_REGISTRY_MODULE_IDENTIFIER before running this test")
1215+
}
1216+
1217+
githubBranch := os.Getenv("GITHUB_REGISTRY_MODULE_BRANCH")
1218+
if githubBranch == "" {
1219+
githubBranch = "main"
1220+
}
1221+
1222+
client := testClient(t)
1223+
ctx := context.Background()
1224+
1225+
orgTest, orgTestCleanup := createOrganization(t, client)
1226+
t.Cleanup(orgTestCleanup)
1227+
1228+
oauthTokenTest, oauthTokenTestCleanup := createOAuthToken(t, client, orgTest)
1229+
t.Cleanup(oauthTokenTestCleanup)
1230+
1231+
t.Run("with explicit name and provider for monorepo with tags", func(t *testing.T) {
1232+
sourceDirectory := "modules/nestedA"
1233+
moduleName := "nestedA"
1234+
moduleProvider := "aws"
1235+
1236+
options := RegistryModuleCreateWithVCSConnectionOptions{
1237+
Name: String(moduleName),
1238+
Provider: String(moduleProvider),
1239+
VCSRepo: &RegistryModuleVCSRepoOptions{
1240+
OrganizationName: String(orgTest.Name),
1241+
Identifier: String(githubIdentifier),
1242+
OAuthTokenID: String(oauthTokenTest.ID),
1243+
DisplayIdentifier: String(githubIdentifier),
1244+
SourceDirectory: String(sourceDirectory),
1245+
Tags: Bool(true),
1246+
},
1247+
}
1248+
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
1249+
require.NoError(t, err)
1250+
assert.NotEmpty(t, rm.ID)
1251+
assert.Equal(t, moduleName, rm.Name)
1252+
assert.Equal(t, moduleProvider, rm.Provider)
1253+
assert.Equal(t, sourceDirectory, rm.VCSRepo.SourceDirectory)
1254+
assert.Equal(t, true, rm.VCSRepo.Tags)
1255+
})
1256+
1257+
t.Run("with explicit name and provider for monorepo with branch", func(t *testing.T) {
1258+
sourceDirectory := "modules/nestedB"
1259+
moduleName := "nestedB"
1260+
moduleProvider := "gcp"
1261+
1262+
options := RegistryModuleCreateWithVCSConnectionOptions{
1263+
Name: String(moduleName),
1264+
Provider: String(moduleProvider),
1265+
VCSRepo: &RegistryModuleVCSRepoOptions{
1266+
OrganizationName: String(orgTest.Name),
1267+
Identifier: String(githubIdentifier),
1268+
OAuthTokenID: String(oauthTokenTest.ID),
1269+
DisplayIdentifier: String(githubIdentifier),
1270+
Branch: String(githubBranch),
1271+
SourceDirectory: String(sourceDirectory),
1272+
},
1273+
}
1274+
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
1275+
require.NoError(t, err)
1276+
assert.NotEmpty(t, rm.ID)
1277+
assert.Equal(t, moduleName, rm.Name)
1278+
assert.Equal(t, moduleProvider, rm.Provider)
1279+
assert.Equal(t, sourceDirectory, rm.VCSRepo.SourceDirectory)
1280+
assert.Equal(t, githubBranch, rm.VCSRepo.Branch)
1281+
assert.Equal(t, false, rm.VCSRepo.Tags)
1282+
})
1283+
1284+
t.Run("with explicit name and provider for deeply nested path", func(t *testing.T) {
1285+
sourceDirectory := "terraform/modules/aws/compute"
1286+
moduleName := "compute"
1287+
moduleProvider := "aws"
1288+
1289+
options := RegistryModuleCreateWithVCSConnectionOptions{
1290+
Name: String(moduleName),
1291+
Provider: String(moduleProvider),
1292+
VCSRepo: &RegistryModuleVCSRepoOptions{
1293+
OrganizationName: String(orgTest.Name),
1294+
Identifier: String(githubIdentifier),
1295+
OAuthTokenID: String(oauthTokenTest.ID),
1296+
DisplayIdentifier: String(githubIdentifier),
1297+
Branch: String(githubBranch),
1298+
SourceDirectory: String(sourceDirectory),
1299+
},
1300+
}
1301+
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
1302+
require.NoError(t, err)
1303+
assert.NotEmpty(t, rm.ID)
1304+
assert.Equal(t, moduleName, rm.Name)
1305+
assert.Equal(t, moduleProvider, rm.Provider)
1306+
assert.Equal(t, sourceDirectory, rm.VCSRepo.SourceDirectory)
1307+
})
1308+
1309+
t.Run("with explicit name and provider for various providers", func(t *testing.T) {
1310+
testCases := []struct {
1311+
name string
1312+
moduleName string
1313+
moduleProvider string
1314+
sourceDirectory string
1315+
}{
1316+
{
1317+
name: "azurerm provider",
1318+
moduleName: "vnet",
1319+
moduleProvider: "azurerm",
1320+
sourceDirectory: "modules/azure-vnet",
1321+
},
1322+
{
1323+
name: "random provider",
1324+
moduleName: "pet",
1325+
moduleProvider: "random",
1326+
sourceDirectory: "modules/random-pet",
1327+
},
1328+
}
1329+
1330+
for _, tc := range testCases {
1331+
t.Run(tc.name, func(t *testing.T) {
1332+
options := RegistryModuleCreateWithVCSConnectionOptions{
1333+
Name: String(tc.moduleName),
1334+
Provider: String(tc.moduleProvider),
1335+
VCSRepo: &RegistryModuleVCSRepoOptions{
1336+
OrganizationName: String(orgTest.Name),
1337+
Identifier: String(githubIdentifier),
1338+
OAuthTokenID: String(oauthTokenTest.ID),
1339+
DisplayIdentifier: String(githubIdentifier),
1340+
Branch: String(githubBranch),
1341+
SourceDirectory: String(tc.sourceDirectory),
1342+
},
1343+
}
1344+
rm, err := client.RegistryModules.CreateWithVCSConnection(ctx, options)
1345+
require.NoError(t, err)
1346+
assert.NotEmpty(t, rm.ID)
1347+
assert.Equal(t, tc.moduleName, rm.Name)
1348+
assert.Equal(t, tc.moduleProvider, rm.Provider)
1349+
assert.Equal(t, tc.sourceDirectory, rm.VCSRepo.SourceDirectory)
1350+
})
1351+
}
1352+
})
1353+
}
1354+
12011355
func TestRegistryModulesCreateBranchBasedWithVCSConnectionWithTesting(t *testing.T) {
12021356
t.Parallel()
12031357
skipUnlessBeta(t)

0 commit comments

Comments
 (0)