Skip to content

chore(ci): check absolute self-links in the offline link gate - #63

Merged
lesnik512 merged 1 commit into
mainfrom
chore/check-absolute-self-links
Sep 6, 2026
Merged

chore(ci): check absolute self-links in the offline link gate#63
lesnik512 merged 1 commit into
mainfrom
chore/check-absolute-self-links

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Implements modern-python/.github#82.

Why

--offline is what makes the link gate deterministic: it blocks network requests and excludes external URLs rather than erroring on them. But an absolute https://github.com/modern-python/<this repo>/blob/main/<path> link pointing back at this repo is an external URL by that rule, so it was never checked. A relative link to a deleted file failed the gate; the same link written absolutely passed forever.

The modern-python/.github#67 migration produced two live instances of this. Both were caught by a human reading the diff; neither by CI.

Design

--remap resolves those URLs against the working tree instead. The target is in the repo, so it needs no network — the gate stays fully offline, and modern-python/.github#66's decision to keep the external check weekly and .github-only is untouched.

The pattern derives the repo from ${{ github.repository }} and the checkout root from ${{ github.workspace }}, so the block is byte-identical in all 26 repos carrying the gate and holds no repo-specific parameter.

That closes the question the issue left open. It asked whether a remap containing the repo name weakens modern-python/.github#66's "nothing to drift" justification enough to warrant a reusable workflow or a guard test. With nothing interpolated by hand, the failure it guards against — a wrong repo name silently disabling the check — cannot occur, so neither is needed. The cost is that the interpolated repo name is not regex-escaped, so in .github the . is a wildcard: over-broad, never under-broad, and inert.

The issue's proposed file://$PWD/$1 does not work. lychee-action runs eval lychee $ARGS, so $PWD stays literal inside the single quotes the remap pair needs, and double quotes make $1 an unbound positional under the entrypoint's set -u. ${{ github.workspace }} is substituted by Actions before the shell sees it.

Non-goals

Verification

A harness reads this repo's real args out of the workflow, applies the Actions substitutions, splits the string the way the entrypoint's eval does, and runs lychee 0.24.2 — the version lychee-action@v2 pins — over a clean git archive HEAD export.

Red before the change (0/26 repos caught an injected broken absolute self-link), green after: 26/26. Per repo it asserts three things — the clean tree is green, an injected broken absolute self-link is caught, and tag-pinned and cross-repo URLs stay excluded.

Also confirmed: actionlint clean; fragments (#anchor) and ?plain=1 queries validate correctly in both directions; all org default branches are main, so the /main/ literal is right; no links job sets a custom checkout path:, so github.workspace is the checkout root.

The pre-adoption sweep the issue asked for found 31 existing absolute self-links across the 26 repos. All resolve, so no gate goes red on adoption.

Known gap

The glob is still '**/*.md', so the docstring URL in faststream-concurrent-aiokafka that the issue cites as user-visible on PyPI stays unchecked. Widening the glob would not reach it either: that URL is split across two adjacent Python string literals at the /docs/adr/ boundary, so no text-level checker can reconstruct it. The target exists today, so nothing is broken.

--offline excludes every external URL, and an absolute
https://github.com/modern-python/<this repo>/blob/main/<path> link back into this
repo is external by that rule. So a relative link to a deleted file failed the
gate while the same link written absolutely passed forever. The
modern-python/.github#67 migration produced two live instances; both were caught
by a human reading the diff, neither by CI.

--remap resolves those URLs against the checkout instead. The target is in the
repo, so it needs no network: the gate stays fully offline and deterministic, and
modern-python/.github#66's decision to keep the external check weekly and
.github-only is untouched.

The pattern derives the repo from github.repository and the checkout root from
github.workspace, so the block is byte-identical in all 26 repos and carries no
repo-specific parameter. That closes the question modern-python/.github#82 left
open: neither a reusable workflow nor a guard test is needed, because the
copy-paste error they were meant to guard against cannot occur. The cost is that
the interpolated repo name is not regex-escaped, so in .github the dot is a
wildcard -- over-broad, never under-broad, and inert.

The issue proposed file://$PWD/$1, which does not work. lychee-action runs
`eval lychee $ARGS`, so $PWD stays literal inside the single quotes the remap
pair needs, and double quotes make $1 an unbound positional under the
entrypoint's `set -u`. github.workspace is substituted by Actions before the
shell sees it.

Verified against lychee 0.24.2, the version lychee-action@v2 pins, over a clean
`git archive HEAD` export of each repo: every tree is green, an injected broken
absolute self-link is caught, and tag-pinned and cross-repo URLs stay excluded.
Swept all 26 repos for pre-existing absolute self-links first -- 31 of them, all
resolving -- so no gate goes red on adoption.

Known gap: the glob is still '**/*.md', so the docstring URL in
faststream-concurrent-aiokafka that the issue cites as user-visible on PyPI stays
unchecked. Widening the glob would not reach it either, because that URL is split
across two adjacent Python string literals.

Refs modern-python/.github#82
@lesnik512
lesnik512 merged commit 71428f3 into main Sep 6, 2026
8 checks passed
@lesnik512
lesnik512 deleted the chore/check-absolute-self-links branch September 6, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant