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>
Each node in 'glint graph includes' now lists the jobs defined directly
in that file. Jobs appear as rounded Mermaid nodes with a distinct
light-purple style, connected with dashed arrows (-.->). This visual
distinction separates ownership (file -.-> job) from the include
hierarchy (file --> included-file).
The root file's jobs are collected by re-parsing it without include
resolution; local and fetched project/component nodes populate their
job list in the existing recurse* methods.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Variables with value/description/options sub-keys, default.image in map
form, default.before_script / default.after_script as block scalars, and
rules.changes / rules.exists in {paths, compare_to} map form all caused
"yaml: cannot unmarshal !!map into string" because the struct fields were
typed too narrowly.
Changed types in model.Pipeline, model.DefaultConfig, and model.Rule to
accept any to match GitLab CI spec flexibility (13.7+ variable declarations,
15.3+ rules.changes map form, image map form in default block).
Adds testdata/script_multiline.yml covering all these patterns.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
actions/checkout@v4 requires Node.js which is absent in golang:alpine.
Clone the repo directly with git using an oauth2 token in the URL,
removing the Node.js dependency entirely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch from the full ubuntu runner image to golang:1.26-alpine via the
container: directive. Go is pre-installed so actions/setup-go is dropped;
curl, git, and jq are added with apk in the first step.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
upload-artifact@v4 uses a backend API incompatible with Gitea (GHES).
Collapse to a single job that builds both targets sequentially and uploads
directly to a Gitea release via the REST API, removing the need for
artifact passing between jobs entirely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Builds Linux x64 and Windows x64 binaries on tag pushes (v*) and
publishes them as assets on a Gitea release via the REST API.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>