Skip to content

Link-check the shipped pages before a release is published #2111

Description

@wmdietl

Since #2097 and #2099, the release zip carries two HTML pages that the website
serves as that release's own: docs/checker-framework-webpage.html and
docs/checker-framework-quick-start.html. Nothing verifies their links, and the
link checking the release scripts do have points at a site that does not exist.

The goal is to catch a broken link before a release is published, since that
is the only point at which it is still cheap to fix.

What is wrong with the link check we have

release_push.py calls run_link_checker against DEV_SITE_URL and
LIVE_SITE_URL (release_vars.py:136-141):

  • DEV_SITE_URL is https://eisop.github.io/cf/dev, which is a 404. eisop never
    set up the dev-site mechanism; releases go straight to live.
  • The suppression argument is hard-coded to
    https://checkerframework.org/checker-framework-<ver>.zip
    (release_push.py:195) -- the typetools domain, so it suppresses nothing for
    us.
  • checkLinks.sh hard-codes a RHEL-era PERL5LIB and still carries
    # TODO: Remove all dependencies on /homes/gws.

So the check runs against a site nobody publishes, after the release exists.

Layer 1: check the shipped pages against the zip, at PR time

Cheap, no network, belongs in misc. For each relative href/src in the two
shipped pages, assert the target is something the release zip actually contains
(checker-includes plus the zipfileset entries in release.xml).

Three targets must be allowlisted, because the website generator produces
them rather than the zip carrying them:

target where it really comes from
quick-start.html the zip has docs/checker-framework-quick-start.html; the generator renames it (eisop/eisop.github.io#103)
api/checker-javadoc/ the zip has checker/dist/checker-javadoc.jar; the generator unpacks it. checker-excludes excludes api/** deliberately
CFLogo.png the generator copies it up from tutorial/CFLogo.png

Everything else in those pages resolves inside the zip today, verified by
inspecting the published 3.49.3 zip and the generator source. This layer would
have flagged all three of the above the moment the front page was added, which is
how they were found.

Layer 2: a real pre-release gate

release_build.py:285 builds checker-framework-<version>.zip into the interm
directory, well before release_push.py pushes anything. That is the hook:

  1. Run the website generator against that local zip, with dry run on, building
    only the newest release. This needs Let the generator build from a local, unpublished release zip, so a release can be link-checked before it ships eisop.github.io#106
    (--local-release, --only-latest), which is the blocking dependency.
  2. Serve the resulting tree and link-check both depths, /cf/index.html and
    /cf/<release>/index.html. The pages' links are deliberately mixed
    relative/absolute because they are served at two depths; checking one proves
    nothing about the other. The reasoning is in a comment at the top of
    docs/checker-framework-webpage.html.
  3. Fail the release. Nothing has been pushed at that point: no tag, no GitHub
    release, no site change.

Cleanup that goes with it

Once the check lives where the tree is, delete the machinery that pretended a dev
site existed: DEV_SITE_URL, DEV_SITE_DIR, LIVE_SITE_DIR, the
checkerframework.org suppression, and checkLinks.sh's hard-coded PERL5LIB.
Check whether run_link_checker has any remaining caller first.

Related, same root cause and worth folding in if it is cheap: the
checker-framework-website-docs target copies the manual, the front page and the
logo into ${dest.dir}, a /tmp/$USER directory nothing publishes, and it also
writes CFLogo.png back into the source tree (docs/manual/CFLogo.png) at
release time.

Order

Layer 1 first -- it is self-contained, needs no other repository, and protects
the zip's contents from the next mistake of this kind. Layer 2 when #106 lands.

Website counterpart: eisop/eisop.github.io#106. Post-release generator work:
eisop/eisop.github.io#105. Maven Central publishing follow-ups: #2109.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions