refactor: improve module source URL validation
- Use more specific regex pattern [a-zA-Z0-9-]+ instead of [^/]+ for namespace/module names - Process all Terraform blocks instead of just the first one - Report correct source if found in any block, only report incorrect sources if no correct source exists - Add comprehensive test cases for multiple Terraform blocks Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
This commit is contained in:
parent
9cc3d5a776
commit
343a2f2bb8
@ -12,7 +12,7 @@ import (
|
||||
var (
|
||||
// Matches Terraform source lines with registry.coder.com URLs
|
||||
// Pattern: source = "registry.coder.com/namespace/module/coder"
|
||||
terraformSourceRe = regexp.MustCompile(`^\s*source\s*=\s*"` + registryDomain + `/([^/]+)/([^/]+)/coder"`)
|
||||
terraformSourceRe = regexp.MustCompile(`^\s*source\s*=\s*"` + registryDomain + `/([a-zA-Z0-9-]+)/([a-zA-Z0-9-]+)/coder"`)
|
||||
)
|
||||
|
||||
func validateModuleSourceURL(rm coderResourceReadme) []error {
|
||||
@ -27,6 +27,7 @@ func validateModuleSourceURL(rm coderResourceReadme) []error {
|
||||
|
||||
trimmed := strings.TrimSpace(rm.body)
|
||||
foundCorrectSource := false
|
||||
var incorrectSources []string
|
||||
isInsideTerraform := false
|
||||
|
||||
lineScanner := bufio.NewScanner(strings.NewReader(trimmed))
|
||||
@ -39,7 +40,8 @@ func validateModuleSourceURL(rm coderResourceReadme) []error {
|
||||
continue
|
||||
}
|
||||
if isInsideTerraform {
|
||||
break
|
||||
// End of current terraform block, continue to look for more
|
||||
isInsideTerraform = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -48,26 +50,34 @@ func validateModuleSourceURL(rm coderResourceReadme) []error {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check for source line in the first terraform block
|
||||
// Check for source line in terraform blocks
|
||||
if matches := terraformSourceRe.FindStringSubmatch(nextLine); matches != nil {
|
||||
actualNamespace := matches[1]
|
||||
actualModule := matches[2]
|
||||
actualSource := registryDomain + "/" + actualNamespace + "/" + actualModule + "/coder"
|
||||
|
||||
|
||||
if actualSource == expectedSource {
|
||||
foundCorrectSource = true
|
||||
break
|
||||
} else {
|
||||
// Collect incorrect sources but don't return immediately
|
||||
incorrectSources = append(incorrectSources, actualSource)
|
||||
}
|
||||
// Found a registry.coder.com source but with wrong namespace/module
|
||||
errs = append(errs, xerrors.Errorf("incorrect source URL format: found %q, expected %q", actualSource, expectedSource))
|
||||
return errs
|
||||
}
|
||||
}
|
||||
|
||||
if !foundCorrectSource {
|
||||
errs = append(errs, xerrors.Errorf("did not find correct source URL %q in first Terraform code block", expectedSource))
|
||||
// If we found the correct source, ignore any incorrect ones
|
||||
if foundCorrectSource {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we found incorrect sources but no correct one, report the first incorrect source
|
||||
if len(incorrectSources) > 0 {
|
||||
errs = append(errs, xerrors.Errorf("incorrect source URL format: found %q, expected %q", incorrectSources[0], expectedSource))
|
||||
return errs
|
||||
}
|
||||
|
||||
// If we found no sources at all
|
||||
errs = append(errs, xerrors.Errorf("did not find correct source URL %q in any Terraform code block", expectedSource))
|
||||
return errs
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,34 @@ var (
|
||||
version = "1.0.0"
|
||||
agent_id = coder_agent.example.id
|
||||
}
|
||||
` + "```\n"
|
||||
|
||||
multipleBlocksValidBody = `# Test Module
|
||||
|
||||
` + "```tf\n" + `module "other-module" {
|
||||
source = "registry.coder.com/other/module/coder"
|
||||
version = "1.0.0"
|
||||
}
|
||||
` + "```\n" + `
|
||||
` + "```tf\n" + `module "test-module" {
|
||||
source = "registry.coder.com/test-namespace/test-module/coder"
|
||||
version = "1.0.0"
|
||||
agent_id = coder_agent.example.id
|
||||
}
|
||||
` + "```\n"
|
||||
|
||||
multipleBlocksInvalidBody = `# Test Module
|
||||
|
||||
` + "```tf\n" + `module "test-module" {
|
||||
source = "registry.coder.com/wrong-namespace/test-module/coder"
|
||||
version = "1.0.0"
|
||||
}
|
||||
` + "```\n" + `
|
||||
` + "```tf\n" + `module "other-module" {
|
||||
source = "registry.coder.com/another-wrong/test-module/coder"
|
||||
version = "1.0.0"
|
||||
agent_id = coder_agent.example.id
|
||||
}
|
||||
` + "```\n"
|
||||
)
|
||||
|
||||
@ -126,4 +154,39 @@ func TestValidateModuleSourceURL(t *testing.T) {
|
||||
t.Errorf("Expected path format error, got: %s", errs[0].Error())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Multiple blocks with valid source in second block", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rm := coderResourceReadme{
|
||||
resourceType: "modules",
|
||||
filePath: "registry/test-namespace/modules/test-module/README.md",
|
||||
namespace: "test-namespace",
|
||||
resourceName: "test-module",
|
||||
body: multipleBlocksValidBody,
|
||||
}
|
||||
errs := validateModuleSourceURL(rm)
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("Expected no errors, got: %v", errs)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Multiple blocks with incorrect source in second block", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rm := coderResourceReadme{
|
||||
resourceType: "modules",
|
||||
filePath: "registry/test-namespace/modules/test-module/README.md",
|
||||
namespace: "test-namespace",
|
||||
resourceName: "test-module",
|
||||
body: multipleBlocksInvalidBody,
|
||||
}
|
||||
errs := validateModuleSourceURL(rm)
|
||||
if len(errs) != 1 {
|
||||
t.Errorf("Expected 1 error, got %d: %v", len(errs), errs)
|
||||
}
|
||||
if !strings.Contains(errs[0].Error(), "incorrect source URL format") {
|
||||
t.Errorf("Expected source URL format error, got: %s", errs[0].Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user