validateRemoteWorkflow checks if a workflow exists in a remote repository and can be triggered. This validation function is co-located with the run command implementation because: - It's specific to remote workflow execution - It's only called when running workflows in remote repositories - It prov
(workflowName string, repoOverride string, verbose bool)
| 298 | // |
| 299 | // This follows the principle that domain-specific validation belongs in domain files. |
| 300 | func validateRemoteWorkflow(workflowName string, repoOverride string, verbose bool) error { |
| 301 | if repoOverride == "" { |
| 302 | return errors.New("repository must be specified for remote workflow validation") |
| 303 | } |
| 304 | |
| 305 | // Normalize workflow ID to handle both "workflow-name" and ".github/workflows/workflow-name.md" formats |
| 306 | normalizedID := normalizeWorkflowID(workflowName) |
| 307 | |
| 308 | // Add .lock.yml extension |
| 309 | lockFileName := normalizedID + ".lock.yml" |
| 310 | |
| 311 | if verbose { |
| 312 | fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Checking if workflow '%s' exists in repository '%s'...", lockFileName, repoOverride))) |
| 313 | } |
| 314 | |
| 315 | // Use gh CLI to list workflows in the target repository |
| 316 | output, err := workflow.RunGH("Listing workflows...", "workflow", "list", "--repo", repoOverride, "--json", "name,path,state") |
| 317 | if err != nil { |
| 318 | var exitError *exec.ExitError |
| 319 | if errors.As(err, &exitError) { |
| 320 | return fmt.Errorf("failed to list workflows in repository '%s': %s: %w", repoOverride, string(exitError.Stderr), err) |
| 321 | } |
| 322 | return fmt.Errorf("failed to list workflows in repository '%s': %w", repoOverride, err) |
| 323 | } |
| 324 | |
| 325 | // Parse the JSON response |
| 326 | var workflows []struct { |
| 327 | Name string `json:"name"` |
| 328 | Path string `json:"path"` |
| 329 | State string `json:"state"` |
| 330 | } |
| 331 | |
| 332 | if err := json.Unmarshal(output, &workflows); err != nil { |
| 333 | return fmt.Errorf("failed to parse workflow list response: %w", err) |
| 334 | } |
| 335 | |
| 336 | // Look for the workflow by checking if the lock file path exists |
| 337 | for _, wf := range workflows { |
| 338 | if strings.HasSuffix(wf.Path, lockFileName) { |
| 339 | if verbose { |
| 340 | fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Found workflow '%s' in repository (path: %s, state: %s)", |
| 341 | wf.Name, wf.Path, wf.State))) |
| 342 | } |
| 343 | return nil |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | suggestions := []string{ |
| 348 | "Check if the workflow has been pushed to the remote repository", |
| 349 | "Verify the workflow file exists in the repository's .github/workflows directory", |
| 350 | fmt.Sprintf("Run '%s status' to see available workflows", string(constants.CLIExtensionPrefix)), |
| 351 | } |
| 352 | return errors.New(console.FormatErrorWithSuggestions( |
| 353 | fmt.Sprintf("workflow '%s' not found in repository '%s'", lockFileName, repoOverride), |
| 354 | suggestions, |
| 355 | )) |
| 356 | } |
no test coverage detected