Skip to content

Latest commit

 

History

History
373 lines (312 loc) · 32.8 KB

File metadata and controls

373 lines (312 loc) · 32.8 KB

Configuration reference

Code Foundry has one repository-owned control plane: .github/code-foundry.yml. init creates it, sync renders the selected baseline, and doctor checks local and GitHub-facing prerequisites.

npx code-foundry init
# edit .github/code-foundry.yml
npx code-foundry sync
npx code-foundry doctor

The generated file is deliberately explicit. Keep it under version control and change it directly rather than passing one-off flags to sync.

How configuration is applied

repository manifests and source
            |
            v
  .github/code-foundry.yml
            |
            +--> detected language and package-manager setup
            +--> standard workflow callers
            +--> runtime repository and version
            +--> validation, release, license, and cache policy

toolchain: auto reuses an existing .mise.toml; otherwise it uses native language tooling. Set toolchain: native to prohibit mise or toolchain: mise to require an existing mise configuration.

Repository and runtime

Key Values Notes
version 1 Configuration schema version.
profile auto, application, monorepo, minimal Repository shape; auto detects it.
languages comma-separated language names Supported values are typescript, rust, python, and solidity.
package_manager bun, pnpm, yarn, npm, none JavaScript package-manager policy.
toolchain auto, native, mise Environment setup policy.
runtime_repository OWNER/REPO Source of reusable workflows and runtime code.
runtime_ref tag or commit Runtime version used by generated callers.
features all or a list See Feature selection.
draft_protection true, false Skip generated runner-heavy gates for draft PRs when false.
billing_paused true, false Disable Dependabot version updates while CI billing is paused.
dependency_updater dependabot, renovate, none Which dependency-update bot sync manages; see Feature selection.
codeql auto, true, false Enable CodeQL when the repository and GitHub plan support it.
dependency_review auto, true, false Enable Dependency Review when supported.
runner and *_runner GitHub runner labels Override the default runner per workflow.

For codeql: auto and dependency_review: auto, public repositories use the available GitHub security checks and private repositories require the relevant capability. Set either key to false when the check is unavailable or not wanted. CodeQL is omitted from the generated validation caller; Dependency Review remains a conditional step inside Security rather than a separate check.

Code Foundry runner-heavy validation, security, qualification, and Cloudflare Deployment jobs protect draft pull requests by default. The draft_protection configuration key defaults to true; set it to false only when the repository intentionally runs generated gates for draft PRs. Cloudflare reusable-workflow callers use their equivalent draft-protection input. These opt-outs affect CI/deployment gates only and do not disable Draft Guard or draft-PR automation.

The CI_BILLING_PAUSED repository variable gates every generated workflow job, but Dependabot's update runs execute under the dynamic event and never see that variable. Set billing_paused: true alongside the variable and re-run sync so the rendered dependabot.yml sets open-pull-requests-limit: 0 and drops the update cadence to monthly for every ecosystem. Removing the flag and syncing again restores the active template. npx code-foundry ci status reports when a paused repository still has Dependabot updates active.

Feature selection

Use features: all or a comma/space-separated list. The canonical validation feature is validation; the legacy names ci, test, security, and codeql remain aliases for compatibility. Other selectable features are:

  • draft-pr — create or update development pull requests.
  • release-pr — promote staging into main in the staging-release topology.
  • release — run Release Please and optional package publication.
  • dependabot — install the language-aware Dependabot configuration.

The dependency_updater key selects which dependency-update bot sync manages, and an explicit value wins over the dependabot feature (including features: all):

  • dependabot (default) — render .github/dependabot.yml whenever the dependabot feature is selected; existing repositories are unaffected.
  • renovate — never render .github/dependabot.yml and remove an existing one; install renovate.json from the runtime template only when the repository has none. A repository-owned renovate.json is never modified.
  • none — never render .github/dependabot.yml, remove an existing one, and install nothing.

Installing renovate.json does not schedule update runs: a repository still needs the Renovate GitHub App or a self-hosted runner. The billing_paused Dependabot pause applies only while dependency_updater is dependabot.

The release-integrity and OpenCode Security callers are installed independently of feature selection. OpenCode Security is disabled unless the repository or organization variable OPENCODE_SECURITY is true and the OPENCODE_API_KEY secret exists. opencode_security_model optionally replaces the generated scanner model.

Merge queues are a separate opt-in because they need a stable runtime pin:

