|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a Gradle settings plugin that enables build caching using Hazelcast as the cache backend. The plugin allows Gradle builds to store and retrieve task outputs from a distributed Hazelcast cluster, speeding up builds across multiple machines or build agents. |
| 8 | + |
| 9 | +## Build Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +# Build the plugin |
| 13 | +./gradlew build |
| 14 | + |
| 15 | +# Run tests |
| 16 | +./gradlew test |
| 17 | + |
| 18 | +# Clean build artifacts |
| 19 | +./gradlew clean |
| 20 | + |
| 21 | +# Check for dependency vulnerabilities (OWASP) |
| 22 | +./gradlew dependencyCheckAnalyze |
| 23 | + |
| 24 | +# Check for dependency updates |
| 25 | +./gradlew dependenceiesUpdates |
| 26 | +``` |
| 27 | + |
| 28 | +## Publishing Commands |
| 29 | + |
| 30 | +```bash |
| 31 | +# Publish to local Maven repository for testing |
| 32 | +./gradlew publishToMavenLocal |
| 33 | + |
| 34 | +# Release workflow (requires credentials and JDK 11+) |
| 35 | +./gradlew release # This creates a git tag, publishes, and closes the staging repository |
| 36 | + |
| 37 | +# Publish manually to Central Portal (for testing) |
| 38 | +./gradlew publishToSonatype |
| 39 | + |
| 40 | +# Close staging repository (after publishToSonatype) |
| 41 | +./gradlew closeSonatypeStagingRepository |
| 42 | + |
| 43 | +# Release to Maven Central (manually after closing - requires separate invocation) |
| 44 | +./gradlew findSonatypeStagingRepository releaseSonatypeStagingRepository |
| 45 | + |
| 46 | +# All-in-one manual publish and close |
| 47 | +./gradlew publishToSonatype closeSonatypeStagingRepository |
| 48 | +``` |
| 49 | + |
| 50 | +The release process is automated using the `net.researchgate.release` plugin. After release, the `afterReleaseBuild` task automatically publishes and closes the staging repository using gradle-nexus/publish-plugin 2.0.0. You must then manually release via the Portal UI at [central.sonatype.com/publishing/deployments](https://central.sonatype.com/publishing/deployments) or run `releaseSonatypeStagingRepository` separately. |
| 51 | + |
| 52 | +## Architecture |
| 53 | + |
| 54 | +### Core Components |
| 55 | + |
| 56 | +**HazelcastPlugin** (`src/main/java/com/github/sinwe/gradle/caching/hazelcast/HazelcastPlugin.java`) |
| 57 | +- Entry point - implements Gradle's `Plugin<Settings>` interface |
| 58 | +- Registers `HazelcastBuildCache` as a build cache service via `HazelcastBuildCacheServiceFactory` |
| 59 | +- Automatically disables local cache and configures Hazelcast as the remote cache |
| 60 | +- The factory creates a Hazelcast client connection and wraps the Hazelcast IMap in Gradle's `MapBasedBuildCacheService` |
| 61 | + |
| 62 | +**HazelcastBuildCache** (`src/main/java/com/github/sinwe/gradle/caching/hazelcast/HazelcastBuildCache.java`) |
| 63 | +- Configuration class extending `AbstractBuildCache` |
| 64 | +- Defines three configurable properties: `host`, `port`, and `name` |
| 65 | +- Supports system property overrides: `com.github.sinwe.gradle.caching.hazelcast.{host,port,name}` |
| 66 | +- Default values: host=`127.0.0.1`, port=`5701`, name=`gradle-task-cache` |
| 67 | +- The `host` property supports comma-separated values for multiple Hazelcast nodes |
| 68 | + |
| 69 | +### Key Design Decisions |
| 70 | + |
| 71 | +1. **Settings Plugin**: This is a settings plugin (not a project plugin), so it's applied in `settings.gradle` rather than `build.gradle`. This is required because build cache configuration happens at settings evaluation time. |
| 72 | + |
| 73 | +2. **MapBasedBuildCacheService**: The plugin leverages Gradle's built-in `MapBasedBuildCacheService` which wraps any `java.util.Map` implementation. The Hazelcast `IMap` is a distributed map that naturally fits this pattern. |
| 74 | + |
| 75 | +3. **Client Connection**: Uses Hazelcast client mode (not embedded), connecting to an external Hazelcast cluster. The connection is established once per build when the factory creates the service. |
| 76 | + |
| 77 | +4. **Multiple Hosts**: The factory parses the comma-separated host list and appends the port to each host address before configuring the Hazelcast client's network config. |
| 78 | + |
| 79 | +## Testing |
| 80 | + |
| 81 | +**IntegrationTest.groovy** (`src/test/groovy/com/github/sinwe/gradle/caching/hazelcast/IntegrationTest.groovy`) |
| 82 | +- Uses Gradle TestKit to run actual Gradle builds |
| 83 | +- Tests verify tasks are cached and retrieved correctly |
| 84 | +- The `HazelcastService` JUnit rule starts an embedded Hazelcast instance on port 5710 for testing |
| 85 | + |
| 86 | +**HazelcastService.java** (`src/test/groovy/com/github/sinwe/gradle/caching/hazelcast/HazelcastService.java`) |
| 87 | +- JUnit `ExternalResource` that manages a test Hazelcast instance lifecycle |
| 88 | +- Configures Hazelcast with multicast disabled (using the specified port only) |
| 89 | +- Automatically starts before each test and shuts down after |
| 90 | + |
| 91 | +## Dependencies Management |
| 92 | + |
| 93 | +Dependencies are centralized in `versions.gradle` using `ext.libraries` map. When updating dependencies: |
| 94 | +- Update version numbers in the `ext` block at the top of `versions.gradle` |
| 95 | +- Reference them via the `libraries` map in `build.gradle` |
| 96 | + |
| 97 | +Key dependencies: |
| 98 | +- `hazelcast-client`: Used by the plugin to connect to Hazelcast |
| 99 | +- `hazelcast`: Used only in tests for the embedded instance |
| 100 | +- Gradle plugin dependencies: release plugin, OWASP dependency check, version checker |
| 101 | + |
| 102 | +## Gradle Configuration |
| 103 | + |
| 104 | +The project uses: |
| 105 | +- Gradle 6.9.4 (via Gradle wrapper) |
| 106 | +- Java 8 source/target compatibility (requires JDK 11+ for building due to gradle-nexus/publish-plugin 2.0.0) |
| 107 | +- `java-gradle-plugin` for automatic plugin metadata generation |
| 108 | +- Plugin ID: `com.github.sinwe.gradle.caching.hazelcast` |
| 109 | +- Group: `com.github.sinwe.gradle.caching.hazelcast` |
| 110 | +- Artifact: `gradle-hazelcast-plugin` |
| 111 | + |
| 112 | +## Publishing Configuration |
| 113 | + |
| 114 | +The project uses the `io.github.gradle-nexus.publish-plugin` (version 2.0.0) for publishing to Sonatype Central Portal. |
| 115 | + |
| 116 | +Publications go to: |
| 117 | +- **Releases/Staging**: `https://ossrh-staging-api.central.sonatype.com/service/local/` |
| 118 | +- **Snapshots**: `https://central.sonatype.com/repository/maven-snapshots/` |
| 119 | + |
| 120 | +### Authentication Setup |
| 121 | + |
| 122 | +Credentials are sourced from (in order of precedence): |
| 123 | +1. Gradle properties in `~/.gradle/gradle.properties`: |
| 124 | + - `sonatypeUsername` - User token username from central.sonatype.com/account |
| 125 | + - `sonatypePassword` - User token password from central.sonatype.com/account |
| 126 | +2. Environment variables: |
| 127 | + - `ORG_GRADLE_PROJECT_sonatypeUsername` |
| 128 | + - `ORG_GRADLE_PROJECT_sonatypePassword` |
| 129 | + |
| 130 | +**Important**: Central Portal tokens are different from legacy OSSRH tokens. Generate new tokens at https://central.sonatype.com/account |
| 131 | + |
| 132 | +### Publication Artifacts |
| 133 | + |
| 134 | +Artifacts include: |
| 135 | +- Main JAR (from Java component) |
| 136 | +- Sources JAR |
| 137 | +- Javadoc JAR |
| 138 | + |
| 139 | +Signing is required only for release versions (non-SNAPSHOT). |
| 140 | + |
| 141 | +### Migration Notes |
| 142 | + |
| 143 | +This project has been migrated from the legacy OSSRH system to Sonatype Central Portal (as of 2025). The OSSRH service was sunset on June 30, 2025. Key changes: |
| 144 | +- New authentication tokens required from central.sonatype.com |
| 145 | +- Publishing workflow now uses staging repositories with explicit close/release steps |
| 146 | +- Publication timeline: ~15 minutes after release for artifacts to appear on Maven Central |
0 commit comments