MCPcopy Create free account
hub / github.com/github/gh-aw / validateRuntimeImportFiles

Function validateRuntimeImportFiles

pkg/workflow/runtime_import_validation.go:93–179  ·  view source on GitHub ↗

validateRuntimeImportFiles validates expressions in all runtime-import files at compile time. This catches expression errors early, before the workflow runs. workspaceDir should be the root of the repository (containing .github folder). It returns any best-effort sub-agent frontmatter warnings and a

(markdownContent string, workspaceDir string)

Source from the content-addressed store, hash-verified

91// It returns any best-effort sub-agent frontmatter warnings and a non-nil error for fatal
92// expression validation failures.
93func validateRuntimeImportFiles(markdownContent string, workspaceDir string) ([]string, error) {
94 expressionValidationLog.Print("Validating runtime-import files")
95
96 // Extract all runtime-import file paths
97 paths := extractRuntimeImportPaths(markdownContent)
98 if len(paths) == 0 {
99 expressionValidationLog.Print("No runtime-import files to validate")
100 return nil, nil
101 }
102
103 expressionValidationLog.Printf("Found %d runtime-import file(s) to validate", len(paths))
104
105 var validationErrors []string
106 var subAgentWarnings []string
107
108 for _, filePath := range paths {
109 // Normalize the path to be relative to .github folder
110 normalizedPath := filePath
111 if strings.HasPrefix(normalizedPath, constants.GithubDir) {
112 normalizedPath = normalizedPath[len(constants.GithubDir):] // Remove ".github/"
113 } else if strings.HasPrefix(normalizedPath, ".github\\") {
114 normalizedPath = normalizedPath[8:] // Remove ".github\" (Windows)
115 }
116 if strings.HasPrefix(normalizedPath, "./") {
117 normalizedPath = normalizedPath[2:] // Remove "./"
118 } else if strings.HasPrefix(normalizedPath, ".\\") {
119 normalizedPath = normalizedPath[2:] // Remove ".\" (Windows)
120 }
121
122 // Build absolute path to the file
123 githubFolder := filepath.Join(workspaceDir, ".github")
124 absolutePath := filepath.Join(githubFolder, normalizedPath)
125
126 // Security check: ensure the resolved path is within the .github folder
127 // Use filepath.Rel to check if the path escapes the .github folder
128 normalizedGithubFolder := filepath.Clean(githubFolder)
129 normalizedAbsolutePath := filepath.Clean(absolutePath)
130 relativePath, err := filepath.Rel(normalizedGithubFolder, normalizedAbsolutePath)
131 if err != nil || relativePath == ".." || strings.HasPrefix(relativePath, ".."+string(filepath.Separator)) || filepath.IsAbs(relativePath) {
132 validationErrors = append(validationErrors, fmt.Sprintf("%s: Security: Path must be within .github folder (resolves to: %s)", filePath, relativePath))
133 continue
134 }
135
136 // Check if file exists; missing files (optional or not) are deferred to runtime
137 if _, err := os.Stat(absolutePath); os.IsNotExist(err) {
138 expressionValidationLog.Printf("Skipping validation for non-existent file: %s", filePath)
139 continue
140 }
141
142 // Read the file content
143 content, err := os.ReadFile(absolutePath)
144 if err != nil {
145 validationErrors = append(validationErrors, fmt.Sprintf("%s: failed to read file: %v", filePath, err))
146 continue
147 }
148
149 // Validate expressions in the imported file
150 if err := validateExpressionSafety(string(content)); err != nil {

Calls 7

validateExpressionSafetyFunction · 0.85
PrintMethod · 0.80
NewValidationErrorFunction · 0.70
PrintfMethod · 0.45