documentation
CI Integration
Automatically track bundle sizes on every push
Environment variables
Add your API token as a CI secret named DENDROBUNDLE_TOKEN. Never commit the raw token value.
The push endpoint accepts two optional query parameters:
| Parameter | Description |
|---|---|
branch |
Branch name (e.g. main, feat/new-header) |
commit |
Full 40-character commit SHA |
Both are optional but strongly recommended — without them, dendrobundle can't diff snapshots across branches. Full parameter and header documentation: API Reference.
GitHub Actions
name: CI
on:
push:
branches: ['**']
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- name: Push bundle stats
env:
DENDROBUNDLE_TOKEN: ${{ secrets.DENDROBUNDLE_TOKEN }}
run: |
curl -sS \
"https://dendrobundle.com/api/push?branch=${GITHUB_REF_NAME}&commit=${GITHUB_SHA}" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-d @dist/webpack-stats.json
GITHUB_REF_NAME and GITHUB_SHA are provided by Actions automatically — no manual extraction needed.
Large stats files (multi-MB): gzip the body —
gzip -c dist/webpack-stats.json | curl … -H "Content-Encoding: gzip" --data-binary @-. The server inflates it transparently (decompressed limit 150 MB). See the API reference.
GitHub PR checks (commit status + comment)
On top of recording the snapshot, dendrobundle can post the size result back to the pull request — a commit status (pass/fail against your budget) and a comment with the per-asset diff — so the bundle signal lands where review happens.
Add three push parameters and one header to the push step:
| Param / header | Value |
|---|---|
gh_repo (query) |
owner/name — the GitHub repository |
commit (query) |
the full commit SHA (use the PR head SHA on pull-request builds) |
pr (query) |
the pull-request number — omit to post only the commit status |
x-github-token (header) |
a token with statuses:write + pull_requests:write |
In GitHub Actions the built-in GITHUB_TOKEN already has those scopes once you grant them under permissions:. It is short-lived and is never stored by dendrobundle.
name: CI
on:
pull_request:
permissions:
contents: read
statuses: write
pull-requests: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- name: Push bundle stats + PR check
env:
DENDROBUNDLE_TOKEN: ${{ secrets.DENDROBUNDLE_TOKEN }}
run: |
curl -sS \
"https://dendrobundle.com/api/push?branch=${GITHUB_HEAD_REF}&commit=${{ github.event.pull_request.head.sha }}&gh_repo=${{ github.repository }}&pr=${{ github.event.pull_request.number }}" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "x-github-token: ${{ github.token }}" \
-H "Content-Type: application/json" \
-d @dist/webpack-stats.json
On
pull_requestevents usegithub.event.pull_request.head.shaforcommit— the built-inGITHUB_SHApoints at the temporary merge commit, so the status would attach to the wrong SHA and never show on the PR.
The PR feedback is best-effort: if GitHub is unreachable or the token lacks scope, the snapshot is still recorded and the push still succeeds. (Prefer zero token wiring? The dendrobundle GitHub App posts the same result as a native check run once installed — no per-push token needed.)
GitLab CI
stages:
- build
- push
build:
stage: build
image: node:20
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
push-bundle:
stage: push
image: curlimages/curl:latest
dependencies:
- build
script:
- |
curl -sS \
"https://dendrobundle.com/api/push?branch=${CI_COMMIT_REF_NAME}&commit=${CI_COMMIT_SHA}" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-d @dist/webpack-stats.json
variables:
DENDROBUNDLE_TOKEN: $DENDROBUNDLE_TOKEN
Add DENDROBUNDLE_TOKEN to Settings → CI/CD → Variables in your GitLab project. Mark it as masked.
CircleCI
version: 2.1
jobs:
build:
docker:
- image: cimg/node:20.11
steps:
- checkout
- run: npm ci
- run: npm run build
- run:
name: Push bundle stats
command: |
curl -sS \
"https://dendrobundle.com/api/push?branch=${CIRCLE_BRANCH}&commit=${CIRCLE_SHA1}" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-d @dist/webpack-stats.json
workflows:
ci:
jobs:
- build
Add DENDROBUNDLE_TOKEN under Project Settings → Environment Variables. CIRCLE_BRANCH and CIRCLE_SHA1 are built in.
Per-file format selection
The push endpoint auto-detects the format by inspecting the JSON structure. If you generate multiple stat formats in one build, pick the one with the most detail:
# webpack-stats gives module-level resolution — use this when available
curl -sS "https://dendrobundle.com/api/push?branch=$BRANCH&commit=$SHA" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-d @dist/webpack-stats.json
# esbuild metafile is the second-best option
curl -sS "https://dendrobundle.com/api/push?branch=$BRANCH&commit=$SHA" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-d @dist/meta.json
Failure handling
A non-200 response from the push endpoint means the snapshot was not recorded. The curl exit code will be non-zero, which will fail the CI step. If you want a failed upload to be non-blocking, append || true:
curl -sS ... -d @dist/webpack-stats.json || true
README badge
Every project has a live SVG badge showing its latest bundle size. The badge is public, cached, and turns red when the project is over budget. Drop this into your README (find the copy-paste snippet under Project → Settings → README badge):
[](https://dendrobundle.com/p/YOUR_PROJECT_SLUG)
An unknown slug renders a neutral placeholder rather than an error, so a badge never breaks a README.