Skip to content

build: rebase Nelo publishing overlay onto upstream 0.11.0 - #2

Open
elliotmjackson wants to merge 2 commits into
mainfrom
nelo-publish-0.11.0
Open

build: rebase Nelo publishing overlay onto upstream 0.11.0#2
elliotmjackson wants to merge 2 commits into
mainfrom
nelo-publish-0.11.0

Conversation

@elliotmjackson

Copy link
Copy Markdown

Review only — do not merge. main is our mirror of upstream, so merging would move it off upstream. Based on main purely so the diff is small: the 0.11.0 release commit plus our overlay. This lands by repointing the fork's default branch to nelo-publish-0.11.0 once api-v2 is migrated.

What this is

Re-cuts the fork's build/publish tooling onto upstream's 0.11.0 (released 2026-08-19). We were on 0.9.91, 69 commits behind. SDK source is 100% upstream; we only add build and publish tooling.

Why the fork exists

Upstream doesn't publish com.github.growthbook:lib to Maven Central and JitPack 403s in CI, so api-v2 can't consume the SDK as a binary. We rebuild upstream's tagged release unchanged and republish it to our own GitHub Packages registry. That rationale now lives in the root build.gradle header, where whoever syncs next will read it — including the retirement condition: if upstream ever ships to Maven Central, this repo can go away. Their new POM metadata (license/developers/scm) suggests that's plausible.

The drift fix

The old patch modified lib/build.gradle — the file upstream churns most — which is why syncing hurt. Upstream has since grown its own GitHubPackages publishing repository, a release plugin driving the version from gradle.properties, and two new optional modules (growthbook-cache-jcache, growthbook-cache-caffeine).

So all fork-specific config now lives in a root build.gradle, which upstream doesn't have. The fork modifies exactly one upstream file: an additive .gitignore line. Future syncs should be near-fast-forwards.

Versioning

Artifacts stay vendor-qualified as <upstream version>-nelo.<N>, preserving what the old pin gave us: a Nelo rebuild can't be mistaken for or collide with a genuine upstream release, and we can re-cut (.2, .3). Two improvements: the base version now tracks upstream's gradle.properties instead of being hardcoded, so it can't go stale on the next sync; and the suffix is appended unconditionally, so no invocation can publish an unqualified version. Re-cut with -PneloBuild=N; -Pversion=x.y.z still works and still gets qualified.

-PpublishVersion is gone in favour of upstream's own version property. Nothing referenced it, including api-v2.

Upstream bug fixed in the overlay

gradle.properties sets group=com.github.growthbook with a trailing space. lib/build.gradle reassigns the group so it escapes, but the cache modules inherit it and Gradle refuses to publish them outright:

Invalid publication 'mavenJava': groupId (com.github.growthbook ) is not a valid Maven identifier

The overlay trims it, so ./gradlew publish works for every module.

Verification

On JDK 17 via the flake (Gradle is still 7.5.1, so the JDK 17 pin stands):

  • ./gradlew build green, full test suite
  • publishToMavenLocal emits all three modules at 0.11.0-nelo.1, jar manifest and POMs agreeing
  • lib POM carries the same seven runtime deps as before (annotations, commons-math3, guava, gson, okhttp, okhttp-sse, slf4j-api), Lombok correctly excluded
  • Version resolution checked for bare, -PneloBuild=7, -Pversion=0.11.0-nelo.4, and -Pversion=9.9.9 (that last yields 9.9.9-nelo.1 — unqualified publishing is impossible)

Blocks api-v2 — breaking changes

api-v2 pins 0.9.91-nelo.1 and will not compile against 0.11.0. Publishing 0.11.0-nelo.1 is safe meanwhile; nothing consumes it until the pin moves.

Upstream moved classes into subpackages — 7 of api-v2's 8 imports:

0.9.91 0.11.0
growthbook.sdk.java.Experiment …java.model.Experiment
growthbook.sdk.java.ExperimentResult …java.model.ExperimentResult
growthbook.sdk.java.FeatureResult …java.model.FeatureResult
growthbook.sdk.java.FeatureResultSource …java.model.FeatureResultSource
growthbook.sdk.java.GBContext …java.model.GBContext
growthbook.sdk.java.TrackingCallback …java.callback.TrackingCallback
growthbook.sdk.java.FeatureUsageCallback …java.callback.FeatureUsageCallback
growthbook.sdk.java.GrowthBook unchanged

Also GBContext.features changed type from JsonObject to Map<String, Feature<?>>, so GrowthBookClientV2.getClient's .features(features) needs the parsed map.

