DunneFlow · Tutorial
Gate CI with dunneflow check
Analyse your code in a CI job and fail the build only when DunneFlow finds something BROKEN.
dunneflow check reports a map's anomalies and exits non-zero only when a finding is
BROKEN. Suspect and informational findings are printed but do not fail the build, so the
gate does not trip every time the tool is merely unsure. In this tutorial you write a small
script that analyses a project and runs the check, first locally and then in any CI system.
You'll need#
- DunneFlow available to the CI job, either from a source checkout with Python 3.12+ and uv,
or the Linux application build, whose
dunneflowprogram is also the command line. - A project to check, in the job's working directory.
- Node.js 20 or newer on the runner if the project contains TypeScript, or use
--without typescript.
Steps#
-
Decide how the job calls DunneFlow. The script below uses a
DUNNEFLOWvariable so it works either way. From a source checkout, run the script from the checkout withDUNNEFLOW="uv run dunneflow"; with the Linux build, set it to the path ofdunneflow. -
Choose an explicit maps root. CI should never depend on a default location, so pass
--outputto every command. A directory inside the job's workspace, such asdunneflow-maps, is fine. -
Write the script. Save it as
dunneflow-check.sh:#!/bin/sh set -u DUNNEFLOW="${DUNNEFLOW:-uv run dunneflow}" SRC="${1:?give the source directory to check}" NAME="${2:-app}" MAPS="${MAPS:-dunneflow-maps}" $DUNNEFLOW analyze "$SRC" --name "$NAME" --output "$MAPS" --no-render || exit $? $DUNNEFLOW check "$NAME" --output "$MAPS" --verbose status=$? case $status in 0) echo "dunneflow: nothing BROKEN" ;; 1) echo "dunneflow: BROKEN findings, failing the build" ;; *) echo "dunneflow: could not read the map (exit $status)" ;; esac exit $status--no-renderskips the Markdown documents, which the gate does not need.--verboseprints each finding's detail and blind spot, so the log explains itself. -
Understand the exit codes.
checkexits 0 when nothing is BROKEN, 1 when at least one finding is BROKEN, and 2 when it cannot read the map at all: no map, a map from a different DunneFlow version, or an unfinished analysis. Treat 2 as a failure of the job, not a pass; an unreadable map must never report 0 broken. -
Run it locally.
DUNNEFLOW="uv run dunneflow" sh dunneflow-check.sh ~/code/some-project/src some-projectRead the findings list and the final count line. If your project contains TypeScript and the machine has no Node.js,
analyzerefuses before reading anything; add--without typescriptto theanalyzeline if the runner will not have Node. -
Add it to your CI. In your CI system, add a step that runs the script after checking out the code and making DunneFlow available. Most CI systems fail a step when its command exits non-zero, which is all the gate needs.
-
Narrow or widen what is printed.
--broken-onlyprints only the findings that fail the build;--alladds informational findings. Neither changes the exit code.--limitcaps how many findings are printed (default 40). -
Include tests if you analyse them. If you add
--include-teststoanalyze, add it tochecktoo, so dead-code reporting knows tests were included.
What you've learned#
checkfails only on BROKEN findings, and exits 2 when it cannot vouch for the map.- A CI script should pass an explicit
--outputand handle all three exit codes. - How
--no-render,--without,--verbose,--broken-onlyand--allfit a CI run.
Next#
- A mixed-language repository without Node.
- Reference: The command line and When it refuses.
Something unclear or out of date? Tell us.