|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Commands |
| 6 | + |
| 7 | +```bash |
| 8 | +# Build |
| 9 | +./gradlew build |
| 10 | + |
| 11 | +# Run all tests |
| 12 | +./gradlew test |
| 13 | + |
| 14 | +# Run tests for a single module |
| 15 | +./gradlew :consul-populate-core:test |
| 16 | + |
| 17 | +# Run a single test class |
| 18 | +./gradlew :consul-populate-core:test --tests "com.frogdevelopment.consul.populate.ConsulFactoryTest" |
| 19 | + |
| 20 | +# Test coverage report |
| 21 | +./gradlew jacocoTestReport |
| 22 | + |
| 23 | +# Build fat JAR (CLI) |
| 24 | +./gradlew :consul-populate-cli:shadowJar |
| 25 | + |
| 26 | +# Build Docker image (requires Docker) |
| 27 | +./gradlew jib -Djib.console='plain' |
| 28 | +``` |
| 29 | + |
| 30 | +## Module Structure |
| 31 | + |
| 32 | +Multi-module Gradle (Kotlin DSL) project. Java 21, Micronaut 4.x, Vertx Consul client. |
| 33 | + |
| 34 | +- **`consul-populate-core`** — library; Consul connection, file parsing, atomic KV population |
| 35 | +- **`consul-populate-git`** — library; JGit integration, polling, webhooks, management endpoints |
| 36 | +- **`consul-populate-cli`** — runnable fat JAR (PicoCLI); one-shot import for CI/CD pipelines |
| 37 | +- **`consul-populate-server`** — Micronaut Netty server; commented out in `settings.gradle.kts`, used for local dev only |
| 38 | +- **`buildSrc`** — convention plugins for Maven publishing (JReleaser) and JaCoCo |
| 39 | + |
| 40 | +## Architecture |
| 41 | + |
| 42 | +### Data flow |
| 43 | + |
| 44 | +``` |
| 45 | +ConsulPopulateCommand (CLI) / GitEndpoint (server) |
| 46 | + → PopulateService.populate() |
| 47 | + → DataImporter.execute() # either FilesImporter or GitImporter |
| 48 | + → GitImporter pulls repo # git mode only; delegates back to FilesImporter |
| 49 | + → FilesImporter reads root dir + merges target subdirectory (override strategy) |
| 50 | + → returns Map<String, String> # key = KV path, value = serialized config |
| 51 | + → builds single TxnRequest # SET new/updated, DELETE removed keys |
| 52 | + → ConsulClient.transaction() # atomic commit |
| 53 | +``` |
| 54 | + |
| 55 | +### Key design decisions |
| 56 | + |
| 57 | +- **Atomic transactions:** all Consul writes are batched into one `TxnRequest`; deletions included to clean up removed |
| 58 | + keys. Never partial-update. |
| 59 | +- **Sealed `FilesImporter`:** restricted to `YamlFilesImporter`, `JsonFilesImporter`, `PropertiesFilesImporter`; new |
| 60 | + formats require adding a permitted subclass. |
| 61 | +- **Async → sync bridge:** `VertxUtils.toBlocking()` wraps Vertx `CompletionStage` for the CLI path. Don't introduce |
| 62 | + raw blocking elsewhere. |
| 63 | +- **`@Requires`-gated beans:** `FilesImportFactory` creates the correct importer based on `consul.files.format`; no |
| 64 | + runtime branching needed. |
| 65 | +- **`RepositoryDirectoryProvider`:** uses `AtomicReference` + `compareAndSet` for lock-free one-time git clone. |
| 66 | +- **Index change listener in `GitPullJob`:** triggers immediate population on detected JGit index changes |
| 67 | + (event-driven, not just timed). |
| 68 | + |
| 69 | +### Configuration properties |
| 70 | + |
| 71 | +Consul connection: `consul.host/port/uri/secured/acl-token/dc/timeout` |
| 72 | +KV path: `consul.kv.prefix` (default `config`), `consul.kv.version` (optional path segment) |
| 73 | +Files mode: `consul.files.format` (YAML|JSON|PROPERTIES), `consul.files.root-path`, `consul.files.target` |
| 74 | +Git mode: `consul.git.uri`, `consul.git.token` (preferred) or `username/password`, `consul.git.branch`, |
| 75 | +`consul.git.poll-enabled`, `consul.git.poll-interval`, `consul.git.webhook.type` (GITHUB|BITBUCKET|CUSTOM), |
| 76 | +`consul.git.webhook.secret` |
| 77 | + |
| 78 | +### Git server endpoints |
| 79 | + |
| 80 | +| Endpoint | Method | Purpose | |
| 81 | +|--------------------|--------|-------------------------------| |
| 82 | +| `/git` | GET | Current repo status/summary | |
| 83 | +| `/git/force-pull` | POST | Manually trigger pull | |
| 84 | +| `/git/webhook` | POST | Receive push events | |
| 85 | +| `/git/toggle-poll` | POST | Enable/disable polling | |
| 86 | + |
| 87 | +Custom webhook providers implement `WebhookPayloadHandler` as a `@Singleton` and set |
| 88 | +`consul.git.webhook.type=CUSTOM`. |
| 89 | + |
| 90 | +## Testing |
| 91 | + |
| 92 | +JUnit 5 + Mockito + AssertJ. Integration tests use Testcontainers (Consul). |
| 93 | +Tests follow BDD given/when/then with `ArgumentCaptor` for Consul client verifications. |
0 commit comments