Skip to content

chore: make the libraries publishable, add CI, fix repo hygiene and doc drift - #3

Merged
renaudmathieu merged 1 commit into
mainfrom
chore/audit-hygiene-publishability
Oct 20, 2026
Merged

renaudmathieu merged 1 commit into
mainfrom
chore/audit-hygiene-publishability

Conversation

@renaudmathieu

Copy link
Copy Markdown
Owner

First two phases of the 2026-10-20 repository audit: repo hygiene, documentation drift, and everything that stood between the two libraries and a publishable artifact. No behaviour change in the sync protocol; that is a separate PR.

Publishability of :crdt and :sync

  • Drop -Xexplicit-backing-fields. The flag marks every compiled class as produced by a pre-release Kotlin compiler (xi=50 in the class metadata), so any consumer of com.doppio.syncdo:sync would fail with "class compiled with a pre-release version of Kotlin". The sample :server already worked around it with -Xskip-prerelease-check under a wrong diagnosis; that flag is removed too. SyncEngine.syncStatus and the sample repository now use the classic private MutableStateFlow + asStateFlow() pattern. Verified with javap: xi=48 on the rebuilt classes.
  • explicitApi() on both libraries, with public on every declaration. The API baselines (api/*.api) are unchanged, which confirms nothing was accidentally public.
  • Pinned JVM bytecode level. The jvm() target had no jvmTarget, so the published -jvm jar followed whichever JDK ran Gradle (Java 17 class files locally). It now targets Java 11 like the Android target (major version: 55 verified).
  • Maven Central configuration: publishToMavenCentral(CENTRAL_PORTAL) + signAllPublications(). publishToMavenLocal still works with no signing key configured (verified).
  • Removed two unused :sync dependencies (ktor-client-content-negotiation, ktor-serialization-kotlinx-json) and the redundant applyDefaultHierarchyTemplate() calls.

CI

  • New ci.yml on pull requests and main: Linux job runs :crdt:check :sync:check (tests, apiCheck, Android lint), the sample JVM tests, and compiles the desktop and Android app; macOS job runs the iOS simulator tests of both libraries.
  • New publish.yml on v* tags, publishing both libraries to Maven Central with the version taken from the tag. Needs the MAVEN_CENTRAL_USERNAME, MAVEN_CENTRAL_PASSWORD, SIGNING_KEY and SIGNING_KEY_PASSWORD secrets.
  • docs.yml now uses JDK 21 (the desktop app requires a 21 toolchain at configuration time, even for library-only tasks) and has a timeout.

Hygiene

  • data/syncdo-state.json was tracked runtime state, rewritten by every IDE run of the server from the repo root. It is removed from the index, and data/ plus server/data/ are ignored.
  • The sample server's state directory is now a parameter of Application.module, so ApplicationTest runs against a temp directory instead of the developer's state. Root log level goes from trace to info.
  • Desktop window title no longer contains an em dash.
  • .claude/settings.local.json and .claude/worktrees/ ignored for other contributors.

Docs

  • CLAUDE.md: getLocalClock is not suspending; design.pen lives under design/.
  • sync/Module.md: PullRequest and PushDelta carry a nodeId.
  • README.md: the libraries are not on Maven Central yet, so the install snippet points at mavenLocal(); prerequisites say JDK 17+ (not 11+); the state directory doc explains the server/data/ path.
  • crdt/README.md: kotlin.time.Instant is stable since Kotlin 2.2, not 2.1.
  • CONTRIBUTING.md: mentions CI and explicit API mode. CHANGELOG.md: entries for the above.

Verification

  • ./gradlew :crdt:check :sync:check :composeApp:jvmJar (same as the Linux CI job, plus iOS simulator tests locally)
  • ./gradlew :shared:jvmTest :server:test :crdt:apiCheck :sync:apiCheck
  • ./gradlew :crdt:publishToMavenLocal :sync:publishToMavenLocal without a signing key
  • ./gradlew dokkaGenerate with no Undocumented warning
  • javap -v on the rebuilt classes: xi=48, major version: 55

Not in this PR (later phases of the audit)

Sync correctness (lost pushes when the socket dies, in-memory outbox, status stuck in Syncing, malformed frames, clock validation on the server), library API reshaping before 0.1.0 (LwwRegister same-instant writes, OrSet invariant on deserialization, data classes as ABI, SyncEngine constructor), and the sample-app items.

…oc drift

Phases 1 and 2 of the 2026-10-20 audit.

Publishability of :crdt and :sync
- Drop -Xexplicit-backing-fields: it marked every compiled class as built by
  a pre-release Kotlin compiler, so consumers of the published artifact would
  fail unless they passed -Xskip-prerelease-check (which :server did, under a
  wrong diagnosis). syncStatus now uses a private MutableStateFlow.
- Enable explicitApi() and add public modifiers; API baselines are unchanged.
- Pin the jvm() target to Java 11 bytecode like the Android target, instead of
  inheriting the level from the JDK running Gradle.
- Configure Maven Central (Central Portal) publishing with signed publications.
  publishToMavenLocal still works without a signing key.
- Remove two unused :sync dependencies and redundant hierarchy template calls.

CI
- ci.yml: library check (tests, apiCheck, lint), sample JVM tests, app
  compilation on Linux; iOS simulator tests on macOS.
- publish.yml: publish both libraries on v* tags, version taken from the tag.
- docs.yml: JDK 21 and a timeout.

Hygiene
- Untrack data/syncdo-state.json (runtime state) and ignore data/, server/data/.
- Sample server state directory is a parameter of Application.module, so the
  test runs against a temp directory. Root log level trace -> info.
- Desktop window title no longer contains an em dash.

Docs
- CLAUDE.md, sync/Module.md, README.md, crdt/README.md, CONTRIBUTING.md and
  CHANGELOG.md brought in line with the code (callback signatures, message
  shapes, JDK and Kotlin requirements, design file path, publishing status).
@renaudmathieu
renaudmathieu merged commit c785933 into main Oct 20, 2026
2 checks passed
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.

1 participant