Share a Papermill run
Papermill solved the boring half of notebooks: parameterize one, execute
it headlessly, get an output notebook per parameter set. What it does not
solve is that the output is another .ipynb — a file format whose
audience is people with a Jupyter install and time.
The run that matters is the one someone else reads.
Publish it
papermill weekly.ipynb "out-$REGION.ipynb" \
-p region "$REGION" -p as_of "$(date +%F)" || true
jupyter nbconvert --to html --embed-images --no-input "out-$REGION.ipynb"
curl -fsS -X PATCH \
"https://commareports.com/api/v1/reports/$COMMA_REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html "out-$REGION.html" \
--arg title "Weekly — $REGION — $(date +%F)" \
'{title: $title, html: $html}')"
|| true on the papermill line is deliberate. Papermill exits non-zero
when a cell raises and still writes the traceback into the output
notebook, and that is precisely the run you want at a URL rather than
buried in a CI log.
PATCH on a saved report id per region is the shape that pays off: one
stable URL per parameter set, a revision per run, and a diff between any
two runs. A fresh POST every execution gives you a graveyard of
one-off links instead.
Use a scoped token with reports:write only.
What the URL changes
- A run has a history. Revision N versus revision N−1 is the actual question — did the number move, and when. See revisions and diffs.
- Reviewers annotate the run. A threshold that fired, a segment that looks wrong: the note anchors to the output cell. See commenting on HTML.
- Failures are readable. The traceback renders as a page rather than as log output someone has to go find.
- Private by default — team, domain-gated, or named reviewers. See the sharing model.
Put it on a cron
Papermill exists so notebooks can run unattended, so the publish should be unattended too. A routine executes the notebook and refreshes the report on a schedule — see scheduled HTML reports and weekly analytics digests.
Limits
- HTML body: 5 MB.
--embed-imagesinlines figures; a plot-heavy run approaches the ceiling. Downsample, or publish a summary notebook and attach the full output as an asset. - Scripts run, sandboxed:
allow-scripts, noallow-same-origin. - 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.
Related
- nbconvert exports — the render step on its own
- Jupyter notebooks · Cron for agents
- Publish from CI · API tokens