merge_queue: true

See Merge queue validation before enabling it.

Validation and quality

Key Values Purpose
performance auto, true, false Discover, require, or disable performance checks.
performance_command JSON argv array or array of argv arrays Ordered commands for a non-package performance harness.
performance_profile empty or node-package Shared package import, memory, archive, and dependency audit.
performance_budget_file repository-relative path Budget file for node-package; defaults to performance-package-budgets.json.
eval auto, true, false Discover, require, or disable the deterministic eval tier.
eval_command JSON argv array Explicit harness command when there is no eval package script.
eval_report_file repository-relative path Report validated against the eval contract; defaults to eval-results/result.json.
eval_budget_file repository-relative path Optional budget file; defaults to eval-budgets.json.
eval_runner runner label Runner for the Validation / Eval lane; defaults to the repository runner. Browser evals need a Chrome-capable runner such as ubuntu-latest.
required_capabilities comma-separated task names Fail closed when a required task or coverage evidence is unavailable.
coverage_enforcement auto, required, off Shared coverage-report policy.
coverage_minimum 0–100 Minimum percentage; defaults to 80.
coverage_metrics lines, functions, branches, statements Metrics checked by the coverage gate.
coverage_report comma-separated repository paths Istanbul JSON summary or LCOV evidence files.
pre_commit_build true, false Run the project's build in the local pre-commit gate. Defaults to false; see Pre-commit gate.
filter_<task> comma-separated repository path globs Skip a lane when no changed path matches; see Lane path filters.
rust_sccache true, false Install sccache and wrap rustc so compile artifacts survive manifest/lockfile churn.
rust_nextest true, false Install cargo-nextest and prefer cargo nextest run over cargo test in Rust test lanes.
e2e_shards 1–8 Fan the Validation / Test / E2E job into one runner per shard. The repository's test:e2e/e2e script receives E2E_SHARD_INDEX and E2E_TOTAL_SHARDS and partitions itself (Playwright takes --shard=$E2E_SHARD_INDEX/$E2E_TOTAL_SHARDS); each shard owns a runner-local test database, so shards stay isolated.
release_batching_schedule five-field numeric cron Batch Release Please into scheduled windows. Ordinary pushes skip the producer; release-PR squashes and manual dispatches still run. Batched releases are created privately as drafts and published with prerelease visibility atomically. Manual dispatches publish stable hotfixes. Absent, releases publish per merge. Requires a single root Release Please package.
release_batching_prerelease true, false Defaults to true with a schedule. Sync enables draft and force-tag-creation in Release Please; the producer publishes the draft with the selected visibility. false keeps scheduled releases stable-visible.
release_batching_soak_hours 1–336 Generate a daily promoter that promotes the newest prerelease when the oldest candidate since the last stable has soaked this many hours, stitching batch notes. Requires a batching schedule and prerelease publication. Set STABLE_PROMOTION_HELD=true in repository Actions variables to hold scheduled and manual promotion; force overrides the hold or soak, and version selects a plain semantic version.
release_batching_qualification_workflow workflow filename (for example release-assets.yml) Require the latest release-event run of this workflow for the candidate tag’s exact source commit to succeed before stable promotion. Requires a batching soak. Running, missing, failed, or cancelled runs hold promotion, including named and forced promotions; force only bypasses hold and soak. The promoter receives read-only Actions access.

Supported task capabilities are format, lint, type_check, build, unit, integration, e2e, smoke, eval, and performance. coverage is a policy capability that also requires unit tests. See Required capabilities and task evidence. The eval tier runs the repository's own harness against the shared report contract and optional budgets; see Evals.

The shared performance job discovers performance:check, then perf:check, in JavaScript repositories. Other repositories can provide one command or an ordered list of argv arrays without shell interpolation:

performance: true
performance_command: '["python3", "scripts/performance_audit.py", "--check"]'
performance_runner: ubuntu-latest

The node-package profile supports cold-import, memory, package-size, file-count, and production-dependency budgets. Supported budget names are coldImportP50Ms, coldImportP95Ms, coldImportRssMaxBytes, coldImportRelativeP50, packedBytes, unpackedBytes, packageFileCount, packageMapFileCount, and productionDependencyCount. Reports are written under performance-results/ and are uploaded when present.

performance: true makes the performance task required. Use performance: auto to keep discovery optional. Product-quality profiles are repository-owned manifests invoked by existing build or E2E commands; they are not activated by a configuration key. See Product quality profiles.

