Composites
Composites are pre-built abstractions that produce typed GitHub Actions resources. They range from single-action wrappers to full multi-job workflow pipelines.
import { Job, Step, Checkout, SetupNode, SetupGo, CacheAction, UploadArtifact, DownloadArtifact, NodePipeline, PythonCI, DockerBuild, DeployEnvironment, GoCI, BunPipeline,} from "@intentius/chant-lexicon-github";
// Checkout — wraps actions/checkoutconst checkout = Checkout({ fetchDepth: 0 });
// SetupNode — wraps actions/setup-node with optional cachingconst setupNode = SetupNode({ nodeVersion: "22", cache: "npm" });
// SetupGo — wraps actions/setup-goconst setupGo = SetupGo({ goVersion: "1.22" });
// CacheAction — wraps actions/cache for custom cache keysconst cache = CacheAction({ path: "~/.cache/my-tool", key: "my-tool-cache-${{ runner.os }}",});
// UploadArtifact — wraps actions/upload-artifactconst upload = UploadArtifact({ name: "build-output", path: "dist/",});
// DownloadArtifact — wraps actions/download-artifactconst download = DownloadArtifact({ name: "build-output", path: "dist/",});
// Combine composites in a jobexport const combinedJob = new Job({ "runs-on": "ubuntu-latest", steps: [ checkout.step, setupNode.step, new Step({ name: "Build", run: "npm ci && npm run build" }), upload.step, ],});
// ── Multi-job pipelines ──────────────────────────────────────────────
// NodePipeline — build + test with artifact passingconst node = NodePipeline({ nodeVersion: "22", packageManager: "pnpm" });export const nodeWorkflow = node.workflow;// The test job declares `needs: ["build"]`, so the build job must be exported under that name.export const build = node.buildJob;export const test = node.testJob;
// BunPipeline preset — NodePipeline with bun defaultsconst bun = BunPipeline({});export const bunWorkflow = bun.workflow;
// PythonCI — test + optional lintconst python = PythonCI({ pythonVersion: "3.12" });export const pythonWorkflow = python.workflow;
// DockerBuild — build + push with official Docker actionsconst docker = DockerBuild({ imageName: "ghcr.io/my-org/my-app" });export const dockerWorkflow = docker.workflow;
// DeployEnvironment — deploy + cleanup job pairconst deploy = DeployEnvironment({ name: "staging", deployScript: "npm run deploy",});export const deployJob = deploy.deployJob;
// GoCI — build + test + optional lintconst go = GoCI({ goVersion: "1.22" });export const goWorkflow = go.workflow;A note on folding. These two composite shapes fold differently (see Folded vs Run). A single-action wrapper like Checkout({...}) is normally embedded inline as checkout.step inside a Job’s steps array — a call nested as a value inside another resource’s own properties, which is outside the fold subset, so a file using it falls back to the normal run path. A multi-job pipeline composite like NodePipeline({...}) is normally consumed the other way: bound to a local const, then each member re-exported separately (export const nodeWorkflow = node.workflow) — a top-level export whose value is a call result’s member access, which is exactly the composite-call shape folding resolves (chant #1023).
Checkout
Section titled “Checkout”Wraps actions/checkout@v4. Clones the repository.
import { Checkout } from "@intentius/chant-lexicon-github";
Checkout({}).step // Default checkoutCheckout({ fetchDepth: 0 }).step // Full historyCheckout({ ref: "develop" }).step // Specific branchCheckout({ submodules: "recursive" }).step // With submodulesProps: ref?, repository?, fetchDepth?, token?, submodules?, sshKey?
SetupNode
Section titled “SetupNode”Wraps actions/setup-node@v4. Installs Node.js with optional dependency caching.
import { SetupNode } from "@intentius/chant-lexicon-github";
SetupNode({ nodeVersion: "22" }).step // Node 22SetupNode({ nodeVersion: "22", cache: "npm" }).step // With npm cacheSetupNode({ nodeVersion: "20", cache: "pnpm" }).step // pnpm cacheProps: nodeVersion?, cache? ("npm" | "pnpm" | "yarn"), registryUrl?
SetupGo
Section titled “SetupGo”Wraps actions/setup-go@v5. Installs Go.
import { SetupGo } from "@intentius/chant-lexicon-github";
SetupGo({ goVersion: "1.22" }).stepSetupGo({ goVersion: "stable" }).stepProps: goVersion?, cache?
SetupPython
Section titled “SetupPython”Wraps actions/setup-python@v5. Installs Python.
import { SetupPython } from "@intentius/chant-lexicon-github";
SetupPython({ pythonVersion: "3.12" }).stepSetupPython({ pythonVersion: "3.12", cache: "pip" }).stepProps: pythonVersion?, cache? ("pip" | "pipenv" | "poetry"), architecture?
CacheAction
Section titled “CacheAction”Wraps actions/cache@v4. Caches files between workflow runs.
import { CacheAction } from "@intentius/chant-lexicon-github";
CacheAction({ path: "~/.npm", key: "npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}", restoreKeys: ["npm-${{ runner.os }}-"],}).stepProps: path, key, restoreKeys?
UploadArtifact
Section titled “UploadArtifact”Wraps actions/upload-artifact@v4. Uploads files as workflow artifacts.
import { UploadArtifact } from "@intentius/chant-lexicon-github";
UploadArtifact({ name: "build-output", path: "dist/", retentionDays: 7,}).stepProps: name, path, retentionDays?, ifNoFilesFound?
DownloadArtifact
Section titled “DownloadArtifact”Wraps actions/download-artifact@v4. Downloads previously uploaded artifacts.
import { DownloadArtifact } from "@intentius/chant-lexicon-github";
DownloadArtifact({ name: "build-output", path: "dist/",}).stepProps: name, path?
NodeCI
Section titled “NodeCI”A batteries-included composite that produces a full CI workflow and job. Generates a Workflow (push + PR on main) and a Job with checkout, setup-node, install, build, and test steps.
import { NodeCI } from "@intentius/chant-lexicon-github";
// Default: Node 22, npm, "build" + "test" scriptsconst { workflow, job } = NodeCI({});
// Customizedconst { workflow: w, job: j } = NodeCI({ nodeVersion: "20", packageManager: "pnpm", buildScript: "compile", testScript: "test:ci",});Props: nodeVersion?, packageManager? ("npm" | "pnpm" | "yarn" | "bun"), buildScript?, testScript?, installCommand?
The returned workflow and job can be exported directly:
const ci = NodeCI({ nodeVersion: "22", packageManager: "npm" });export const workflow = ci.workflow;export const build = ci.job;NodePipeline
Section titled “NodePipeline”A production-grade Node pipeline with separate build and test jobs connected by artifact passing. The build job uploads artifacts; the test job downloads them and runs tests with needs: ["build"].
import { NodePipeline } from "@intentius/chant-lexicon-github";
const { workflow, buildJob, testJob } = NodePipeline({ nodeVersion: "22", packageManager: "pnpm", buildScript: "build", testScript: "test:ci", buildArtifactPaths: ["dist/", "lib/"],});Props: nodeVersion?, packageManager? ("npm" | "pnpm" | "yarn" | "bun"), buildScript?, testScript?, installCommand?, buildArtifactPaths?, artifactName?, artifactRetentionDays?, runsOn?
Presets
Section titled “Presets”import { BunPipeline, PnpmPipeline, YarnPipeline } from "@intentius/chant-lexicon-github";
const bun = BunPipeline({}); // packageManager: "bun", uses oven-sh/setup-bun@v2const pnpm = PnpmPipeline({}); // packageManager: "pnpm"const yarn = YarnPipeline({}); // packageManager: "yarn"PythonCI
Section titled “PythonCI”Python CI with test and optional lint jobs. Supports pip and Poetry workflows.
import { PythonCI } from "@intentius/chant-lexicon-github";
const { workflow, testJob, lintJob } = PythonCI({ pythonVersion: "3.12", testCommand: "pytest --junitxml=report.xml --cov", lintCommand: "ruff check .",});
// Omit lint jobconst { workflow: w, testJob: t } = PythonCI({ lintCommand: null });
// Poetry modeconst poetry = PythonCI({ usePoetry: true });Props: pythonVersion?, testCommand?, lintCommand? (null to omit), requirementsFile?, usePoetry?, runsOn?
DockerBuild
Section titled “DockerBuild”Docker build and push using official Docker actions (login, setup-buildx, metadata, build-push). Configured for GitHub Container Registry by default.
import { DockerBuild } from "@intentius/chant-lexicon-github";
const { workflow, job } = DockerBuild({ registry: "ghcr.io", imageName: "ghcr.io/my-org/my-app", dockerfile: "Dockerfile", platforms: ["linux/amd64", "linux/arm64"],});Props: tag?, dockerfile?, context?, registry?, imageName?, tagLatest?, buildArgs?, push?, platforms?, runsOn?
DeployEnvironment
Section titled “DeployEnvironment”Deploy and cleanup job pair using GitHub Environments with concurrency control.
import { DeployEnvironment } from "@intentius/chant-lexicon-github";
const { deployJob, cleanupJob } = DeployEnvironment({ name: "staging", deployScript: ["npm run build", "npm run deploy"], cleanupScript: "npm run teardown", url: "https://staging.example.com",});Props: name (required), deployScript (required), cleanupScript?, url?, concurrencyGroup?, cancelInProgress?, runsOn?
Go CI with build, test, and optional lint jobs. Uses golangci-lint-action for linting.
import { GoCI } from "@intentius/chant-lexicon-github";
const { workflow, buildJob, testJob, lintJob } = GoCI({ goVersion: "1.22", buildCommand: "go build ./...", testCommand: "go test ./... -v -race",});
// Without lintconst noLint = GoCI({ lintCommand: null });Props: goVersion?, testCommand?, buildCommand?, lintCommand? (null to omit), runsOn?
Dependabot
Section titled “Dependabot”Models the repository’s dependency-update configuration (.github/dependabot.yml) as a chant resource, so it is emitted and lintable like a workflow. The composite ships safe defaults: a cooldown window on every ecosystem (so a version published moments ago — including a compromised one — is not adopted before anyone can react) and external code execution explicitly denied.
import { Dependabot } from "@intentius/chant-lexicon-github";
export const dependabot = Dependabot({ ecosystems: [ { packageEcosystem: "npm", directory: "/" }, { packageEcosystem: "github-actions", directory: "/" }, ], // cooldownDays defaults to 7, openPullRequestsLimit to 5});Props: ecosystems (required — each { packageEcosystem, directory?, interval? }), cooldownDays? (default 7), openPullRequestsLimit? (default 5)
For full control, construct the DependabotConfig resource directly with raw updates: entries. Two post-synth checks validate the emitted config: GHA057 (insecure-external-code-execution: allow) and GHA058 (no cooldown). See Lint Rules.
PrPlanReport
Section titled “PrPlanReport”Runs chant lifecycle plan <environment> --report markdown and posts (or updates) one sticky PR comment with the result — the compiled diff reaches the reviewer without being asked for. Guarded on github.event_name == 'pull_request', since the comment targets github.event.number.
import { PrPlanReport } from "@intentius/chant-lexicon-github";
export const plan = PrPlanReport({ environment: "prod", // credential setup — the plan queries the live system to classify drift before: ["aws sts get-caller-identity"],}).job;The job builds, plans, writes the markdown to plan.md with a hidden marker prepended (<!-- chant-pr-plan-report:prod --> by default — one per environment, so two environments get two comments), then finds a comment already carrying that marker and PATCHes it, or POSTs a new one. Same mechanism examples/github-pr-preview proved for the preview-environment comment: a scripted gh api call keyed on the marker, no marketplace action to pin.
The job needs its own Workflow (on: pull_request) declared alongside it — PrPlanReport returns only the job, the same as DeployEnvironment.
Props: environment (required), lexicon?, ownedOnly?, runsOn?, nodeVersion?, installCommand?, before?, postComment? (default true — the explicit opt-out), marker?
Caveats worth knowing:
- Opt-out is explicit.
postComment: falsestill runs the plan (useful to read in the job log, or ahead of turning the comment on) without posting anything. - The plan reads the live system, so the job needs cloud credentials — wire them via
beforeor CI variables, same asMrPlanReporton GitLab. - Forgejo gets this for free. The forgejo lexicon re-exports every github composite through its dialect (
@intentius/chant-lexicon-forgejore-exports@intentius/chant-lexicon-github), soPrPlanReportworks unchanged there — the dialect still drops the job’spermissionsand remaps its runner label, same as any other github-lexicon job.