CI: guard against reading data-lectures over the LFS media host - #58
Merged
Conversation
Code cells here execute in the reader's browser, so a dataset read on the
wrong host is a reader-visible failure on every page view. This repo's CI
cannot see it: ci.yml runs `myst build --html` with no execution, so nothing
fetches the URL until a reader does. The data-audit dashboard that would
catch it lives in QuantEcon/data-lectures and never runs on a pull request
here — its detection lag is up to seven days.
media.githubusercontent.com is the LFS *media* endpoint and routes per path,
serving a file only where that path is LFS-tracked in the repo the URL names.
Everything data-lectures publishes is plain git, so that host never resolves
for it — and the six datasets folded in from high_dim_data are read from it
here today, in heavy_tails, inequality and mle.
Only the media host is checked. Rule 5's github.com/*/raw/ form is wrong in a
code cell but correct in a {download} role or a prose link, and this repo has
both today (french_rev, inflation_history) — a grep cannot tell them apart,
so that rule stays with the strict audit, which scans code cells only.
Matches zero lines today (verified: exit 1), so it goes green on merge and is
armed before the fold rather than alongside it.
Gate 2 of QuantEcon/workspace-lectures#23 step 3. See QuantEcon/data-lectures
PLAN.md, repoint rule 6.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
❌ Deploy Preview for beautiful-dodol-cb9543 failed.
|
|
📖 Netlify Preview Ready! Preview URL: https://pr-58--beautiful-dodol-cb9543.netlify.app (141d42c) ✨ Browse the preview at the URL above. |
There was a problem hiding this comment.
Pull request overview
Adds a lightweight CI alarm to detect any accidental use of the Git LFS media host for QuantEcon/data-lectures URLs within lectures/, catching reader-visible runtime 404s that this repo’s current HTML-only build won’t surface.
Changes:
- Introduces a new GitHub Actions workflow that greps
lectures/formedia.githubusercontent.com/media/QuantEcon/data-lectures. - Emits a workflow error and fails the job if any such URL is present.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Copilot review on #58. The job greps a checkout and writes nothing, but this repo's default workflow permission is `write`, so it was receiving a token that could also approve pull requests. ci.yml already sets its own block. The error message opened with a bare imperative naming the *correct* host — "Read data-lectures over raw.githubusercontent.com" — which reads as a description of what was found rather than as the fix. Reordered to name the defect first. The intro twin avoids this by carrying a "never media.githubusercontent.com" clause; that clause is deliberately absent here, since repoint rule 5 bars the github.com/*/raw/ form for code cells that execute in the reader's browser. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
📖 Netlify Preview Ready! Preview URL: https://pr-58--beautiful-dodol-cb9543.netlify.app (65c5c0b) ✨ Browse the preview at the URL above. |
mmcky
added a commit
to QuantEcon/lecture-python-intro
that referenced
this pull request
Aug 10, 2026
* CI: least-privilege token for the data URL guard The job greps a checkout and writes nothing, but this repo's default workflow permission is `write`, so it was receiving a token that could also approve pull requests. Raised by Copilot on the wasm twin, QuantEcon/lecture-wasm#58, which carries the same one-line change; it left no inline comments on #830, so this landed here unflagged. Scoped to this workflow. cache.yml, ci.yml and collab.yml have the same gap and are left alone — linkcheck.yml, publish.yml and sync-translations-zh-cn.yml already scope theirs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gate 2 of QuantEcon/workspace-lectures#23 step 3, the
lecture-wasmhalf. One new workflow, no lecture changes. Companion to QuantEcon/lecture-python-intro#830.The failure it catches
media.githubusercontent.comis the LFS media endpoint. It routes per path, not per repo — it serves a file only where that path is LFS-tracked in the repo the URL names, and 404s otherwise. EverythingQuantEcon/data-lecturespublishes is plain git, so the media host never resolves for it:raw.githubusercontent.com/QuantEcon/data-lectures/main/lectures/mpd2020.xlsxmedia.githubusercontent.com/media/QuantEcon/data-lectures/main/lectures/mpd2020.xlsxBoth hosts send
access-control-allow-origin: *, so this is host routing, not CORS — a different failure from repoint rule 5, and one that hits every runtime rather than only the browser.It is live risk here specifically: the six
high_dim_datadatasets are LFS-tracked there, soheavy_tails,inequalityandmleread them from the media host today. When they land in data-lectures as plain git, a mechanical org/repo swap that preserves the host breaks every one of them — in the reader's browser, on every page view.Why this repo needs it more than intro does
ci.ymlrunsmyst build --htmlwith no execution, so no URL in a code cell is ever fetched by CI. A dead read is invisible here until a reader arrives. (Intro's build does execute and raisesCellExecutionErroron a 404 — a signal this repo does not have at all.)grep -roverlectures/also walkslectures/_static/**/*.ipynb, which the data-lectures audit deliberately excludes from its scan — so this guard is the only mechanism of any kind that sees_static/lecture_specific/inequality/data.ipynb.Scope
Media host only. Rule 5's
github.com/*/raw/form is wrong in a code cell but correct in a{download}role or a prose link, and this repo has both today —french_rev.mdlinks threeblob/URLs andinflation_history.mdhas a{download}on the raw redirect form. A grep cannot tell a code cell from a prose link, so rule 5 stays where it already is: asserted on code cells only, post-merge, by the strict audit in data-lectures.Matches zero lines today — verified,
grepexits 1 — so it goes green on merge and is armed before the fold rather than landing alongside it.It is an alarm, not a gate.
mainhere has no branch protection object at all, so this shows as a failed check on the PR without blocking anything. Making it binding is a separate, deliberate decision.The companion assertion — that no
high_dim_dataURL remains anywhere — matches 7 lines here today, so it belongs in the repoint PR itself.🤖 Generated with Claude Code