Skip to content

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 analyze your TypeScript source code before build.

Severity: warning | Category: style

Flags raw uses: strings when a typed composite wrapper is available (e.g. actions/checkout@v4Checkout({})). Typed composites provide better IDE support and catch configuration errors at compile time.

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.

Severity: error | Category: security

Flags hardcoded GitHub tokens, AWS keys, and other secret patterns in source code. Use secrets("...") expressions instead.

lint-gha003.ts
import { Job, Step, secrets } from "@intentius/chant-lexicon-github";
// BAD — hardcoded token triggers GHA003
export 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() expression
export 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",
}),
],
});

Severity: info | Category: style

Flags inline matrix objects and suggests extracting them to named constants for readability.

Severity: info | Category: style

Flags deeply nested inline objects and suggests extracting them to named constants.

Severity: warning | Category: style

Flags files with more than 10 job exports. Split large workflows into separate files for maintainability.

Severity: info | Category: style

Flags raw ${{ }} expression strings outside of if: fields. Use the typed expression helpers (github.*, secrets(), matrix()) for better type safety.

Severity: warning | Category: correctness

Flags setup action composites (SetupNode, SetupGo, SetupPython) without a version input. Pinning the version ensures reproducible builds.

Severity: warning | Category: correctness

Flags action uses: references that point to deprecated versions. Upgrade to the recommended version.

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.

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.

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.

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 run against the serialized YAML after build. They catch issues only visible in the final output.

Severity: error

Flags multiple workflows that share the same name: value. Duplicate names cause confusion in the GitHub Actions UI.

Severity: error

Flags matrix strategy dimensions with an empty values array. An empty dimension causes the job to be skipped entirely.

Severity: error

Flags jobs whose needs: entries reference a job not defined in the workflow. This causes a workflow validation error on GitHub.

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.

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.

Terminal window
# Lint your chant project
chant lint src/
# Lint with auto-fix where supported
chant lint --fix src/

To suppress a rule on a specific line:

// chant-disable-next-line GHA001
new Step({ uses: "actions/checkout@v4" });

To suppress globally in chant.config.ts:

export default {
lint: {
rules: {
GHA014: "off",
},
},
};