findWorkflowFile searches for a workflow file in the configured workflows directory only. Returns paths and existence flags for .md, .lock.yml, and .yml files
(workflowName string, currentWorkflowPath string)
| 56 | // findWorkflowFile searches for a workflow file in the configured workflows directory only. |
| 57 | // Returns paths and existence flags for .md, .lock.yml, and .yml files |
| 58 | func findWorkflowFile(workflowName string, currentWorkflowPath string) (*findWorkflowFileResult, error) { |
| 59 | dispatchWorkflowValidationLog.Printf("Finding workflow file: name=%s, current_path=%s", workflowName, currentWorkflowPath) |
| 60 | result := &findWorkflowFileResult{} |
| 61 | |
| 62 | // Get the current workflow's directory |
| 63 | currentDir := filepath.Dir(currentWorkflowPath) |
| 64 | |
| 65 | // Get repo root by going up from the current workflow directory. |
| 66 | // Assume structure: <repo-root>/<configured-workflows-dir>/file.md or <repo-root>/.github/aw/file.md. |
| 67 | githubDir := filepath.Dir(currentDir) // .github |
| 68 | repoRoot := filepath.Dir(githubDir) // repo root |
| 69 | |
| 70 | // Only search in the configured workflows directory. |
| 71 | searchDir := filepath.Join(repoRoot, constants.GetWorkflowDir()) |
| 72 | |
| 73 | // Build paths for the workflows directory |
| 74 | mdPath := filepath.Clean(filepath.Join(searchDir, workflowName+".md")) |
| 75 | lockPath := filepath.Clean(filepath.Join(searchDir, workflowName+".lock.yml")) |
| 76 | ymlPath := filepath.Clean(filepath.Join(searchDir, workflowName+".yml")) |
| 77 | |
| 78 | // Validate paths are within the search directory (prevent path traversal) |
| 79 | if !isPathWithinDir(mdPath, searchDir) || !isPathWithinDir(lockPath, searchDir) || !isPathWithinDir(ymlPath, searchDir) { |
| 80 | dispatchWorkflowValidationLog.Printf("Rejecting workflow name '%s': resolved paths escape search dir %s", workflowName, searchDir) |
| 81 | return result, fmt.Errorf("invalid workflow name '%s' (path traversal not allowed)", workflowName) |
| 82 | } |
| 83 | |
| 84 | // Check which files exist |
| 85 | result.mdPath = mdPath |
| 86 | result.lockPath = lockPath |
| 87 | result.ymlPath = ymlPath |
| 88 | result.mdExists = fileutil.FileExists(mdPath) |
| 89 | result.lockExists = fileutil.FileExists(lockPath) |
| 90 | result.ymlExists = fileutil.FileExists(ymlPath) |
| 91 | |
| 92 | dispatchWorkflowValidationLog.Printf("Workflow file search results: md_exists=%v, lock_exists=%v, yml_exists=%v", result.mdExists, result.lockExists, result.ymlExists) |
| 93 | return result, nil |
| 94 | } |
| 95 | |
| 96 | // mdHasWorkflowDispatch reads a .md workflow file's frontmatter and reports whether |
| 97 | // the workflow includes a workflow_dispatch trigger in its 'on:' section. |