ci(release): add Maven Central idempotency guard to publish step#56
Conversation
Probe repo1.maven.org for this version's sdk-core POM before publishing and skip the upload when it is already there, so a re-run after a partial failure (e.g. the workflow dies after a successful publish, as happened to sibling repos during the 2026-07-16 Actions outage) recovers cleanly instead of failing on Sonatype 'component already exists'. Ports TAKPacket-SDK's 'Check Maven Central state' pattern. sdk-core is the probe coordinate because all sdk-* artifacts publish together in a single Central Portal deployment. A transient probe failure degrades to 'not published' (attempt the publish), which is today's behavior. Also documents the re-run recovery path in the release runbook. Fixes #55 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
📝 WalkthroughWalkthroughThe release workflow now probes Maven Central for the target ChangesMaven Central idempotency
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Around line 95-97: Update the mc_check step to pass steps.ver.outputs.version
through an env variable and reference that variable in the shell instead of
interpolating it in run. Apply the same safe environment-variable pattern to the
unchanged Resolve version step for inputs.version, preserving the existing
version-resolution behavior.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 282f30c2-5c26-4050-b374-7d65e2b078b5
📒 Files selected for processing (2)
.github/workflows/release.ymldocs/release-runbook.md
| id: mc_check | ||
| run: | | ||
| VERSION="${{ steps.ver.outputs.version }}" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win
Prevent code injection via template expansion.
Expanding the expression ${{ steps.ver.outputs.version }} directly into the run script leaves the workflow vulnerable to command injection if the version string contains malicious input. Instead, bind the context value to an environment variable and reference it in the shell script.
(Note: Consider applying this same pattern to the unchanged "Resolve version" step above, which also expands inputs.version directly).
🔒️ Proposed fix
id: mc_check
+ env:
+ VERSION: ${{ steps.ver.outputs.version }}
run: |
- VERSION="${{ steps.ver.outputs.version }}"
# `|| true`: a transient probe failure must not kill the run —📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| id: mc_check | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| id: mc_check | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | |
🧰 Tools
🪛 zizmor (1.26.1)
[info] 97-97: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml around lines 95 - 97, Update the mc_check step
to pass steps.ver.outputs.version through an env variable and reference that
variable in the shell instead of interpolating it in run. Apply the same safe
environment-variable pattern to the unchanged Resolve version step for
inputs.version, preserving the existing version-resolution behavior.
Source: Linters/SAST tools
Summary
Adds a
Check Maven Central statestep torelease.ymlthat probesrepo1.maven.orgfor the version'ssdk-corePOM and guards the publish step with the resultingalready_publishedoutput, so a plain re-run after a partial failure skips the already-done upload instead of failing on Sonatypecomponent already exists. Ports the pattern from TAKPacket-SDK's release workflow.Type of change
Related issue / discussion
Fixes #55
Affirmations
git commit -s).CONTRIBUTING.md../gradlew checklocally and it passes. (N/A — no Kotlin/Gradle sources touched; workflow + docs only.)How was this verified?
actionlintand YAML parse pass on the edited workflow.set -efor all three cases:already_published=true(publish skips)already_published=false(publish runs)curlfails,|| truecatches it, HTTP 000 →already_published=false(publish runs; step does not die)Notes for reviewers
org/meshtastic/sdk-core/$VERSION/sdk-core-$VERSION.pom. Allsdk-*artifacts (core, transports, storage, testing, bom) publish in one Central Portal deployment via vanniktechpublishAndReleaseToMavenCentral, sosdk-core's POM is an accurate proxy for the whole release — either the deployment landed or it didn't.component already exists; the runbook says to wait for sync and re-run. Same caveat exists in the TAKPacket original.if: ${{ inputs.dry_run != true && steps.mc_check.outputs.already_published == 'false' }}.🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation