IsWorkflowSpec checks if a path looks like a workflowspec (owner/repo/path[@ref]).
(path string)
| 290 | |
| 291 | // IsWorkflowSpec checks if a path looks like a workflowspec (owner/repo/path[@ref]). |
| 292 | func IsWorkflowSpec(path string) bool { |
| 293 | // Remove section reference if present |
| 294 | cleanPath := path |
| 295 | if before, _, ok := strings.Cut(path, "#"); ok { |
| 296 | cleanPath = before |
| 297 | } |
| 298 | |
| 299 | // Remove ref if present |
| 300 | if idx := strings.Index(cleanPath, "@"); idx != -1 { |
| 301 | cleanPath = cleanPath[:idx] |
| 302 | } |
| 303 | |
| 304 | // Check if it has at least 3 parts (owner/repo/path) |
| 305 | parts := strings.Split(cleanPath, "/") |
| 306 | if len(parts) < 3 { |
| 307 | return false |
| 308 | } |
| 309 | |
| 310 | // Preserve legacy behavior expected by parser tests: URL-like paths are |
| 311 | // currently treated as workflowspecs because downstream parsing supports |
| 312 | // repository/path extraction from slash-delimited remote references. |
| 313 | if strings.Contains(cleanPath, "://") { |
| 314 | return true |
| 315 | } |
| 316 | |
| 317 | // Reject paths that start with "." (local paths like .github/workflows/...) |
| 318 | if strings.HasPrefix(cleanPath, ".") { |
| 319 | return false |
| 320 | } |
| 321 | |
| 322 | // Reject paths that start with "shared/" (local shared files) |
| 323 | if strings.HasPrefix(cleanPath, "shared/") { |
| 324 | return false |
| 325 | } |
| 326 | |
| 327 | // Reject absolute paths |
| 328 | if strings.HasPrefix(cleanPath, "/") { |
| 329 | return false |
| 330 | } |
| 331 | |
| 332 | // Safe indexing: len(parts) >= 3 is guaranteed above. |
| 333 | owner := parts[0] |
| 334 | repo := parts[1] |
| 335 | if owner == "" || repo == "" { |
| 336 | return false |
| 337 | } |
| 338 | |
| 339 | return true |
| 340 | } |
| 341 | |
| 342 | func isWorkflowSpec(path string) bool { |
| 343 | return IsWorkflowSpec(path) |
no outgoing calls