Pre-commit gate

code-foundry sync installs .githooks/pre-commit, which runs code-foundry pre-commit when the repository depends on code-foundry. The gate is change-aware and never runs work for code the commit cannot affect:

  • With nothing staged it exits immediately. git diff --cached --check still blocks whitespace errors in every staged change.
  • Oxfmt and Oxlint check only the staged files they support, honoring their own ignore patterns. Staging .oxfmtrc.json, .oxlintrc.json, or their *.config.* equivalents widens that tool to the whole repository through the repository's format:check/lint script. A repository without Oxfmt or Oxlint keeps its own script, which runs only when a matching file is staged.
  • The project's type-check/typecheck/type:check script (or tsc --noEmit) runs only when .ts, .tsx, .mts, .cts, or tsconfig*.json files are staged, and for JavaScript sources when the repository type-checks them with a root jsconfig.json or checkJs.
  • Ruff checks only staged Python files (--force-exclude), or the whole repository when pyproject.toml, ruff.toml, or a requirements file is staged. Staged Rust sources or Cargo.toml run cargo fmt --check and Clippy.
  • The build does not run at commit time; CI and explicit commands own it. Set pre_commit_build: true to run the build script (or cargo build) when code is staged.

Tools read working-tree contents, so a partially staged file is checked as it exists on disk. Task scripts that declare dependencies of their own, such as a Turborepo typecheck task with dependsOn: ["^build"], still run them; drop that dependency to keep type checks build-free.

Release and branch policy

Key Values Purpose
release_type auto, node, python, rust, simple, none Select a release manifest; auto detects one.
npm_publish true, false Opt into npm publication.
license gpl-3.0-or-later, agpl-3.0-or-later, apache-2.0, mit, preserve, none License policy for initialized repositories.
git_workflow direct, staging-release Choose the branch topology.
merge_strategy squash or rebase Required topology-specific merge method.
release_merge_strategy squash or rebase Required method for Release Please version PRs.
staging_validation_mode fast, audit Validation tier for pull requests into staging; staging-release only.

direct is the default: feature branches and release PRs target main, and both merge with squash. staging-release sends feature branches to staging, uses rebase for the staging → main promotion and Release Please PR, and keeps feature PRs into staging on squash. sync, doctor, and release automation reject a strategy that does not match the selected topology.

# Preview/staging environment
release_type: auto
git_workflow: staging-release
staging_validation_mode: fast
merge_strategy: rebase
release_merge_strategy: rebase

Use simple with version.txt when no package manifest exists. Use none to skip automated releases. npm_publish affects generated consumer release callers; Code Foundry's own repository uses the qualified publication path described in Qualified publication. A self-sync of the Code Foundry source does not advance its own runtime_ref; this prevents a self-referencing runtime pin from creating a release loop.

Synchronization and extensions

Key Values Purpose
sync_mode overlay, strict Synchronization policy; overlay is the default.
custom_workflows preserve Custom workflows are always preserved; other values are rejected.
post_release true, auto, false Enable a post-release delivery hook.
post_release_workflow workflow filename Workflow dispatched by the post-release hook.
post_release_mode auto, workflow-dispatch, release-event, disabled Select the hook delivery mechanism.

sync_mode accepts overlay (the default) or strict; sync validates the selected value before writing. Custom workflows remain preserved in either mode, and custom_workflows must remain preserve. See Extension points.

Caching and remote caching

The standard workflows use lockfile- and configuration-keyed caches. Their repository variables, rather than application source files, control cache behavior:

  • REPO_FOUNDRY_CACHE_PACKAGES controls package-store caching.
  • REPO_FOUNDRY_CACHE_BUILD controls build-cache reuse.
  • turbo_remote: auto, true, or false declares the remote-cache policy; doctor --github warns when enabled remote caching lacks TURBO_TOKEN or TURBO_TEAM.
  • TURBO_TOKEN and TURBO_TEAM provide the Turborepo remote-cache credentials.

Use these controls only after measuring a repeatable benefit. See Caching and remote caching.

Lane path filters

Validation lanes run their full suite by default. Repositories with clearly separated areas — for example a Rust workspace next to a web app — can opt any task lane into path filtering so a change that cannot affect the lane skips its setup and execution steps:

filter_integration: 'src/**/*.py,tests/**,pyproject.toml,uv.lock'
filter_eval: 'eval/**,crates/**,src/**'
filter_e2e: 'apps/**,src/**'

