feat(linter): add file/line to findings; downgrade extends missing-script to warning
Every finding now carries the source file and exact line number of the job key in its YAML file. Format: [ERROR] job "name" (file.yml:12): message. Pipeline-level findings (workflow rules, no stages) reference p.SourceFile. Cross-file include jobs (local, project, component) carry the include source as their File, set via Pipeline.SetJobOrigin after each ParseBytes call in the resolver. Line numbers come from the yaml.Node key node (exact job-name line) in a new document-level first pass in ParseBytes, replacing the previous map[string]yaml.Node approach which only gave value-node lines. Also: jobs that declare extends: but have no script after resolution now emit WARNING instead of ERROR. The script may come from a base in a remote include that was not fetched (no token, offline), making the error a false positive in common project setups. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,8 @@ func checkNeeds(p *model.Pipeline) []Finding {
|
||||
findings = append(findings, Finding{
|
||||
Severity: Error,
|
||||
Job: name,
|
||||
File: job.File,
|
||||
Line: job.Line,
|
||||
Message: fmt.Sprintf("needs unknown job %q", needed),
|
||||
})
|
||||
continue
|
||||
@@ -47,6 +49,8 @@ func checkNeeds(p *model.Pipeline) []Finding {
|
||||
findings = append(findings, Finding{
|
||||
Severity: Error,
|
||||
Job: name,
|
||||
File: job.File,
|
||||
Line: job.Line,
|
||||
Message: fmt.Sprintf(
|
||||
"needs %q which is in a later stage (%q after %q)",
|
||||
needed, neededJob.Stage, job.Stage,
|
||||
@@ -57,7 +61,7 @@ func checkNeeds(p *model.Pipeline) []Finding {
|
||||
}
|
||||
}
|
||||
|
||||
findings = append(findings, detectNeedsCycles(needsGraph)...)
|
||||
findings = append(findings, detectNeedsCycles(needsGraph, p.Jobs)...)
|
||||
return findings
|
||||
}
|
||||
|
||||
@@ -82,7 +86,7 @@ func parseNeedJobNames(needs []any) []string {
|
||||
return names
|
||||
}
|
||||
|
||||
func detectNeedsCycles(graph map[string][]string) []Finding {
|
||||
func detectNeedsCycles(graph map[string][]string, jobs map[string]model.Job) []Finding {
|
||||
const (
|
||||
unvisited = 0
|
||||
visiting = 1
|
||||
@@ -101,9 +105,12 @@ func detectNeedsCycles(graph map[string][]string) []Finding {
|
||||
case visiting:
|
||||
if !reported[name] {
|
||||
reported[name] = true
|
||||
j := jobs[name]
|
||||
findings = append(findings, Finding{
|
||||
Severity: Error,
|
||||
Job: name,
|
||||
File: j.File,
|
||||
Line: j.Line,
|
||||
Message: fmt.Sprintf("circular dependency in needs: %v → %s", path, name),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user