CI Integration
cmakefmt is designed to be a zero-friction CI step. Use --check to fail the
build when files are not formatted, or --in-place to auto-format and commit
the result.
GitHub Actions
Section titled “GitHub Actions”The official cmakefmt/cmakefmt-action
installs the correct binary for the runner OS, adds it to PATH, and runs
cmakefmt with sensible defaults. No Rust toolchain or Python environment is
required on the runner.
The action exposes two high-level inputs that cover almost every workflow:
modeselects whatcmakefmtdoes:check(verify formatting),diff(verify and print a unified diff),fix(reformat in place), orsetup(install only, do not run).scopeselects which files are processed:all(the whole repository),changed(files modified since the base ref), orstaged(Git-tracked files in the index).
The paths, since, version, and working-directory inputs cover the rest.
Reach for args only when you need flags none of the structured inputs
expose.
Strict whole-repo check (recommended starting point)
Section titled “Strict whole-repo check (recommended starting point)”The default behaviour: run cmakefmt --check --report-format github . over
the entire repository. The job fails on the first file that would change, and
inline annotations on the pull request show exactly where.
- uses: actions/checkout@v6- uses: cmakefmt/cmakefmt-action@v2Changed-file check for incremental rollout
Section titled “Changed-file check for incremental rollout”When adopting cmakefmt in an existing repository without reformatting every
CMake file on day one, scope the check to files modified since the base ref:
- uses: actions/checkout@v6 with: fetch-depth: 0 # required so the action can resolve the base ref- uses: cmakefmt/cmakefmt-action@v2 with: mode: diff scope: changedOn pull requests, scope: changed compares against
origin/${{ github.base_ref }}. On push events, it compares against the
push event’s before commit. The since input lets you override the base
ref when you want to compare against, for example, the most recent tag.
Auto-format and commit
Section titled “Auto-format and commit”Reformat files on the runner and push the result back. Combine mode: fix
with a commit step:
- uses: actions/checkout@v6- uses: cmakefmt/cmakefmt-action@v2 with: mode: fix- name: Commit any reformat uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "chore: auto-format CMake files"Install only, run yourself
Section titled “Install only, run yourself”When you want full control over the cmakefmt invocation, install the
binary with mode: setup and run it directly:
- uses: cmakefmt/cmakefmt-action@v2 with: mode: setup- run: cmakefmt --check --report-format sarif . > cmakefmt.sarifPin a specific version
Section titled “Pin a specific version”The action installs the latest release by default. To pin to a specific version (e.g. for reproducible CI on long-lived branches):
- uses: cmakefmt/cmakefmt-action@v2 with: version: "1.5.0"Monorepo subdirectory
Section titled “Monorepo subdirectory”When CMake files live under a subdirectory rather than the repository root,
point the action at it with working-directory:
- uses: cmakefmt/cmakefmt-action@v2 with: working-directory: cpp/Full example
Section titled “Full example”name: Format check
on: [push, pull_request]
jobs: cmakefmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: cmakefmt/cmakefmt-action@v2The complete list of inputs and outputs is documented in the
cmakefmt-action README.
GitLab CI
Section titled “GitLab CI”Download the pre-built Linux binary directly from GitHub Releases:
cmakefmt: stage: lint image: ubuntu:latest before_script: - apt-get update -qq && apt-get install -y -qq curl - | LATEST=$(curl -sI https://github.com/cmakefmt/cmakefmt/releases/latest \ | grep -i '^location:' \ | sed 's|.*/tag/v||;s/[[:space:]]//g') curl -sSL \ "https://github.com/cmakefmt/cmakefmt/releases/download/v${LATEST}/cmakefmt-x86_64-unknown-linux-musl.tar.gz" \ | tar -xz -C /usr/local/bin script: - cmakefmt --check .Or install via Cargo if you already have a Rust image:
cmakefmt: stage: lint image: rust:latest cache: paths: - $CARGO_HOME/bin/ script: - cargo install cmakefmt-rust --quiet - cmakefmt --check .Azure Pipelines
Section titled “Azure Pipelines”steps: - script: | LATEST=$(curl -sI https://github.com/cmakefmt/cmakefmt/releases/latest \ | grep -i '^location:' \ | sed 's|.*/tag/v||;s/[[:space:]]//g') curl -sSL \ "https://github.com/cmakefmt/cmakefmt/releases/download/v${LATEST}/cmakefmt-${LATEST}-x86_64-unknown-linux-musl.tar.gz" \ | tar -xz --strip-components=1 -C /usr/local/bin displayName: Install cmakefmt - script: cmakefmt --check . displayName: Check CMake formattingOr with Cargo:
steps: - script: cargo install cmakefmt-rust --quiet displayName: Install cmakefmt - script: cmakefmt --check . displayName: Check CMake formattingBitbucket Pipelines
Section titled “Bitbucket Pipelines”pipelines: default: - step: name: Check CMake formatting image: rust:latest caches: - cargo script: - cargo install cmakefmt-rust --quiet - cmakefmt --check .Docker
Section titled “Docker”Pre-built images are published to GitHub Container Registry on every release:
docker run --rm -v "$(pwd):/work" -w /work ghcr.io/cmakefmt/cmakefmt --check .Or format a single file via stdin:
cat CMakeLists.txt | docker run --rm -i ghcr.io/cmakefmt/cmakefmt -Pin a specific version:
docker run --rm -v "$(pwd):/work" -w /work ghcr.io/cmakefmt/cmakefmt:1.5.0 --check .You can also build the image locally from the repository root:
docker build -t cmakefmt .pre-commit
Section titled “pre-commit”Add a local hook to your .pre-commit-config.yaml. This runs cmakefmt --check
on every staged CMake file before the commit is created:
repos: - repo: local hooks: - id: cmakefmt name: cmakefmt language: system entry: cmakefmt --check files: '(CMakeLists\.txt|\.cmake)$' pass_filenames: trueInstall the hook once per clone:
pre-commit installYou can also run it manually across all files:
pre-commit run cmakefmt --all-filesCheck only changed files
Section titled “Check only changed files”When working on large repositories, limit formatting checks to files changed since a given ref to keep CI fast:
# Check files changed since the last tagcmakefmt --check --changed v0.1.0
# Check only staged files (useful locally)cmakefmt --check --staged
Docs track main. For historical docs, check out a release tag in
the repository and build
docs/ locally.