Skip to content

ci: prevent SNAPSHOT releases; bump to 0.1.6-SNAPSHOT#49

Open
WilliamAGH wants to merge 5 commits intomainfrom
dev
Open

ci: prevent SNAPSHOT releases; bump to 0.1.6-SNAPSHOT#49
WilliamAGH wants to merge 5 commits intomainfrom
dev

Conversation

@WilliamAGH
Copy link
Copy Markdown
Owner

@WilliamAGH WilliamAGH commented Feb 14, 2026

Mirrors the Maven Central publishing guardrails used in tui4j.

Changes:

  • Release workflow: fail fast if the release tag ends with -SNAPSHOT (Central releases reject SNAPSHOTs).
  • CI workflow: only publish snapshots when VERSION_NAME ends with -SNAPSHOT; publish snapshots without overriding -Pversion (uses gradle.properties).
  • gradle.properties: bump VERSION_NAME to 0.1.6-SNAPSHOT.
  • README: document Sonatype snapshot repository + snapshot dependency coordinates.

Verification:

  • ./gradlew build

Greptile Summary

This PR adds guardrails to prevent SNAPSHOT versions from being published to Maven Central, bumps VERSION_NAME to 0.1.6-SNAPSHOT, and documents the Sonatype snapshot repository in the README. The CI and Release workflow changes are clean and correct.

  • P1 — README snapshot coordinates will be overwritten: The new snapshot section in README.md contains implementation(\"com.williamcallahan:apple-maps-java:0.1.6-SNAPSHOT\") and the matching Maven <version>0.1.6-SNAPSHOT</version>. The pre-existing UpdateReadmeVersion.yaml perl substitutions use the /g flag and will replace all matching coordinates globally — including those in the snapshot section — with the latest stable version from Maven Central on its next run (daily schedule or next release trigger). The UpdateReadmeVersion script needs its regexes scoped to non-SNAPSHOT versions before this README section can be trusted.

Confidence Score: 4/5

Safe to merge after fixing the UpdateReadmeVersion regex scope, which will otherwise silently corrupt the new snapshot docs on its next run.

All CI/workflow logic changes are correct and well-structured. The sole P1 finding is in README.md: the existing global regex in UpdateReadmeVersion.yaml will overwrite the new snapshot coordinates with the stable release version, breaking the snapshot documentation for consumers.

README.md (snapshot section) and .github/workflows/UpdateReadmeVersion.yaml (perl regex scope)

Important Files Changed

Filename Overview
.github/workflows/CI.yaml Refactored snapshot detection: version check now reads the SNAPSHOT suffix from gradle.properties rather than appending it; publish step correctly conditioned on is_snapshot=true; no issues.
.github/workflows/Release.yaml Added SNAPSHOT guard that fails fast when the release tag resolves to a -SNAPSHOT version; correctly positioned before build/publish steps.
.github/workflows/UpdateReadmeVersion.yaml ref: main checkout added (correct); however its global perl regex will overwrite the new snapshot version coordinates in README.md on the next run.
README.md New snapshot repo section added with correct coordinates; however, the pre-existing UpdateReadmeVersion automation will corrupt the snapshot version on its next run due to global regex replacement.
gradle.properties VERSION_NAME bumped from 0.1.5 to 0.1.6-SNAPSHOT; straightforward and correct.
AGENTS.md Expanded rule set (ZA1, GT1, CC1, ID1, DS1, LOC1, MO1); file is 161 lines, comfortably under the 350-line ceiling defined in LOC1a.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Push to main] --> B{version_check:\nVERSION_NAME ends\nwith -SNAPSHOT?}
    B -- Yes --> C[Publish SNAPSHOT\npublishAllPublicationsToCentralPortalSnapshots]
    B -- No --> D[Skip publish]

    E[GitHub Release published] --> F[Extract version\nfrom tag]
    F --> G{Fail if SNAPSHOT tag:\nVERSION ends with\n-SNAPSHOT?}
    G -- Yes --> H[Exit 1\nRefuse SNAPSHOT release]
    G -- No --> I[Build & Test\n-Pversion=TAG]
    I --> J[Deploy to Maven Central\npublishAllPublicationsToCentralPortal]

    K[Daily schedule / release trigger] --> L[UpdateReadmeVersion:\nFetch latest stable\nfrom Maven Central]
    L --> M{Resolved version\nis SNAPSHOT?}
    M -- Yes --> N[Exit 1\nRefuse SNAPSHOT update]
    M -- No --> O[Perl regex /g:\nupdates ALL coords\nincl. snapshot section]
