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 (
|
var (
|
||||||
// Matches Terraform source lines with registry.coder.com URLs
|
// Matches Terraform source lines with registry.coder.com URLs
|
||||||
// Pattern: source = "registry.coder.com/namespace/module/coder"
|
// 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 {
|
func validateModuleSourceURL(rm coderResourceReadme) []error {
|
||||||
@ -27,6 +27,7 @@ func validateModuleSourceURL(rm coderResourceReadme) []error {
|
|||||||
|
|
||||||
trimmed := strings.TrimSpace(rm.body)
|
trimmed := strings.TrimSpace(rm.body)
|
||||||
foundCorrectSource := false
|
foundCorrectSource := false
|
||||||
|
var incorrectSources []string
|
||||||
isInsideTerraform := false
|
isInsideTerraform := false
|
||||||
|
|
||||||
lineScanner := bufio.NewScanner(strings.NewReader(trimmed))
|
lineScanner := bufio.NewScanner(strings.NewReader(trimmed))
|
||||||
@ -39,7 +40,8 @@ func validateModuleSourceURL(rm coderResourceReadme) []error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if isInsideTerraform {
|
if isInsideTerraform {
|
||||||
break
|
// End of current terraform block, continue to look for more
|
||||||
|
isInsideTerraform = false
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -48,26 +50,34 @@ func validateModuleSourceURL(rm coderResourceReadme) []error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for source line in the first terraform block
|
// Check for source line in terraform blocks
|
||||||
if matches := terraformSourceRe.FindStringSubmatch(nextLine); matches != nil {
|
if matches := terraformSourceRe.FindStringSubmatch(nextLine); matches != nil {
|
||||||
actualNamespace := matches[1]
|
actualNamespace := matches[1]
|
||||||
actualModule := matches[2]
|
actualModule := matches[2]
|
||||||
actualSource := registryDomain + "/" + actualNamespace + "/" + actualModule + "/coder"
|
actualSource := registryDomain + "/" + actualNamespace + "/" + actualModule + "/coder"
|
||||||
|
|
||||||
if actualSource == expectedSource {
|
if actualSource == expectedSource {
|
||||||
foundCorrectSource = true
|
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 {
|
// If we found the correct source, ignore any incorrect ones
|
||||||
errs = append(errs, xerrors.Errorf("did not find correct source URL %q in first Terraform code block", expectedSource))
|
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
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,34 @@ var (
|
|||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
agent_id = coder_agent.example.id
|
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"
|
` + "```\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,4 +154,39 @@ func TestValidateModuleSourceURL(t *testing.T) {
|
|||||||
t.Errorf("Expected path format error, got: %s", errs[0].Error())
|
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