Skip to main content

Running checks before you push to GitHub

GitHub Actions checks every pull request, but a round trip through CI takes minutes and leaves a trail of "fix lint" commits. The same checks run locally in seconds.


From the command line​

# Interview YAML: structure, WCAG, and broken links
python3 -m dayamlchecker docassemble/MyPackage/data/questions/

# Word templates: document accessibility
python3 -m dayamlchecker docassemble/MyPackage/data/templates/

# Python: syntax, formatting, docstrings, tests
python3 -m compileall . -q
black .
docsig docassemble/
pytest

See the DAYamlChecker page for what each finding means and how to suppress one.

Some findings do not need a decision from you. Missing question ids, duplicate block ids, yes/no shorthands, and the first unlabeled field on a multi-field screen all have one sensible answer, and --fix writes them for you before reporting whatever is left:

python3 -m dayamlchecker --fix docassemble/MyPackage/data/questions/

It edits in place, so commit or stash first and read the git diff. To see the plan without writing anything, run python3 -m dayamlchecker.fixer on its own — its default mode is a dry run. See fixing findings automatically.

Skip the network when you are iterating

dayamlchecker requests every external link it finds, which is the slowest thing it does. Pass --no-url-check while you are working, and leave the link checking to CI.


Automating with Git pre-commit hooks​

A pre-commit hook runs every time you git commit. If a check fails, the commit is aborted, so a broken template never reaches your history in the first place. There are two ways to set one up.

pre-commit installs and runs hooks from many languages, and only passes it the files you actually staged.

1. Install it​

uv tool install pre-commit
# or
pip install pre-commit

2. Create .pre-commit-config.yaml​

In the root of your package repository:

repos:
# General file hygiene
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
# Docassemble interviews are multi-document YAML with Mako in them
exclude: ^docassemble/.*/data/questions/.*\.yml$

# Python formatting
- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black

# Python docstrings
- repo: https://github.com/jshwi/docsig
rev: v0.96.0
hooks:
- id: docsig
args: [--disable=description-not-capitalized]
exclude: (test_.*|setup)\.py$

# DAYamlChecker, from your own environment
- repo: local
hooks:
- id: dayamlchecker
name: DAYamlChecker
entry: dayamlchecker --no-url-check
language: system
files: ^docassemble/.*/data/(questions/.*\.ya?ml|templates/.*\.docx)$
pass_filenames: true

--no-url-check keeps every commit from making live HTTP requests to every link in your interview. CI still checks the links.

3. Install the hook​

pre-commit install
pre-commit installed at .git/hooks/pre-commit

4. What it looks like​

$ git add docassemble/MyPackage/data/questions/interview.yml
$ git commit -m "Add new interview screen"

Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
black................................................(no files to check)Skipped
docsig...............................................(no files to check)Skipped
DAYamlChecker............................................................Passed
[feature-branch 8a3f910] Add new interview screen
1 file changed, 25 insertions(+)

To run every hook over the whole repository, without committing:

pre-commit run --all-files

Option 2: a plain shell hook​

If you would rather not add a dependency, write .git/hooks/pre-commit yourself:

#!/bin/bash
# Check staged interview files before committing
set -e

echo "Checking Python syntax..."
python3 -m compileall . -q

STAGED=$(git diff --cached --name-only --diff-filter=ACM \
| grep -E '^docassemble/.*/data/(questions/.*\.ya?ml|templates/.*\.docx)$' || true)

if [ -n "$STAGED" ]; then
echo "Running DAYamlChecker on:"
echo "$STAGED"
# shellcheck disable=SC2086
dayamlchecker --no-url-check $STAGED
fi

echo "All pre-commit checks passed."

Then make it executable:

chmod +x .git/hooks/pre-commit

Unlike the pre-commit framework, a hook in .git/hooks/ is local to your own clone and is not shared with the rest of the team.


Skipping the hooks​

git commit --no-verify -m "WIP: save checkpoint"
warning

--no-verify only skips the local checks. The same checks run again on your pull request, so anything you skipped will come back.