Lint Rules
The GitHub Actions lexicon ships lint rules that run during chant lint and post-synth checks that validate the serialized YAML after chant build.
Lint rules
Section titled “Lint rules”Lint rules analyze your TypeScript source code before build.
GHA001 — Use typed action composites
Section titled “GHA001 — Use typed action composites”Severity: warning | Category: style
Flags raw uses: strings when a typed composite wrapper is available (e.g. actions/checkout@v4 → Checkout({})). Typed composites provide better IDE support and catch configuration errors at compile time.
GHA002 — Use Expression helpers
Section titled “GHA002 — Use Expression helpers”Severity: warning | Category: style
Flags raw ${{ }} strings in if: conditions. Use the typed Expression helpers (github.ref.eq(...), branch("main"), failure()) instead for type safety and lint coverage.
GHA003 — No hardcoded secrets
Section titled “GHA003 — No hardcoded secrets”Severity: error | Category: security
Flags hardcoded GitHub tokens, AWS keys, and other secret patterns in source code. Use secrets("...") expressions instead.
import { Job, Step, secrets } from "@intentius/chant-lexicon-github";
// BAD — hardcoded token triggers GHA003export const badDeploy = new Job({ "runs-on": "ubuntu-latest", steps: [ new Step({ name: "Deploy", run: "curl -H 'Authorization: token ghp_abc123def456' https://api.github.com/repos", }), ],});
// GOOD — use secrets() expressionexport const goodDeploy = new Job({ "runs-on": "ubuntu-latest", steps: [ new Step({ name: "Deploy", env: { GH_TOKEN: secrets("GITHUB_TOKEN") }, run: "curl -H \"Authorization: token $GH_TOKEN\" https://api.github.com/repos", }), ],});GHA004 — Extract inline matrix
Section titled “GHA004 — Extract inline matrix”Severity: info | Category: style
Flags inline matrix objects and suggests extracting them to named constants for readability.
GHA005 — Extract deeply nested objects
Section titled “GHA005 — Extract deeply nested objects”Severity: info | Category: style
Flags deeply nested inline objects and suggests extracting them to named constants.
GHA007 — Too many jobs per file
Section titled “GHA007 — Too many jobs per file”Severity: warning | Category: style
Flags files with more than 10 job exports. Split large workflows into separate files for maintainability.
GHA008 — Avoid raw expression strings
Section titled “GHA008 — Avoid raw expression strings”Severity: info | Category: style
Flags raw ${{ }} expression strings outside of if: fields. Use the typed expression helpers (github.*, secrets(), matrix()) for better type safety.
GHA010 — Setup action missing version
Section titled “GHA010 — Setup action missing version”Severity: warning | Category: correctness
Flags setup action composites (SetupNode, SetupGo, SetupPython) without a version input. Pinning the version ensures reproducible builds.
GHA012 — Deprecated action version
Section titled “GHA012 — Deprecated action version”Severity: warning | Category: correctness
Flags action uses: references that point to deprecated versions. Upgrade to the recommended version.
GHA014 — Missing timeout
Section titled “GHA014 — Missing timeout”Severity: warning | Category: correctness
Flags jobs without timeoutMinutes. Jobs without a timeout default to 360 minutes (6 hours), which can waste runner minutes if stuck.
GHA015 — Setup without cache
Section titled “GHA015 — Setup without cache”Severity: warning | Category: performance
Flags setup action composites (SetupNode, SetupGo, SetupPython) without a paired CacheAction or built-in cache option. Caching dependencies significantly speeds up builds.
GHA016 — Concurrency missing group
Section titled “GHA016 — Concurrency missing group”Severity: warning | Category: correctness
Flags concurrency with cancel-in-progress: true but no group specified. Without a group, all runs of the workflow share a single concurrency slot.
GHA020 — Potential secret detected
Section titled “GHA020 — Potential secret detected”Severity: error | Category: security
Flags string literals that match common secret patterns (API keys, tokens, passwords). Use secrets() or environment variables instead.
Post-synth checks
Section titled “Post-synth checks”Post-synth checks run against the serialized YAML after build. They catch issues only visible in the final output.
GHA006 — Duplicate workflow names
Section titled “GHA006 — Duplicate workflow names”Severity: error
Flags multiple workflows that share the same name: value. Duplicate names cause confusion in the GitHub Actions UI.
GHA009 — Empty matrix dimension
Section titled “GHA009 — Empty matrix dimension”Severity: error
Flags matrix strategy dimensions with an empty values array. An empty dimension causes the job to be skipped entirely.
GHA011 — Invalid needs target
Section titled “GHA011 — Invalid needs target”Severity: error
Flags jobs whose needs: entries reference a job not defined in the workflow. This causes a workflow validation error on GitHub.
GHA017 — Missing permissions block
Section titled “GHA017 — Missing permissions block”Severity: info
Flags workflows without an explicit permissions: block. Omitting permissions uses the repository default (often overly broad). Following least-privilege by declaring explicit permissions is a security best practice.
GHA018 — pull_request_target with checkout
Section titled “GHA018 — pull_request_target with checkout”Severity: warning
Flags workflows triggered by pull_request_target that include actions/checkout. This combination can be a security risk because the workflow runs with write permissions in the context of the base branch while checking out potentially untrusted PR code.
GHA019 — Circular needs chain
Section titled “GHA019 — Circular needs chain”Severity: error
Detects cycles in the needs: dependency graph. If job A needs B and B needs A (directly or transitively), GitHub rejects the workflow. Reports the full cycle chain in the diagnostic message.
Running lint
Section titled “Running lint”# Lint your chant projectchant lint src/
# Lint with auto-fix where supportedchant lint --fix src/To suppress a rule on a specific line:
// chant-disable-next-line GHA001new Step({ uses: "actions/checkout@v4" });To suppress globally in chant.config.ts:
export default { lint: { rules: { GHA014: "off", }, },};