Check your paper in CI¶
Run Fledge on every push to a paper repository on GitHub and you get the findings as GitHub annotations, plus the verified submission ZIP, the rebuilt PDF and the reports as a downloadable artifact. A broken citation or a missing file then shows up when you push it, not on submission day.
The workflow below uses a macOS runner because macOS is the platform on which Fledge’s sandbox and builds are validated; see limitations. Linux runners will be documented once the Linux sandbox passes on a live Linux host.
The workflow¶
Save this as .github/workflows/fledge.yml in the paper repository. It assumes
the repository root is the paper and main.tex is the main file; change both to
match your project.
name: Check paper
on:
push:
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
fledge:
runs-on: macos-latest
timeout-minutes: 45
env:
HOMEBREW_NO_AUTO_UPDATE: "1"
HOMEBREW_NO_INSTALL_CLEANUP: "1"
steps:
- name: Check out the paper
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: "3.13"
- name: Install TeX and Poppler
run: |
brew install --cask basictex
brew install poppler
echo "/Library/TeX/texbin" >> "$GITHUB_PATH"
# Add any other packages your paper needs to the tlmgr install line.
- name: Install TeX packages
run: |
sudo /Library/TeX/texbin/tlmgr update --self
sudo /Library/TeX/texbin/tlmgr install latexmk biber biblatex hyperref
- name: Install Fledge
run: python -m pip install fledge-latex
- name: Check the paper
run: |
mkdir -p "$RUNNER_TEMP/fledge"
status=0
fledge check . --main main.tex --output-format ci --quiet \
--json-report "$RUNNER_TEMP/fledge/check.json" \
--html-report "$RUNNER_TEMP/fledge/check.html" || status=$?
[ "$status" -le 2 ] || exit "$status"
- name: Prepare the submission
run: |
status=0
fledge prepare . --main main.tex \
--output "$RUNNER_TEMP/fledge/submission" \
--output-format ci --quiet \
--html-report "$RUNNER_TEMP/fledge/prepare.html" || status=$?
[ "$status" -le 2 ] || exit "$status"
- name: Upload the submission and reports
if: ${{ !cancelled() }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: fledge-submission
path: |
${{ runner.temp }}/fledge/submission/submission.zip
${{ runner.temp }}/fledge/submission/manuscript.pdf
${{ runner.temp }}/fledge/submission/report.json
${{ runner.temp }}/fledge/check.json
${{ runner.temp }}/fledge/check.html
${{ runner.temp }}/fledge/prepare.html
if-no-files-found: ignore
retention-days: 14
Each action is pinned to a full commit SHA with its version in a comment, as in Fledge’s own workflows; a tool such as Dependabot can keep them current.
What the steps do¶
TeX and Poppler. BasicTeX is a small TeX Live distribution, and
tlmgraddslatexmk, Biber and BibLaTeX. A package your paper needs but the runner lacks is reported as a build failure; add it to thetlmgr installline. Pin the version of Fledge, for examplefledge-latex==0.3.0, if you want the same checks on every run.--output-format ciprints each finding as a GitHub annotation, and--quietleaves out the progress messages. Fledge also reads afledge.tomlin the repository, so settings and presets apply in CI exactly as they do on your machine.Reports and output go to the runner’s temporary directory because Fledge never writes into the project it reads.
--outputmust name a directory that does not exist yet.preparerepeats the checks, then rebuilds the PDF from the submission ZIP it wrote and compares it with the original.checkcomes first for a quicker verdict;preparebuilds again, so the job takes longer.The upload runs even when a step fails, so the reports are available for the failing run. Files that were never written, such as the ZIP after a blocked check, are skipped.
Exit codes¶
Fledge’s exit code decides whether the job passes. The workflow above continues on 0, 1 and 2 and fails on everything else:
Exit |
Meaning |
Job |
|---|---|---|
0 |
Everything in scope passed |
Passes |
1 |
Passed with advisories: warnings need review |
Passes; the warnings stay visible as annotations |
2 |
Passed only because of exceptions you accepted in |
Passes |
3 |
Blocked: a required check failed or lacked evidence |
Fails |
4, 64, 130 |
Error (including an internal failure), invalid command line, or interrupted |
Fails |
To fail the job on advisories as well, change -le 2 to -le 0. The
reports page explains every code.
Cost and other runners¶
GitHub-hosted runners are free for public repositories. For private repositories, a macOS minute costs more than a Linux minute; see GitHub Actions billing. Every run installs BasicTeX and its packages again, which adds to the minutes used.
Fledge cannot build on a Windows runner because Windows has no build sandbox. A Linux runner is the cheaper option once the Linux sandbox has been validated; this page will show that workflow then.