Transitive bumps for consumers: okhttp 4.11.0 → 5.4.0 (upstream's own fix!), guava 31.0.1-jre → 33.3.1-jre, gson 2.9.1 → 2.12.1.

Supersedes #1

Draft PR #1 (perf/cache-parsed-feature-definitions) should be closed as superseded, not forward-ported. Upstream now parses features once into a volatile Map<String, Feature<?>> in GBFeaturesRepository and FeatureEvaluator reads pre-parsed objects — there's no Gson.fromJson in the hot path at all. Same win, at the repository layer, without static mutable state or the reference-identity trick.

Caveat: realising that win depends on the GBContext.features migration above. Have cacheManager hold the parsed Map rather than the raw JsonObject, so the parse happens once per refresh. Parsing inside getClient instead would reintroduce exactly the per-request cost #1 removed.

🤖 Generated with Claude Code

github-actions Bot and others added 2 commits August 19, 2026 21:49
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Re-cuts the fork's build/publish tooling on top of upstream's 0.11.0 release
(was 0.9.91, 69 commits behind). The SDK source is still 100% upstream; we only
add build and publish tooling.

The fork exists because upstream does not publish com.github.growthbook:lib to
Maven Central and JitPack 403s in CI, so api-v2 cannot consume the SDK as a
binary. We rebuild upstream's tagged release unchanged and republish it to our
own GitHub Packages registry. That rationale now lives in the root build.gradle
header, where the next person to sync will actually read it.

Restructure the patch so it no longer touches lib/build.gradle. Upstream has
since grown its own `GitHubPackages` publishing repository, a release plugin
that drives the version from gradle.properties, and two new optional modules
(growthbook-cache-jcache, growthbook-cache-caffeine). Rather than re-patching
lib/build.gradle on every sync -- the file upstream changes most -- all
fork-specific config now lives in a root build.gradle, which upstream does not
have. The fork modifies exactly one upstream file: an additive .gitignore line.

Artifacts stay vendor-qualified as <upstream version>-nelo.<N>, preserving the
guarantee the previous pin gave us: a Nelo rebuild can never be mistaken for or
collide with a genuine upstream release, and we can re-cut (.2, .3) if a build
needs redoing. The base version now tracks upstream's gradle.properties instead
of being hardcoded, so it cannot go stale on the next sync, and the suffix is
appended unconditionally so no invocation can publish an unqualified version.
Re-cut with -PneloBuild=N; -Pversion=x.y.z is still honoured and still gets
qualified.

Also trim the group in the overlay. Upstream's gradle.properties sets
`group=com.github.growthbook ` with a trailing space; lib/build.gradle
reassigns the group so it escapes, but the cache modules inherit it and Gradle
refuses to publish them at all ("groupId (com.github.growthbook ) is not a
valid Maven identifier"). Trimming it makes `./gradlew publish` work for every
module.

Drop upstream's workflows again, now including release-please.yml, which would
otherwise open release PRs against the fork. The publish workflow takes the
re-cut number plus a choice of `:lib:publish` (default, what api-v2 consumes)
or `publish` for all three modules; deriving the version from the checked-out
tag means it always matches the code being built.

Gradle is still 7.5.1, so the flake's JDK 17 pin stands.

Verified on JDK 17 via the flake: `./gradlew build` green (full test suite);
publishToMavenLocal emits all three modules at 0.11.0-nelo.1 with the jar
manifest and POMs agreeing. The lib POM carries the same seven runtime deps as
before (annotations, commons-math3, guava, gson, okhttp, okhttp-sse,
slf4j-api) with Lombok correctly excluded. Version resolution checked for bare,
-PneloBuild, and -Pversion invocations.

NOTE: consumers get breaking transitive bumps -- okhttp 4.11.0 -> 5.4.0,
guava 31.0.1-jre -> 33.3.1-jre, gson 2.9.1 -> 2.12.1 -- and upstream moved
classes into growthbook.sdk.java.{model,callback}, which api-v2 imports.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown

Greptile Summary

The PR rebases the Nelo publishing overlay onto upstream 0.11.0 and adds root-level Gradle, Nix, and manual GitHub Packages publishing configuration.

  • Vendor-qualifies published versions and redirects module publications to Nelo’s registry.
  • Trims the inherited Maven group and supports publishing the SDK alone or all cache modules.
  • Updates upstream release metadata and removes superseded upstream workflows.

Confidence Score: 4/5

The PR appears safe to use for its review-only publishing branch, with the non-blocking recommendation to pin actions in the privileged release workflow to immutable commits.

The Gradle overlay’s publication behavior has no established blocking failure, while the package-write workflow remains unnecessarily exposed to future changes in mutable action references.

Files Needing Attention: .github/workflows/publish-github-packages.yml

Security Review

The publishing workflow uses mutable action references, including a third-party action’s main branch, in a job with package-write permission. Pinning both actions to reviewed commit SHAs would make the privileged release path reproducible and resistant to reference changes.

Important Files Changed

Filename Overview
build.gradle Adds the fork overlay for version qualification, Maven group normalization, and GitHub Packages repository redirection; no blocking defect remains established.
.github/workflows/publish-github-packages.yml Adds the manual Nix-based publication workflow, but its privileged steps depend on mutable action references.
flake.nix Pins a JDK 17 development environment compatible with the bundled Gradle wrapper.
gradle.properties Advances the upstream project version to 0.11.0 while retaining the group value normalized by the root overlay.

Fix all with Greploop Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
### Issue 1
.github/workflows/publish-github-packages.yml:36
**Mutable actions in publishing job**

The package-write workflow executes `DeterminateSystems/nix-installer-action@main` and `actions/checkout@v4`, so those references can later resolve to unreviewed code and make releases non-reproducible or expose the job token. Pin both actions to reviewed full commit SHAs.

**How this was verified:** Both mutable references execute before Gradle in a job granted `packages: write`.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "build: rebase Nelo publishing overlay on..." | Re-trigger Greptile

- uses: actions/checkout@v4

# Use exact JDK versions pinned with nix
- uses: DeterminateSystems/nix-installer-action@main

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 security Mutable actions in publishing job

The package-write workflow executes DeterminateSystems/nix-installer-action@main and actions/checkout@v4, so those references can later resolve to unreviewed code and make releases non-reproducible or expose the job token. Pin both actions to reviewed full commit SHAs.

How this was verified: Both mutable references execute before Gradle in a job granted packages: write.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/publish-github-packages.yml
Line: 36

Comment:
**Mutable actions in publishing job**

The package-write workflow executes `DeterminateSystems/nix-installer-action@main` and `actions/checkout@v4`, so those references can later resolve to unreviewed code and make releases non-reproducible or expose the job token. Pin both actions to reviewed full commit SHAs.

**How this was verified:** Both mutable references execute before Gradle in a job granted `packages: write`.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code Fix in Codex

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