Loading

Fix All in Claude Code Fix All in Cursor Fix All in Codex

Prompt To Fix All With AI
This is a comment left during a code review.
Path: README.md
Line: 77-102

Comment:
**`UpdateReadmeVersion` will overwrite snapshot coordinates with the stable version**

The `UpdateReadmeVersion.yaml` perl substitutions use the `/g` (global) flag, so they match **all** occurrences of the dependency coordinates in the file — including the new snapshot section. The next time that workflow runs (daily schedule, or on the next release), it will replace `0.1.6-SNAPSHOT` in both the Gradle and Maven snapshot snippets with the latest Maven Central stable version (e.g., `0.1.5`), silently corrupting the documentation for consumers who rely on snapshots.

The simplest fix is to guard the regex so it only touches non-SNAPSHOT versions:

```perl
# Gradle snippet — stable only
s/(implementation\("com\.williamcallahan:apple-maps-java:)(?!.*SNAPSHOT)[^"]+("\))/$1$v$2/g;

# Maven snippet — stable only
s#(<dependency>\s*<groupId>com\.williamcallahan</groupId>\s*<artifactId>apple-maps-java</artifactId>\s*<version>)(?!.*SNAPSHOT)[^<]+(</version>\s*</dependency>)#$1$v$2#gms;
```

Alternatively, wrap each stable snippet in HTML comment markers and scope the replacement to only that region.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "docs: add Mintlify badge, mvnrepository ..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

WilliamAGH and others added 4 commits January 23, 2026 01:19
When triggered by release:published events, GitHub Actions checks out the
release tag (detached HEAD) rather than a branch. This caused git push to
fail with "You are not currently on a branch" error.

Fixed by explicitly specifying ref: main in the checkout step, ensuring
the workflow always operates on the main branch regardless of trigger.
The repository’s agent guidance needed to be more explicit and linkable, with
stable rule hashes that can be cited during reviews and automated changes.
This formalizes additional non-negotiables (verification, SRP, LOC ceilings,
dependency source inspection) and adds a single “code change contract” so
new work follows consistent placement and splitting decisions.

- Expand AGENTS rule summary and add missing rule sections/hashes
- Add dependency source verification workflow (Gradle cache / sources JAR)
- Add LOC ceiling and no-monolith decision rules (new file vs edit)
- Add a contracts doc with a decision matrix and verification gates
Docs pages currently lack frontmatter metadata and there is no Mintlify docs
configuration to define navigation and site identity. This adds the Mintlify
`docs.json` plus per-page titles so the documentation can be rendered and
navigated consistently.

- Add docs/docs.json with theme, name, and grouped navigation
- Add YAML frontmatter titles to core docs pages
- Include Contracts navigation entry pointing at the code-change contract page
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

Walkthrough

This pull request adds snapshot release handling and stricter release gating: CI now detects SNAPSHOT versions via an is_snapshot output and conditionally publishes snapshots; Release workflow aborts on -SNAPSHOT tags; project version set to 0.1.6-SNAPSHOT; docs, Mintlify config, and governance/policy docs added or expanded.

Changes

Cohort / File(s) Summary
GitHub Actions Workflows
.github/workflows/CI.yaml, .github/workflows/Release.yaml, .github/workflows/UpdateReadmeVersion.yaml
CI: replaced snapshot extraction with version_check step that sets is_snapshot output and logs version; Snapshot publish step now conditioned on is_snapshot; Release: added "Fail if SNAPSHOT tag" step to abort releases with -SNAPSHOT; UpdateReadmeVersion now explicitly checks out main.
Version Configuration
gradle.properties
Bumped VERSION_NAME from 0.1.5 to 0.1.6-SNAPSHOT.
Documentation & Metadata
docs/usage.md, docs/cli.md, docs/authorization.md, docs/tests.md, docs/docs.json
Added YAML front matter titles to docs files and introduced docs/docs.json Mintlify site config (theme, nav, branding).
Policy & Architecture Guidance
AGENTS.md, docs/contracts/code-change.md
Large expansion/rewrite of governance: Zero Tolerance (ZA1), expanded Git & Permissions (GT1), Clean Code & DDD (CC1), new policy sections (ID1, DS1, FS1, LOC1, MO1) and a detailed Code Change Policy Contract.
User Documentation
README.md
Added Docs badge, bumped installation example to 0.1.5 display, and new "Snapshots" section describing snapshot publishing and consumption with Gradle/Maven snippets.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer (push/tag)
  participant GH as GitHub Actions
  participant Gradle as Gradle build
  participant Repo as Artifact Repo (Sonatype)
  Dev->>GH: push to main / create release
  GH->>Gradle: read `VERSION_NAME` (via workflow output)
  GH->>GH: set `is_snapshot` output (true/false)
  alt is_snapshot == true
    GH->>Gradle: run publish (snapshot)
    Gradle->>Repo: publish `*-SNAPSHOT`
  else is_snapshot == false
    GH->>GH: Release flow continues
    GH->>Gradle: build & test, then publish release
    Gradle->>Repo: publish release artifact
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🌱 A snapshot caught mid-flight, a version set to play,
Workflows watch the tag and say who may publish today,
Docs and rules aligned like stars to guide the climb,
Small changes, steady rails—releases now keep time. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ci: prevent SNAPSHOT releases; bump to 0.1.6-SNAPSHOT' clearly and concisely describes the two main changes: preventing SNAPSHOT releases in CI/Release workflows and bumping the version.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description clearly relates to the changeset: it documents the addition of SNAPSHOT guardrails to CI/Release workflows, bumps the version to 0.1.6-SNAPSHOT, and updates README documentation for snapshot dependencies.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3134895ba2

ℹ️ 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".

}

