Three steps: create a project, add one job to your pipeline, get size reports on every pull request.
On the dashboard, create a project and copy your API token (shown once). Add it to your repository secrets as FLASHBUDGET_TOKEN — Settings → Secrets and variables → Actions on GitHub.
After your firmware build step, upload the .elf. Two calls: one on pushes to main (records the baseline), one on pull requests (computes the diff and posts the comment).
# .github/workflows/size.yml
name: Firmware size
on:
push: { branches: [main] }
pull_request:
jobs:
size:
runs-on: ubuntu-latest
permissions:
pull-requests: write # to post the comment
steps:
- uses: actions/checkout@v4
# ... your existing build steps producing build/app.elf ...
- name: Upload build to FlashBudget
id: fb
run: |
RESP=$(curl -sf https://flashbudget.io/api/builds \
-H "Authorization: Bearer ${{ secrets.FLASHBUDGET_TOKEN }}" \
-F "elf=@build/app.elf" \
-F "branch=${{ github.head_ref || github.ref_name }}" \
-F "base_branch=main" \
-F "commit=${{ github.sha }}")
echo "$RESP" | python3 -c "
import json,sys,os
d = json.load(sys.stdin)
with open(os.environ['GITHUB_OUTPUT'],'a') as o:
o.write('exceeded=' + str(d.get('budget_exceeded', False)).lower() + '\n')
open('size-report.md','w').write(d.get('markdown',''))
"
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with: { path: size-report.md }
- name: Fail if memory budget exceeded
if: steps.fb.outputs.exceeded == 'true'
run: echo "::error::Memory budget exceeded" && exit 1
Any other CI (GitLab, Jenkins, Buildkite…) works the same way — it is a single curl call. The response contains the markdown report and a budget_exceeded boolean.
Give your project the real limits of your MCU, and the check fails automatically when a PR crosses them:
curl -X PATCH https://flashbudget.io/api/projects/me \
-H "Authorization: Bearer $FLASHBUDGET_TOKEN" \
-H "Content-Type: application/json" \
-d '{"flash_budget": 262144, "ram_budget": 65536}'
POST /api/projects — create project → token (once).
POST /api/builds — multipart elf + fields branch, base_branch, commit, target → totals, diff, markdown, budget_exceeded.
GET /api/projects/me — project info + last 200 builds.
PATCH /api/projects/me — update flash_budget / ram_budget.
Auth: Authorization: Bearer fb_…. Upload limit 8 MB. Beta: 50 builds/project/day, free.
Prefer to keep binaries on your machines? The diff engine is open source: fbdiff.