Add manni meta to CI (GitHub Actions)
This page wires manni meta into GitHub Actions. Every push and pull request then validates your document metadata, and fails the job when a file is non-conformant. Each failure is reported as an inline annotation on the pull request diff.
You do not need to install manni meta into your repository. The recipes here run it
with npx, which fetches the published manni meta package on demand. The only
requirement on the runner is Node.js 24 or newer.
How the gate works
Section titled “How the gate works”manni meta is built to behave well in CI. Two properties carry the whole integration:
- Exit codes drive the gate. manni meta exits
0when every file is valid, and1when one or more files fail validation. It exits2on an operational or usage error, such as no inputs and no config. GitHub Actions treats any non-zero exit from a step as a failed step, so the metadata gate is enforced for free. There is no separate “if failures, then fail” wiring to maintain. --format githubproduces inline annotations. Instead of pretty console output, thegithubformat emits one GitHub Actions workflow command per error (::error file=...,line=...,col=...::...). GitHub turns each line into an annotation, pinned to the offending file and line in the pull request. Reviewers then see exactly what failed without opening the job log.
For the full contract, see Exit codes & PR annotations.
Standalone workflow
Section titled “Standalone workflow”Use this when metadata validation is its own job. This is the canonical recipe
from examples/manni.yml.
-
Create the workflow file. Add
.github/workflows/manni.yml:.github/workflows/manni.yml # Validate document metadata on every push and pull request.name: Validate metadataon:push:pull_request:jobs:manni:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v7- uses: actions/setup-node@v6with:node-version: 24# Validate all Markdown. `--format github` turns failures into inline# PR annotations; the nonzero exit code fails the job.- name: Validate frontmatterrun: npx -y @hawkeyexl/manni meta validate "**/*.md" --format github -
Adapt the targets. Replace
"**/*.md"with the paths, directories, or globs you want to check, for example"docs/**/*.md". Quote globs so the shell passes them to manni meta intact rather than expanding them itself. -
Commit and push. On the next push or pull request, the
manni metajob runs. A clean run passes; any validation failure fails the job and annotates the diff.
Let the config file supply the paths
Section titled “Let the config file supply the paths”If your repository has a manni.config.yaml at its root, its top-level
collections: list already names the document sets. A run with no positional
targets reads those. That lets the workflow step drop the glob entirely:
- name: Validate frontmatter # Targets come from collections: in manni.config.yaml at the repo root. run: npx -y @hawkeyexl/manni meta validate --format githubKeeping the target list in manni.config.yaml means the same command works
locally and in CI, and you change what gets validated in one place. Because a
collection is declared once for every manni tool rather than per tool, the
a11y gate beside this one reads the same list. See
Create your manni.config.yaml for both halves of
the file.
To gate one part of a docs set rather than all of it, name its collection.
--collection <name> is repeatable, one name per occurrence:
- name: Validate the published guides run: npx -y @hawkeyexl/manni meta validate --collection guides --format githubA scoped run does skip corpus
checks:, with a notice on
stderr, because a rule that spans the corpus cannot be answered by part of it.
Keep one unscoped job if you gate on those.
Add a step to an existing workflow
Section titled “Add a step to an existing workflow”You do not need a dedicated workflow. If you already run a docs or lint job, add manni meta as one more step. It needs a checkout and a Node.js 24+ toolchain. If the job already has those, the validation step is a single line.
jobs: # ... your existing jobs ...
metadata: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v6 with: node-version: 24 - name: Validate frontmatter run: npx -y @hawkeyexl/manni meta validate "docs/**/*.md" --format githubjobs: docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v6 with: node-version: 24
# ... your existing build/lint steps ...
- name: Validate frontmatter run: npx -y @hawkeyexl/manni meta validate "docs/**/*.md" --format githubVerify it works
Section titled “Verify it works”To confirm the gate fires, open a pull request that introduces a metadata error.
A Markdown file missing a required type field will do. Then check that:
- The
manni metajob is red. - The failing file shows an inline annotation on the changed line.
- A passing change leaves the job green.
If you want to see the same output locally before pushing, run the command from
your shell. Locally, --format github prints the raw ::error lines; drop the
flag to get the readable pretty report:
npx -y @hawkeyexl/manni meta validate "docs/**/*.md"