dependencies {
implementation("com.williamcallahan:apple-maps-java:0.1.6-SNAPSHOT")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent README updater from rewriting snapshot coordinate

Adding this -SNAPSHOT dependency example introduces a regression with the existing UpdateReadmeVersion workflow: its global regex replacement updates every implementation("com.williamcallahan:apple-maps-java:...") occurrence, so the next scheduled/release run will overwrite this snapshot line to the latest release version and break the snapshot instructions. Scope the replacement to the release-install snippet (or explicitly exclude the snapshot block) so docs stay correct after automation runs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/CI.yaml:
- Around line 32-41: The version_check step currently sets VERSION from
gradle.properties but will silently treat a missing or empty VERSION_NAME as
non-snapshot; modify the run block for the step with id version_check to enable
strict shell mode (set -euo pipefail) and add an explicit non-empty check for
VERSION (e.g., if [ -z "$VERSION" ]; then echo "ERROR: VERSION_NAME not found or
empty" >&2; exit 1; fi) before the SNAPSHOT test, so the job fails fast and
loudly when VERSION_NAME is absent.

Comment on lines +32 to +41
- name: Check if SNAPSHOT version
id: version_check
run: |
VERSION=$(grep '^VERSION_NAME=' gradle.properties | cut -d'=' -f2)
echo "VERSION=${VERSION}-SNAPSHOT" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
if [[ "$VERSION" == *-SNAPSHOT ]]; then
echo "is_snapshot=true" >> $GITHUB_OUTPUT
else
echo "is_snapshot=false" >> $GITHUB_OUTPUT
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against missing VERSION_NAME to avoid silent skips.

If VERSION_NAME is absent or empty, this step will quietly set is_snapshot=false and skip snapshot publishing. Adding strict mode + a non-empty check makes the failure loud and easy to debug. Tiny CI hygiene win. 🌱

✅ Suggested hardening
       - name: Check if SNAPSHOT version
         id: version_check
+        shell: bash
         run: |
-          VERSION=$(grep '^VERSION_NAME=' gradle.properties | cut -d'=' -f2)
+          set -euo pipefail
+          VERSION=$(grep -E '^VERSION_NAME=' gradle.properties | head -n1 | cut -d'=' -f2 | tr -d '\r')
+          if [[ -z "$VERSION" ]]; then
+            echo "::error::VERSION_NAME not found in gradle.properties"
+            exit 1
+          fi
           echo "Version: $VERSION"
           if [[ "$VERSION" == *-SNAPSHOT ]]; then
-            echo "is_snapshot=true" >> $GITHUB_OUTPUT
+            echo "is_snapshot=true" >> "$GITHUB_OUTPUT"
           else
-            echo "is_snapshot=false" >> $GITHUB_OUTPUT
+            echo "is_snapshot=false" >> "$GITHUB_OUTPUT"
           fi
🤖 Prompt for AI Agents
In @.github/workflows/CI.yaml around lines 32 - 41, The version_check step
currently sets VERSION from gradle.properties but will silently treat a missing
or empty VERSION_NAME as non-snapshot; modify the run block for the step with id
version_check to enable strict shell mode (set -euo pipefail) and add an
explicit non-empty check for VERSION (e.g., if [ -z "$VERSION" ]; then echo
"ERROR: VERSION_NAME not found or empty" >&2; exit 1; fi) before the SNAPSHOT
test, so the job fails fast and loudly when VERSION_NAME is absent.

…ndency

- Add Mintlify docs badge to badge row
- Add version callout with Maven Central and mvnrepository links
- Add Maven <dependency> element to snapshot XML section
- Clarify snapshots are auto-published on every push to main
Copilot AI review requested due to automatic review settings April 2, 2026 18:39
Comment on lines +77 to +102
implementation("com.williamcallahan:apple-maps-java:0.1.6-SNAPSHOT")
}
```

Maven:

```xml
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.williamcallahan</groupId>
<artifactId>apple-maps-java</artifactId>
<version>0.1.6-SNAPSHOT</version>
</dependency>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 UpdateReadmeVersion will overwrite snapshot coordinates with the stable version

The UpdateReadmeVersion.yaml perl substitutions use the /g (global) flag, so they match all occurrences of the dependency coordinates in the file — including the new snapshot section. The next time that workflow runs (daily schedule, or on the next release), it will replace 0.1.6-SNAPSHOT in both the Gradle and Maven snapshot snippets with the latest Maven Central stable version (e.g., 0.1.5), silently corrupting the documentation for consumers who rely on snapshots.

The simplest fix is to guard the regex so it only touches non-SNAPSHOT versions:

# Gradle snippet — stable only
s/(implementation\("com\.williamcallahan:apple-maps-java:)(?!.*SNAPSHOT)[^"]+("\))/$1$v$2/g;

# Maven snippet — stable only
s#(<dependency>\s*<groupId>com\.williamcallahan</groupId>\s*<artifactId>apple-maps-java</artifactId>\s*<version>)(?!.*SNAPSHOT)[^<]+(</version>\s*</dependency>)#$1$v$2#gms;

Alternatively, wrap each stable snippet in HTML comment markers and scope the replacement to only that region.

Prompt To Fix With AI
This is a comment left during a code review.
Path: README.md
Line: 77-102

Comment:
**`UpdateReadmeVersion` will overwrite snapshot coordinates with the stable version**

The `UpdateReadmeVersion.yaml` perl substitutions use the `/g` (global) flag, so they match **all** occurrences of the dependency coordinates in the file — including the new snapshot section. The next time that workflow runs (daily schedule, or on the next release), it will replace `0.1.6-SNAPSHOT` in both the Gradle and Maven snapshot snippets with the latest Maven Central stable version (e.g., `0.1.5`), silently corrupting the documentation for consumers who rely on snapshots.

The simplest fix is to guard the regex so it only touches non-SNAPSHOT versions:

```perl
# Gradle snippet — stable only
s/(implementation\("com\.williamcallahan:apple-maps-java:)(?!.*SNAPSHOT)[^"]+("\))/$1$v$2/g;

# Maven snippet — stable only
s#(<dependency>\s*<groupId>com\.williamcallahan</groupId>\s*<artifactId>apple-maps-java</artifactId>\s*<version>)(?!.*SNAPSHOT)[^<]+(</version>\s*</dependency>)#$1$v$2#gms;
```

Alternatively, wrap each stable snippet in HTML comment markers and scope the replacement to only that region.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Cursor Fix in Codex

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates CI/release guardrails to prevent accidental SNAPSHOT releases to Maven Central, bumps the project to the next snapshot version, and adds snapshot consumption + Mintlify docs metadata.

Changes:

  • Add workflow checks to block publishing SNAPSHOTs via the release workflow and only publish snapshots from main when VERSION_NAME ends with -SNAPSHOT.
  • Bump VERSION_NAME to 0.1.6-SNAPSHOT and document snapshot repository/dependency coordinates in the README.
  • Introduce Mintlify docs configuration (docs.json) and add front matter to existing docs pages.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Adds docs badge, stable release pointer, and snapshot repository/dependency instructions.
gradle.properties Bumps VERSION_NAME to 0.1.6-SNAPSHOT.
docs/usage.md Adds Mintlify front matter metadata.
docs/tests.md Adds Mintlify front matter metadata.
docs/docs.json Adds Mintlify documentation site configuration and navigation.
docs/contracts/code-change.md Adds a “code change policy contract” doc page.
docs/cli.md Adds Mintlify front matter metadata.
docs/authorization.md Adds Mintlify front matter metadata.
AGENTS.md Expands and reorganizes agent rules (zero-tolerance, git permissions, architecture, etc.).
.github/workflows/UpdateReadmeVersion.yaml Ensures README updates are performed against main instead of a release ref.
.github/workflows/Release.yaml Fails fast when the release tag resolves to a -SNAPSHOT version.
.github/workflows/CI.yaml Publishes snapshots only when VERSION_NAME is a -SNAPSHOT and avoids overriding -Pversion.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


## Installation

> Latest stable release: **0.1.5** — [view on Maven Central](https://central.sonatype.com/artifact/com.williamcallahan/apple-maps-java) | [view on mvnrepository](https://mvnrepository.com/artifact/com.williamcallahan/apple-maps-java)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README now hardcodes the latest stable release version ("Latest stable release: 0.1.5"), but the UpdateReadmeVersion workflow only rewrites the dependency snippet versions. This line will drift after the next release unless the workflow is updated to rewrite it too (or the line is removed in favor of the Central link alone).

Suggested change
> Latest stable release: **0.1.5**[view on Maven Central](https://central.sonatype.com/artifact/com.williamcallahan/apple-maps-java) | [view on mvnrepository](https://mvnrepository.com/artifact/com.williamcallahan/apple-maps-java)
> View the latest release on [Maven Central](https://central.sonatype.com/artifact/com.williamcallahan/apple-maps-java) | [mvnrepository](https://mvnrepository.com/artifact/com.williamcallahan/apple-maps-java)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants