Repository navigation
Rewrite consumer Gradle scripts for publishApiDocs on pull - #817
Conversation
The `UpdateGitHubPages` plugin became `PublishApiDocs` with no deprecated
aliases. `migrate` deleted the stale plugin sources but restored the
consumer's `module.gradle.kts`, which in most consumers still calls
`updateGitHubPages { }`, so their `buildSrc` stopped compiling after
`./config/pull` (`Unresolved reference 'updateGitHubPages'`).
`scripts/migrate-publish-api-docs.sh`, called by `migrate`, rewrites the
forms the consumers use, in the Kotlin sources under `buildSrc/src` and the
tracked `*.gradle.kts` files: the import and the call are renamed, the
dependency of `publish` on the docs task is deleted, and a script's own
`configureGitHubPages()` becomes `configureApiDocs()`, as in
`jvm-module.gradle.kts`. Any other use of the old API, and a workflow that
names the old task, is reported with its file, line, and replacement.
`scripts/test-migrate-publish-api-docs.sh` covers each surveyed form, the
warnings, CRLF, a second run, and a run of the real `migrate`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Delete a `dependsOn` only when the docs task is its single argument; one
with more arguments is left as it is and reported, instead of losing the
other dependencies without a word.
- List tracked files with `git ls-files -z`, so that a path with non-ASCII
characters, which Git quotes otherwise, is not missed.
- Leave a declaration such as `fun Project.updateGitHubPages() {` alone.
- Write the temporary file outside the consumer's tree, and hand the paths and
the KDoc to `awk` through the environment, which keeps backslashes.
- Test the new guards, a function's own KDoc, a consumer outside Git, and the
added KDoc against `jvm-module.gradle.kts`; the JVM fixtures of the sibling
`migrate` suites now carry the script.
- Word the comments and messages as "rewrite" throughout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For a release version, `:publishAllApiDocs` runs Dokka for every published module, and `org.gradle.parallel=true` lets those runs overlap. Hosted Linux runners have effectively no swap, so a memory peak becomes an OOM kill; `build-on-ubuntu.yml` adds 8 GB of swap for that reason, and so does this job now. The step runs before the deploy key is decrypted, so that the third-party action never runs with the key on disk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 54cdcf578a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🟡 Changes recommended
A verified temporary-output reuse bug can overwrite a consumer script with another script’s contents when its rewrite removes every line.
1 open issue
What changed in this PR
This PR automates consumer migration to publishApiDocs during config pulls, following the separation of API documentation publishing from Maven publishing.
Changes:
- Rewrite known legacy Gradle API calls, remove old publishing dependencies, and warn about unsupported forms.
- Add migration regression coverage and update existing test fixtures.
- Add 8 GB of swap to the API documentation workflow before deploy-key decryption.
| File | Description |
|---|---|
scripts/test-migrate-wrapper-validation.sh |
Include the new migration script in fixtures. |
scripts/test-migrate-publishing-pin.sh |
Include the new migration script in fixtures. |
scripts/test-migrate-publish-api-docs.sh |
Add rewrite, preservation, warning, and integration checks. |
scripts/migrate-publish-api-docs.sh |
Implement legacy API migration and remaining-use warnings. |
migrate |
Invoke the migration after workflow copying. |
.github-workflows/publish-api-docs.yml |
Allocate swap for parallel documentation builds. |
.agents/tasks/migrate-publish-api-docs.md |
Record the consumer survey, implementation, and verification. |
Review effort: Balanced
- A line with the `fun` keyword is a declaration wherever the keyword stands,
so `@Suppress("unused") fun Project.updateGitHubPages() {` is no longer
rewritten into `fun Project.publishApiDocs {`, which does not compile and
hides the old name from the warning.
- Empty the temporary output before each file. A script of nothing but the
docs dependency drops every line, so `awk` never opened its output: the
file got the previous file's text, or `cp` failed when it was the first.
Both have regression tests; each fix, reverted, fails them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
publishApiDocs on pull

