chore(ci): publish an openapi json artifact with nightly releases#999
Conversation
WalkthroughThis PR establishes an OpenAPI artifact export pipeline for nightly releases. It introduces a composite GitHub Action orchestrating checkout, Java 25 setup, and Gradle task execution; adds a new nightly workflow job that exports OpenAPI JSON and gates downstream notifications; implements Gradle tasks and a bash script to extract the OpenAPI specification from a running Spring Boot instance; and provides supporting configuration files and documentation updates. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/build.gradle.kts`:
- Around line 252-282: The exportOpenApi task currently misses the APP_VERSION
as an input, so Gradle can reuse a cached output when the APP_VERSION
environment variable changes; add an inputs.property entry to the
tasks.register("exportOpenApi") configuration (before doLast) that declares the
APP_VERSION (e.g. inputs.property("APP_VERSION", System.getenv("APP_VERSION") ?:
"")) so Gradle will consider APP_VERSION when up-to-date checking and not reuse
stale openApiOutputFile / grimmory-openapi.json produced by exportOpenApi.
In `@backend/scripts/export-openapi.sh`:
- Around line 18-38: The script currently chooses an ephemeral port into
variable port, closes the socket, then starts the JVM which creates a race;
change this by either (A) letting Spring bind port 0 and discovering the
assigned port from the running process (start org.booklore.BookloreApplication
with -Dserver.port=0, tail/grep the application log for the bound port or probe
the application’s /actuator or /api/openapi.json endpoint repeatedly until it
responds and then set endpoint accordingly) or (B) implement a safe startup
retry: after picking port as done today, start the JVM (using "$java_executable"
launching org.booklore.BookloreApplication) and if startup fails to bind that
port detect the failure (check process exit or log for “Address already in use”)
then pick a new ephemeral port and retry a limited number of times before
failing; update variables port, endpoint, app_pid and log handling accordingly
so there is no window where another process can claim the chosen port.
- Around line 54-56: The current check uses grep to look for the string
"openapi" which accepts false positives; instead parse and validate the fetched
JSON by using a JSON parser (e.g., jq) on "$output_file" and verify it contains
a top-level "openapi" field (e.g., test that .openapi exists and is a string)
before exiting successfully; update the conditional around the curl/grep block
(referencing variables endpoint and output_file) to run a jq validation step and
fail (non-zero exit) if the file is not valid OpenAPI JSON.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 2c19d8c0-9649-4d30-ab4f-564ebaeda841
📒 Files selected for processing (8)
.github/actions/export-openapi/action.yml.github/workflows/publish-nightly.ymlbackend/DEVELOPMENT.mdbackend/Justfilebackend/build.gradle.ktsbackend/scripts/export-openapi.shbackend/src/main/resources/application-openapi-export.yamldocs/MAKING-A-RELEASE.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Test Suite / Backend Tests
- GitHub Check: Test Suite / Frontend Tests
- GitHub Check: Analyze (java-kotlin)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Frontend Lint Threshold Check
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-03-31T06:22:25.311Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 113
File: booklore-api/build.gradle.kts:89-90
Timestamp: 2026-03-31T06:22:25.311Z
Learning: When reviewing build logic or CI checks that call the JitPack build status API, do not treat a response like {"status":"none"} as evidence that a dependency is unavailable or that a build has failed. JitPack typically builds packages on-demand the first time they’re requested (e.g., via Gradle); "none" means the package isn’t pre-built/cached yet. Only raise a build failure concern when the status explicitly indicates an error/failure (e.g., failed/cancelled), or when dependent resolution actually fails.
Applied to files:
backend/build.gradle.kts
📚 Learning: 2026-04-02T09:12:48.158Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 334
File: booklore-api/build.gradle.kts:0-0
Timestamp: 2026-04-02T09:12:48.158Z
Learning: In this repo, nightcompress (groupId `com.github.gotson.nightcompress`, artifact `nightcompress`) is the preferred library for archive/unarchive operations (including RAR and other formats). During code review, flag changes to Gradle dependency declarations that remove nightcompress or replace it with an alternative for unarchiving (e.g., junrar, commons-compress, JNI-based libraries, or standard Java `ZipInputStream`/`ZipFile`) unless there’s a justified exception. Exceptions are acceptable only when nightcompress cannot handle a specific archive format; in that case, require the PR to clearly document the format limitation, the alternative being used, and get maintainer confirmation of the trade-off.
Applied to files:
backend/build.gradle.kts
🪛 Shellcheck (0.11.0)
backend/scripts/export-openapi.sh
[info] 40-45: This function is never invoked. Check usage (or ignored if invoked indirectly).
(SC2329)
Description
Adds automated OpenAPI JSON exports to the nightly build pipeline
Once this is in, nightly will generate
backend/build/openapi/grimmory-openapi.jsonfrom a dedicatedopenapi-exportprofile and upload it as a workflow artifact. This will give us a consistent source for the latest nightly API spec without depending on an external database or running it locally.Once we've confirmed this behaves to our liking, we can merge in the next PR to introduce this flow to stable releases.
Linked Issue: Fixes #291
Changes
openapi-exportprofile for lightweight OpenAPI generationjust api openapi-export/buildOpenApiArtifactssupport for exportinggrimmory-openapi.jsonapplication-dev.ymlSummary by CodeRabbit