filter_<task> accepts the same task names as required_capabilities. Globs are repo-relative: **/ matches any directory depth, * stays inside one path segment, ? matches one character, and a trailing / is shorthand for dir/**.

The gate is fail-open by design: a task without a configured filter, a diff that cannot be resolved (shallow checkout edge, missing base ref), or an empty change set all keep the lane running. Paths are evaluated against base...head for pull requests and before..after for pushes; other events always run. Because filters only decide whether a lane executes, required checks stay green and the aggregate gate sees a normal success.

Diff resolution only runs for lanes that have a filter configured, so repositories using a single filter pay one shallow fetch per change instead of one per lane. An orchestrator that has already resolved the change set can inject it for a lane through a newline-delimited CHANGED_PATHS environment variable; an empty or missing value falls back to local resolution, so an injection can never widen a skip.

Security lanes and CodeQL are never filterable: their coverage is structural, not change-scoped.

Rust CodeQL tuning

Rust CodeQL defaults to one full scan with one worker. Larger multi-crate repositories can opt into bounded parallelism:

codeql_rust_shards: '["crates/api", "crates/worker"]'
codeql_rust_threads: 2
codeql_rust_max_parallel: 2

Each shard must contain tracked Rust source. Absolute paths, parent traversal, duplicates, empty scopes, and more than eight shards are rejected. Use ["all"] when complete, non-overlapping source scopes are not available.

Every lane rendered from this configuration (pull-request validation, the default-branch scan, the scheduled audit, and merge queues) receives the same shard list, and the CodeQL Detect job fails closed when caller workflows drift apart. Keep them aligned: each shard uploads a SARIF category keyed by a hash of the shard scope, GitHub code scanning baselines every category it has seen on the default branch, and the code-scanning merge gate waits for results in every tracked category. Two practical consequences:

  • Treat codeql_rust_shards as add-only while the gate tracks categories. Removing a shard orphans its category on the default branch, and pull requests then stall on "Code scanning is still expecting N results" until the category is covered again.
  • To retire a category for real, delete its code-scanning analyses (Code security → Code scanning → analyses, or the code-scanning analysis deletion API) after removing the shard, then re-run sync. Covering retired categories in the shard list keeps the gate green but re-runs their analysis on every pull request and is not a substitute for cleanup.

On pull requests without a code-scanning merge gate, analyzers run only for languages with changed files, and Rust shards run only when their scope (or a workspace-wide Cargo manifest or toolchain file) changed; unchanged matrix entries report Not applicable instead of analyzing. Repositories whose rulesets enforce a code-scanning requirement are detected automatically and analyze everything, because that merge gate waits for results in every tracked category. Push, schedule, and merge-queue events always analyze the complete set so the default branch keeps one full, comparable baseline.

Cloudflare Workers

Repositories that deploy to Cloudflare Workers can use the opt-in verified delivery workflow with fixed Preview and Production environments, candidate verification, and version-identity promotion. Pin both the reusable workflow reference and runtime-ref to the same reviewed 40-character commit SHA. Provide CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID in the consumer repository and configure environment reviewers separately.

The legacy cloudflare-deploy.yml workflow remains available for direct (unverified) deployments. It runs wrangler versions upload for previews and wrangler deploy for production, records a GitHub deployment plus status, and respects CI_BILLING_PAUSED. With deploy-tool: cf it instead deploys through the Cloudflare cf CLI: production runs cf-wrangler build plus cf deploy --prebuilt (consuming the project's cf Build Output), previews run cf previews deploy named after the pull request or branch, and the cf/wrangler CLIs must be devDependencies of the deployed package (the build step installs them), so build-script is required. Deployment URLs and version IDs are extracted from the same job outputs either way. Preview deployment records use the pull request head SHA when called from a PR, which lets GitHub show the completed preview in the PR's Deployments section; direct pushes use the workflow SHA. Its legacy-compatible Wrangler default is latest; callers should prefer local or provide an exact wrangler-version for reproducibility. Bun consumers may pass build-script, install-working-directory, and bun-version; the runtime installs the frozen lockfile and builds the Worker before invoking Wrangler. Bun-backed callers invoke Wrangler through bunx so OpenNext's production delegation resolves the workspace-local opennextjs-cloudflare binary; callers without build-script retain the npm/npx path. See Verified Cloudflare delivery.