- Add --changes PATH and --changes-from REF flags to glint check and glint graph
for rules:changes: evaluation. --changes marks files explicitly; --changes-from
runs git diff --name-only <REF> automatically. Both flags can be combined.
- Implement doublestar glob matching (*, ** across path segments) in EvalJob and
EvalWorkflow; extended {paths, compare_to} map form supported.
- Without --changes/--changes-from the condition stays permissive (existing behaviour).
- Context summary line now shows changed-file count when file data is provided.
- Achieve 100% statement coverage: comprehensive tests added across all packages;
removed provably dead code; added testability seams (exit, userHomeDirFn,
execCommandOutput variables) to cover previously unreachable paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
11 KiB
Roadmap
This document tracks planned improvements to glint. Items are grouped by theme, roughly in priority order within each group. Nothing here is a commitment — the tool is experimental and the list will shift as real usage surfaces better priorities.
Context simulation
Pass --branch, --tag, --source, or --var to glint check or glint graph to evaluate rules:if: expressions and only/except filters against a specific pipeline event.
Single-context simulation— ✓ shipped v0.2.0;--branch,--tag,--source,--varflags on both subcommands; jobs classified as active / manual / skipped— ✓ shipped post-v0.2.0; variables from the matching workflow rule entry injected into the evaluation context before jobworkflow:rules:variables:propagationrules:if:expressions are evaluatedExpression evaluator: multi-line— ✓ shipped post-v0.2.0; newlines in block-scalar and folded YAMLif:valuesif:values treated as whitespaceExpression evaluator:— ✓ shipped post-v0.2.0;${VAR}syntax${CI_COMMIT_BRANCH}equivalent to$CI_COMMIT_BRANCHeverywhereExpression evaluator: regex flags— ✓ shipped post-v0.2.0;/pattern/i,/pattern/m,/pattern/ssupportedExpression evaluator: variable as regex RHS— ✓ shipped post-v0.2.0;$BRANCH =~ $PATTERNwhere$PATTERNholds a/regex/string evaluates correctlyExpression evaluator: bare— ✓ shipped post-v0.2.0;true/falseand integer literals$FLAG == true,$COUNT == 4compare as decimal strings matching GitLab CI behaviourImplicit default context— ✓ shipped v0.2.11; defaults to--branch main --source pushwhen no context flag is given, sorules:if:is always evaluated— ✓ shipped v0.2.11; prints sorted--list-varsdebug flagKEY=VALUEof all collected pipeline variables (root file + includes + workflow-rule union + effective context) to stderrVariable expansion— ✓ shipped v0.2.13;$VAR/${VAR}references within variable values expanded after all sources are merged; transitive chains resolved; visible in--list-varsNon-string scalar variables— ✓ shipped v0.2.13;BUILD: true,RETRIES: 3rendered and injected correctly instead of being silently droppedYAML— ✓ shipped v0.2.13; regex patterns like\/escape in double-quoted strings/^us\//in double-quotedif:blocks no longer cause a parse errorWorkflow rule strict evaluation— ✓ shipped v0.2.14; unparseableif:skips the rule instead of matching everything; prevents wrong variables being injectedSingle— ✓ shipped v0.2.14; bare=operator=accepted as alias for==inrules:if:expressions— ✓ shipped v0.2.21;rules:changes:evaluation--changes PATHand--changes-from REFflags; doublestar glob matching (*within segment,**across segments); permissive when no file list provided- Multi-context simulation — run multiple contexts in one invocation and print a comparison table (
--context branch=main --context branch=develop --context tag=v1.0.0) - Context-scoped linting — skip
needs:/dependencies:cross-checks for jobs that are statically unreachable in the given context
Lint coverage
The current rule set covers the most common sources of broken pipelines. These are the gaps most likely to matter in practice.
Variable reference validation (GL032)— ✓ shipped v0.2.11; warns when arules:if:expression references$VAR/${VAR}not declared anywhere in pipeline YAML; predefined GitLab namespaces (CI_*,GITLAB_*, …) exempt; variables from included files are also considered— ✓ shipped v0.2.15; warns when every rule in a job'srules:if:static reachability (GL033)rules:block haswhen: never, making the job permanently excluded from any pipeline run; noif:evaluation required— ✓ shipped v0.2.16; map form requiresservices:validation (GL034)name;aliasmust be a valid DNS label— ✓ shipped v0.2.16; warns when a path starts withrules:changes/rules:existsabsolute path detection (GL035)/; GitLab CI paths are always relative to the repo root— ✓ shipped v0.2.16; validates job-level andtimeoutformat validation (GL036)default.timeoutagainst recognised GitLab CI duration strings— ✓ shipped v0.2.16;id_tokens:/secrets:required-key checks (GL037, GL038)id_tokensentries must haveaud;secretsentries must declare a provider— ✓ shipped v0.2.16; warns when the publish directory is missing frompages:publish+artifacts.pathsconsistency (GL039)artifacts.pathsDuplicate stage names (GL040)— ✓ shipped v0.2.16; warns when a stage appears more than once instages:— ✓ shipped v0.2.16; warns when entries look like glob patternscache:key:filesmust be exact paths (GL041)Unreachable jobs— covered by GL033 (shipped v0.2.15); every-when:neverrules block is statically dead— ✓ shipped v0.2.20; warns wheninherit:completeness (GL043)inherit: default:is declared but there's nodefault:block, or list form names fields not set indefault:
Include resolution
— ✓ shipped in v0.2.0; local files are read from disk, recursively resolved, and merged before lintinginclude: local:full resolution— ✓ shipped post-v0.2.0; plain HTTPS URLs are fetched (unauthenticated), parsed, and merged; sub-includes are resolved recursively; unreachable URLs emitinclude: remote:(URL)[WARNING]and linting continuesRecursive include depth limit— ✓ shipped v0.2.17; depth capped at 100 (matching GitLab); project/component includes now tracked in visited set to prevent cross-file cyclesOffline mode / cache— ✓ shipped v0.2.17;--cache-dir DIRpersists fetched templates;--offlineserves from cache only; default cache dir (~/.cache/glint) used automatically with--offline— ✓ shipped v0.2.17;include: inputs:$[[ inputs.KEY ]]and$[[ inputs.KEY | default(…) ]]placeholders in fetched component YAML are substituted from the include'swith:block before parsing
Output formats — ✓ shipped v0.2.18
JSON (— ✓ shipped v0.2.18; machine-readable findings with stable schema (version 1)--format json)SARIF (— ✓ shipped v0.2.18; SARIF 2.1.0; consumed natively by GitHub Code Scanning and GitLab SAST--format sarif)JUnit XML (— ✓ shipped v0.2.18; lets CI pipelines publish lint results as a test report artifact--format junit)GitHub annotation format (— ✓ shipped v0.2.18; emits--format github)::error file=…,line=…,title=RULE::messagelines so findings appear as inline comments in PR diffs
Pipeline graph improvements
The SVG renderer and terminal tree cover the basic layout. These would bring it closer to GitLab's full interactive view.
Terminal job tree— ✓ shipped in v0.2.0 asglint graph tree; stages as branches, jobs as leaves, context-aware annotations— ✓ shipped post-v0.2.0; each include node shows the jobs it defines as dashed-arrow rounded nodes in a distinct styleglint graph includesshows jobs per file- Multi-job connector accuracy — draw one connector per job pair rather than one per stage pair in classic mode, so pipelines with uneven columns look correct
- Job tooltip / detail panel — embed a hidden
<title>and<desc>per chip so SVG viewers showstage,when,image, andneedson hover when: on_failurevisual distinction — dashed border or distinct icon for failure-path jobs- Blocked / skipped state colouring — grey out jobs that are statically unreachable given known
rules:conditions - Interactive HTML output — self-contained
.htmlfile with pan/zoom and a job-detail sidebar; no external dependencies - Mermaid pipeline output — keep
pipeline.gobut wire it up through--graph pipeline --format mermaidfor users who want to paste into mermaid.live
Findings quality — ✓ file and line numbers shipped post-v0.2.0; ruff-style format shipped v0.2.11
File and line numbers on findings — ✓ shipped post-v0.2.0; every finding includes the source file and exact line of the job key. Works across local includes, remote project templates, and fetched component templates.
Ruff-style output format — ✓ shipped v0.2.11; findings follow file:line: RULEID [severity] message matching the convention used by ruff and other modern linters.
Remaining improvements
— ✓ shipped post-v0.2.0; optional missing needs are downgraded toneeds: optional: truefalse-positive errors[WARNING]— ✓ shipped post-v0.2.0; jobs usingextends:jobs with missing script false errorsextends:that have noscriptafter resolution emit[WARNING](the script may come from an unfetchable remote base)— ✓ shipped v0.2.20; warns when allrules:if:static reachability (GL042)rules:if:conditions evaluate to false given declared variable values (only fires when all referenced vars are declared in YAML)
CI / editor integration
- GitLab CI template — a
.gitlab-ci.ymlsnippet that runsglintas a pipeline-validation job before the real pipeline executes; publishable to the GitLab CI/CD Catalog - GitHub Actions action —
uses: k3nny/glint@v1wrapper for repositories that mirror or manage GitLab pipelines from GitHub - Pre-commit hook — entry for pre-commit so
glintruns automatically ongit commitwhen.gitlab-ci.ymlchanges - LSP server —
glint lspmode exposing diagnostics over the Language Server Protocol; enables inline squiggles in VS Code, JetBrains, Neovim, etc. without a dedicated extension - VS Code extension — thin wrapper around the LSP server with syntax highlighting for
.gitlab-ci.yml
Configuration — ✓ shipped v0.2.19
— ✓ shipped v0.2.19;.glint.ymlconfig fileignore:,severity:,stages:,token:,url:,cache_dir:; searched from the pipeline directory up to the git rootInline suppression comments— ✓ shipped v0.2.19;# glint: ignore GL007before a job definition; comma/space-separated rules;# glint: ignore allwildcard
Reliability and developer experience
Structured rule IDs— ✓ shipped post-v0.2.0; GL001–GL031 assigned; GL032 added v0.2.11; GL033 added v0.2.15; GL034–GL041 added v0.2.16; output formats (--format json/sarif/junit/github) added v0.2.18; GL042–GL043 added v0.2.20— ✓ shipped v0.2.20; prints rule description, rationale, bad-YAML example, and fix;glint explain <rule-id>glint explain(no arg) lists all rulesSemantic versioning and first release— shipped asv0.1.0(2026-06-07)Subcommand CLI— shipped asv0.2.0(2026-06-11);glint check/glint graph [mode]with ruff-style--help- Changelog automation — generate release notes from Conventional Commits via
git-cliffor similar - Fuzz testing — add a
go test -fuzztarget for the YAML parser to harden it against malformed input