Ship the front page in the release zip, and record the link scheme it depends on - #2099
Merged
Merged
Conversation
…l release step Two asks: publish nightly snapshots, and stop finishing every release by hand on the Central Portal website. Both turn out to need less than expected. Snapshots already go to the Central Portal snapshot repository -- the URL in gradle-mvn-push.gradle is the right one -- and they are deliberately unsigned, so a nightly job needs no publishing changes and no GPG key. What is missing is a scheduled workflow, a per-namespace "enable SNAPSHOT" setting in the Portal, and two secrets. The manual click on a release exists because releases upload through ossrh-staging-api.central.sonatype.com, Sonatype's compatibility layer for builds that predate the Portal API, which leaves the deployment for a human to publish. That service has an API for the last step: POST /manual/upload/defaultRepository/io.github.eisop?publishing_type=automatic so the click can go away without changing how the build uploads anything. The document recommends against adopting a Portal-native publishing plugin. com.vanniktech.maven.publish and the alternatives configure publications for you, and this build has eighteen, several hand-tuned: checker publishes components.shadow rather than components.java, with a comment explaining that the latter would ship the skinny jar under the fat jar's name, and a Gradle attribute copied onto the shadow configuration by hand. Re-expressing that inside another plugin's model is risk for no gain when the upload already works. The document says which plugin to revisit if the publications are ever simplified. Adds .github/workflows/publish-snapshot.yml as a starting point, inert until the secrets exist: a first job checks for SONATYPE_NEXUS_USERNAME and the publish job is skipped without it, so merging publishes nothing by itself. It also refuses to run if the version does not end in SNAPSHOT, since a release upload cannot be undone. The version-extraction command and the workflow's shell were both checked locally. Nothing here is enabled. Enabling it is adding the secrets. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The six links to search.maven.org in the manual no longer resolve: that host answers 403 for both its /search and /artifact URLs, with a browser user agent as well as without, while the same queries on central.sonatype.com answer 200. Rewrite them, and drop the trailing "/jar" segment that the artifact URL form no longer takes. Each rewritten URL was fetched to confirm it resolves. Only the URLs change; the surrounding LaTeX is untouched. The publishing URLs in the build were already current: snapshots go to central.sonatype.com/repository/maven-snapshots/ and releases to the ossrh-staging-api host, and no oss.sonatype.org or s01.oss.sonatype.org reference remains anywhere in the tree. The occurrence in docs/CHANGELOG.md is in a released section and is left as the historical record. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Found while tracing how a release reaches Maven Central. release_push.py steps 5b and 5c walk the releaser through the OSSRH Nexus staging UI -- "click on iogithubeisop-XXXX", "Click close at the top", "Copy the URL of the closed artifacts (in the bottom pane)" -- and then ask them to paste that URL back into the script. The Central Portal has no close step and no such panes, so anyone following the script looks for a button that no longer exists. Adopting the one-call automation removes these steps rather than requiring them to be reworded. A release has to bump the version in 34 places across 12 files besides build.gradle: the examples under docs/examples, and several places in the manual and the webpage. They are consistent today, and keeping them so is manual; a missed one leaves the manual telling readers to depend on a version that is no longer newest. docs/examples/publish-smoketest builds against publishToMavenLocal, so it checks the artifacts the build would publish but not that a deployment arrived. Once nightly snapshots exist, pointing it at the published snapshot repository would catch a broken publication on the day it breaks. And the documented release command hardcodes one maintainer's GPG key, which reads as the value to use rather than as the releaser's own. README-eisop.md now says that the key is the releaser's own, that the upload is staged and not live until published, where that is done, and that other files carry the version too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Push steps 5a/5b/5c and 10 drove the retired OSSRH Nexus staging UI: they told the releaser to "close" artifacts in a top pane and paste a staging repository URL back into the script. The Central Portal has no such step. The staging call itself could never have worked here either: it read the signing passphrase from /projects/swlab1/checker-framework/hosting-info/, a University of Washington path that does not exist, and signed with checker-framework-dev@googlegroups.com rather than the releaser's key. Maven Central publishing is in practice a separate ./gradlew publish run, so remove those steps rather than reword them, and renumber the remaining GitHub/website steps 1-12. Removing step 5c retires the only caller that passed a staging repository URL, so maven_sanity_check's repo_url parameter and add_repo_information -- which edited poms to point at org/checkerframework artifacts -- go with it. Document the separate publish step in README-release-process.html. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The target rewrote files that no longer exist and keyed off marker comments that pages no longer carry. Ant's <replaceregexp> only prints "The following file is missing" and still reports BUILD SUCCESSFUL, and a marker regex that matches nothing is not an error at all, so both kinds of drift were silent. Gone from the tree: docs/manual/checkerframework.gradle, build-common.properties, checker/build.properties. Wrong path: checkerQuickStartPage pointed into docs/manual/ rather than docs/. Absent markers: checker-framework-version and compiler-version on docs/checker-framework-webpage.html. Drop those five rules, fix the quick-start path, and add require-file and require-marker macros that assert every file and marker up front, so the target now fails before rewriting anything. Also drop checker.tutorial and checker.release, unused in this target, and the release.properties entries left with no reader. docs/checker-framework-quick-start.html still advertised checker-framework-2.1.7.zip, having missed every release since the path broke; bring it to the current release and fix its javac path, which had bin/checker inverted relative to every other document. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ents The release scripts and Renovate were both bumping docs/examples, and fighting. Renovate rewrites a pom property in place and drops marker comments around it -- it did that to MavenExample-framework-all/pom.xml in PR #2017. The Ant target keyed off those same markers, including in update-and-copy-maven-example, which sets the version on the copy the Maven sanity check compiles. Had Renovate reached MavenExample/pom.xml first, that check would have gone on compiling the previous release and still passed. Give the examples to Renovate alone: drop both example rules from update-checker-framework-versions, match the <checkerFrameworkVersion> element rather than markers when preparing the sanity-check copy, and remove the now-vestigial markers from MavenExample/pom.xml. Two renovate.json changes make that reliable. Every Renovate edit ever made to the example Gradle builds was a plugin version; the eisop version in them was last bumped by Dependabot, removed in PR #1997. These builds hold it in a variable (an ext.versions map entry, or a plain def), so add an explicit customManagers regex rather than rely on Renovate's Gradle variable resolution. Second, the repository-wide minimumReleaseAge of 7 days delayed our own artifact a week behind every release, so set it to 0 for io.github.eisop and give it its own PR. Separately, checker-includes had drifted the same silent way, and an Ant include pattern that matches nothing is not an error either. README.html was renamed away in 2015, so no README shipped in the distribution at all. "Make class name and file name the same" moved the units-extension qualifiers into qual/ and renamed Demo.java in 2020, so that example shipped its Makefile, README and Expected.txt and not one Java source -- the shipped Makefile refers to files that are not in the zip. Verified on the published site, whose newest release is 3.49.3-eisop1: under /cf/checker-framework-3.49.3-eisop1/examples/units-extension/, README is 200 while UnitsExtensionDemo.java is 404, and README.md is 404. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Maven Central does not pin a signing key to a namespace; it only checks that each signature verifies against a public key it can fetch from a keyserver. Several maintainers can therefore each sign with their own key, and nothing in this repository has to change when a new one starts releasing. Only the documentation implied otherwise, by presenting one maintainer's key as the value to pass. Move the key out of the command line and into the releaser's own ~/.gradle/gradle.properties, next to the Portal tokens already documented there, so the release command names no key at all. Fail the signing task with an explicit message when signing.gnupg.keyName is unset: gpg would otherwise fall back to whichever secret key happens to be its default, which may not be one Central can verify. Snapshots are unsigned, so the check does not affect them. Record the release-process findings from this audit in maven-central-publishing.md: two web pages that the release still rewrites but that nothing publishes (the main one has already been ported to the website repository's cf-template.md, minus its Dataflow Framework bullet), and the fact that the website is still on 3.49.3-eisop1 because nothing runs the site generator as part of a release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two documents were produced at release time and then discarded, because they only ever reached the interm site directory that nothing publishes for eisop. docs/checker-framework-quick-start.html was kept version-correct by update-checker-framework-versions but shipped nowhere and appeared on no website. Add it to checker-includes so it travels in the release zip alongside the manual, the tutorial and the CHANGELOG. Its links pointed at https://eisop.github.io/cf/manual/#anchor, which resolves only through the 404 page's JavaScript redirect; make them site-relative so they work both at cf/quick-start.html and in an archived cf/<release>/quick-start.html. release_build.py already runs `make` in dataflow/manual, and checker-framework-website-docs copies the result to the interm directory under the very name the old front page linked to. Add it to the zip at docs/manual/checker-framework-dataflow-manual.pdf with a fullpath zipfileset, the mechanism already used for CFLogo.png. Because the website generator lifts docs/manual wholesale, it surfaces at cf/manual/checker-framework-dataflow-manual.pdf with no generator change. eisop/eisop.github.io#103 lifts the quick-start guide to cf/quick-start.html, restores the Dataflow Framework bullet that was dropped when the front page was ported to cf-template.md, and links both from the front page. checker-framework-webpage.html is deliberately left untouched here: a follow-up PR ships it in the release zip as that release's own page, which is the opposite of the "not published, do not edit" note that would otherwise have landed with this commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs/checker-framework-webpage.html is the Checker Framework's front page. It is not published by eisop: the website generates its own from cf-template.md in the eisop.github.io repository, a Markdown port of this file. So this page has been version-stamped by every release and then discarded, while its port drifted -- the port silently lost the Dataflow Framework bullet, and nobody noticed for two years. One template shared across every release is also a standing mismatch. A link added for content that first ships in release N is broken on the archived page of every release before N, permanently, not merely until the next release. Shipping the page with the release it describes removes that by construction, and this file is already exactly such a page: release.xml stamps the Checker Framework version and date, and the AFU zip name and date, into it, so it is self-contained at release time. Add it to checker-includes. Align its links, which were still the old typetools site layout, to the layout the zip and the website share. Because the page is served at two depths -- as cf/index.html and as cf/<release>/index.html -- the scheme has to be mixed: relative for what exists at both (manual/manual.html, manual/manual.pdf, tutorial/, api/checker-javadoc/, CHANGELOG.md, CFLogo.png) and absolute for site singletons (/cf/<zip>, /cf/releases/releases.html, /afu/<zip>, /afu/annotation-file-utilities.html). Checked against the live site: manual/manual.pdf resolves at both depths while manual/checker-framework-manual.pdf exists only at cf/. The favicon the page references existed nowhere on the site, so ship it alongside. The website half -- using this page and retiring cf-template.md -- needs no release and follows separately. Until then the page rides along unused, as the quick-start guide does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The front page did not link the quick-start guide at all, and linked the dataflow manual by absolute URL into the current website. Both matter now that this page travels with the release: if the links are not in the shipped page, correcting them later needs another release. Link quick-start.html from the Quick start entry and from both Documentation lists. Point the dataflow manual at manual/checker-framework-dataflow-manual.pdf, where this release now puts it, so an archived page links its own release's manual rather than whatever the site currently serves. No hardcoded eisop.github.io links remain in the page. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
wmdietl
added a commit
to eisop/eisop.github.io
that referenced
this pull request
Sep 16, 2026
The Dataflow bullet and the quick-start links added here are superseded by eisop/checker-framework#2099, which ships docs/checker-framework-webpage.html in the release zip so that each release carries its own front page. That page already has the Dataflow bullet -- it is the page cf-template.md was ported from, and the port is where the bullet was lost -- and #2099 adds the quick-start links to it. Editing the template here as well would mean landing links to files that no published release contains, then reverting them when the template retires. Drop that half; the generator change stays, since the quick-start guide has to be lifted out of the release zip either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 16, 2026
PR #2097 was squash-merged, so master carries its twelve commits as one commit that is not an ancestor of this branch, and the eight of them that this branch also contains came through a different route. Four files conflicted: - `publish-snapshot.yml` and `maven-central-publishing.md`: master's versions are newer -- the workflow's pins were aligned with the other workflows, and the document was trimmed -- and this branch never touched either after forking, so master's win. - `checker-includes` and `release.xml`: both sides add entries. Kept the union -- master's `README.md` and units-extension corrections, and this branch's front page and favicon. One thing was lost with the trimmed document: the front page's relative versus absolute link scheme, which is a trap for a future editor. It is restored as a comment in the page itself in the next commit.
The page is served at two depths, as /cf/index.html and as /cf/<release>/index.html, so its links have to be mixed: relative for what sits beside it at both depths, absolute for site singletons. Making them uniformly one or the other breaks one of the two depths, which is a trap for anyone editing the links later. That constraint was written down in maven-central-publishing.md, which no longer carries the release-process archaeology. Put it in the page it constrains, together with the three targets that the website generator produces rather than the zip, and a reminder that release.xml keys off the marker comments. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
It is served at the same two depths as the front page, so it has the same mixed relative/absolute links and the same trap for a later editor. Point at the front page's comment rather than repeating the explanation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 19, 2026
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.
Follows #2097, now merged; master is merged in, so this reduces to the front page alone. This must merge before the next release, since only a release built after it can carry the page.
Why
docs/checker-framework-webpage.htmlis the Checker Framework's front page, and eisop does not publish it. The website generates its own fromcf-template.md, a Markdown port of this file. So the page here has been version-stamped by every release and then thrown away, while the port drifted — it silently lost the Dataflow Framework bullet, and nobody noticed for two years.The deeper problem is that one template shared across every release is a standing mismatch. A link added for content that first ships in release N is broken on the archived page of every release before N — permanently, not just until the next release. That is not a transition cost; it recurs every time per-release content is added, which is exactly what #2097 did with the quick-start guide and the dataflow manual.
A page that travels with the release it describes cannot have that problem, and this file already is such a page:
release.xmlstamps the Checker Framework version and date and the AFU zip name and date into it, so it is self-contained at release time.What changed
The page is added to
checker-includes, the favicon it references ships beside it via azipfileset, and its links are aligned from the old typetools site layout to the layout the zip and the website share.The page is served at two depths — as
cf/index.htmlfor the newest release and ascf/<release>/index.htmlfor an archived one — so the link scheme has to be mixed, the same trickcf-template.mdalready used for its download link:manual/manual.html,manual/manual.pdf,manual/checker-framework-dataflow-manual.pdf,tutorial/,api/checker-javadoc/,CHANGELOG.md,quick-start.html,CFLogo.png,favicon-checkerframework.png/cf/checker-framework-<ver>.zip,/cf/releases/releases.html,/afu/annotation-tools-<ver>.zip,/afu/annotation-file-utilities.htmlUniformly relative breaks the singletons at release depth; uniformly absolute makes every archived page link the newest release's manual rather than its own. That constraint is now recorded in a comment at the top of the page itself, along with the three targets the website generator produces rather than the zip carrying them. The quick-start guide, which #2097 shipped and which is served at the same two depths for the same reason, gets a short comment pointing at it.
Testing
EisopSiteGenerator's source. On the website all resolve, or will once Lift the quick-start guide out of the release zip eisop.github.io#103 and Add more aliases for nullness annotations; fix formatting #105 land. Three resolve only there and not in an unzipped release, because the generator produces them:quick-start.html(the zip hasdocs/checker-framework-quick-start.html, which the generator renames),api/checker-javadoc/(the zip haschecker/dist/checker-javadoc.jar, which it unpacks), andCFLogo.png(copied up fromtutorial/). Each was considered and left as is — see the comment in the page./cf/<release>/{CFLogo.png,api/checker-javadoc/,manual/manual.html,tutorial/,CHANGELOG.md}are all 200, and the zip'sdocs/holds onlyCHANGELOG.md,examples,manual,tutorial.update-checker-framework-versionsrun end-to-end on a scratch copy with the real AFUbuild.properties: both rewritten absolute links pick up the new version, and all four marker-wrapped values still update. Thebylineregex that rewriteschecker-framework-<version>cannot chew the new comment prose, since it requires a digit after the hyphen.zipfilesetentries verified in isolation:docs/checker-framework-webpage.htmlanddocs/favicon-checkerframework.pngland where the generator will look for them.spotlessCheckpasses andrelease.xmlparses.htmlValidatecovers both pages and is left to CI, sincehtml5validatoris not installed locally; the comments avoid--for that reason.Not in this PR
The website half — teaching the generator to use this page as
cf/<release>/index.htmland retiringcf-template.md— needs no release and follows separately in eisop/eisop.github.io#105. Until it lands, the page rides along in the zip unused, exactly as the quick-start guide does. Releases predating this PR have no such page, so the generator keeps a fallback for them.Nothing verifies these links automatically yet. #2111 proposes checking the shipped pages against the zip's contents at PR time, and gating a release on a link check of the generated site before anything is published — which needs eisop/eisop.github.io#106.
🤖 Generated with Claude Code