Problem
#815 renamed the
UpdateGitHubPagesplugin toPublishApiDocs, with no deprecated aliases.migratedeletes the stale plugin sources, but it restores the consumer's ownbuildSrc/src/main/kotlin/module.gradle.kts, and most consumers call the old API there. After./config/pull, theirbuildSrcstops compiling:The
summitwave hit this re-shippingtime, which got a fix by hand (SpineEventEngine/time#202, commit54c0e602). The other consumers still onconfigad3dff08hit it on their next pull.Change
scripts/migrate-publish-api-docs.sh, called bymigrate, rewrites the consumer's own scripts that name the old API: the Kotlin sources and scripts underbuildSrc/src, and the tracked*.gradle.ktsfiles elsewhere. The filesconfigdistributes no longer name it, so what is found belongs to the consumer.import io.spine.gradle.github.pages.updateGitHubPages→…publishApiDocs.updateGitHubPages {andupdateGitHubPages() {→publishApiDocs {.publishon the docs task is deleted, in both known forms:tasks.named("publish") { dependsOn("${project.path}:updateGitHubPages") }, andproject.afterEvaluate { val publish = tasks.findByName("publish"); publish?.dependsOn(…) }. Kept, it would failpublishon a task that no longer exists. It is not renamed either, because the docs are no longer a part ofpublish.fun Module.configureGitHubPages()and its calls becomeconfigureApiDocs(), with the KDoc ofjvm-module.gradle.ktswhen the function has none. A script's top-level functions are visible only inside the script, so every call is in that file.Each rewrite matches only the old form, so a second run changes nothing. A file is written only when its content changes, and it keeps its mode and CRLF line endings.
Any use of the old API left afterwards, and any tracked workflow that names the old task, is a form the script does not know. It prints a warning with the file, the line, and the replacements.
migratestays fail-open: if the script fails, the pull goes on with a warning.The script runs after the workflows are copied, so the warning covers only the workflows the consumer keeps itself. The closing
git add ./buildSrc/srcstages the rewrittenbuildSrcfiles. A rewritten script outsidebuildSrc, such as gcloud-jvm's rootbuild.gradle.kts, is left unstaged for the developer to commit.Swap space for
publish-api-docs.ymlThe third commit addresses a Codex finding on SpineEventEngine/time#202 about the distributed
publish-api-docs.yml. For a release version,:publishAllApiDocsruns Dokka for every published module, andorg.gradle.parallel=truelets those runs overlap. Hosted Linux runners have effectively no swap, so a memory peak becomes an OOM kill.build-on-ubuntu.ymlalready adds 8 GB of swap for that reason, so the docs job now gets the samepierotofy/set-swap-space@v1.0step. The step runs before the deploy key is decrypted, so the third-party action never runs while the key is on disk. A snapshot version is unaffected either way: itspublishApiDocsruns no Dokka.actionlintreports only theconcurrency.queuekey that #815 already accepted.Survey
I checked consumer-owned files on
origin/masterof the 19 Gradle repositories insummit(the per-form table is in.agents/tasks/migrate-publish-api-docs.md). The old API appears in 12module.gradle.ktsfiles and in gcloud-jvm's rootbuild.gradle.kts. All 13 use the forms above. On copies of all 13, the script rewrote every use and printed no warnings.Verification
Same as the hand fix. For
time, the rewrittenmodule.gradle.ktsis byte-identical to54c0e602.Compiles against
configmaster. For time, compiler, testlib, tool-base, change, and core-jvm:origin/masterwithgit archive, added this branch asconfig/(withadopt-shared-agentsstubbed), and ran the realmigrate. No use of the old API was left, andmodule.gradle.ktswas staged../gradlew helpbuiltbuildSrc:BUILD SUCCESSFULfor all six.:buildSrc:compileKotlinran each time rather than coming from the cache, and producedModule_gradle.class.Negative control. The same layout with compiler's unmigrated
module.gradle.ktsfails with the errors quoted above.scripts/test-migrate-publish-api-docs.sh: 43 checks pass. It covers:afterEvaluateone istime's fix);buildSrcscript, a tracked root script, and a tracked script under a non-ASCII path;644;dependsOnwith more than the docs task, a declaration ofupdateGitHubPages()(with an annotation before it, too), the extension type, and a workflow's-x updateGitHubPages;jvm-module.gradle.kts;buildSrcis rewritten);migrate, which rewrites and stages the restoredmodule.gradle.ktsand stages the deleted plugin source.Reverting any of the guards one at a time makes the suite fail: the
afterEvaluaterule, the single-argumentdependsOnmatch,ls-files -z, the declaration check, and the emptied temporary output.The other
migratesuites (test-migrate-ide-files,test-migrate-publishing-pin,test-migrate-wrapper-validation,test-update-gitignore) pass, and the JVM fixtures of the pin and wrapper-validation suites now carry the new script.shellcheckis clean onmigrateand on every changed script.spine-code-reviewandreview-docsboth approved with changes, and the changes are applied in the second commit. Two later findings from the PR review (Codex: an annotated declaration; Copilot: stale temporary output when a rewrite drops every line) are fixed in the fourth.spine-code-reviewran the script under BSD awk, mawk 1.3.4, and gawk 5.3.2 and got byte-identical results. After the changes, the 13 real files still rewrite to the same output../gradlew detektpasses, and./gradlew -p buildSrc testpasses all 315 tests. No Kotlin changed.Not covered
publishdependency removal is checked against the expected text, not by runningpublish --dry-runin a full consumer build.build.gradle.ktsis checked against the expected text and against the same form in the tests. It was not compiled, since that would configure the whole gcloud-jvm build.🤖 Generated with Claude Code