diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..e5d02a8f --- /dev/null +++ b/.envrc @@ -0,0 +1,7 @@ +if has nix; then + if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM=" + fi +fi + +source_env_if_exists .envrc.local diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 159d58cd..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: CI -on: - push: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Build, Test - run: ./gradlew build --info diff --git a/.github/workflows/ci_linux_windows.yml b/.github/workflows/ci_linux_windows.yml deleted file mode 100644 index 6b67f328..00000000 --- a/.github/workflows/ci_linux_windows.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: CI (Linux, Windows) -on: - push: - branches: - - main - - pull_request: - branches: - - main - -jobs: - build_all: - strategy: - matrix: - os: [ ubuntu-latest, windows-latest ] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Build, Test - run: ./gradlew build --info diff --git a/.github/workflows/java_versions.yml b/.github/workflows/java_versions.yml deleted file mode 100644 index 35604b4d..00000000 --- a/.github/workflows/java_versions.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Java versions -on: - push: - branches: - - main - - pull_request: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - java: [ '8', '11', '16' ] # default is 17. See ci.yml - name: Java version ${{ matrix.java }} - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: ${{ matrix.java }} - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Build, Test - run: ./gradlew build --info diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml deleted file mode 100644 index f6174745..00000000 --- a/.github/workflows/publish-docs.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Documentation -on: - push: - branches: - - main - -jobs: - javadoc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - - - name: "Setup Gradle" - uses: gradle/gradle-build-action@v2 - - - name: "Build docs with JavaDoc" - run: ./gradlew javadoc --info - - - name: "Publish JavaDoc" - uses: peaceiris/actions-gh-pages@v3 - with: - GITHUB_TOKEN: ${{ github.token }} - publish_dir: 'lib/build/docs/javadoc' diff --git a/.github/workflows/publish-github-packages.yml b/.github/workflows/publish-github-packages.yml new file mode 100644 index 00000000..41f2aebe --- /dev/null +++ b/.github/workflows/publish-github-packages.yml @@ -0,0 +1,50 @@ +name: Publish to GitHub Packages + +# Manually triggered release of the GrowthBook SDK artifact to our GitHub +# Packages Maven registry. +on: + workflow_dispatch: + inputs: + neloBuild: + description: 'Nelo re-cut number; version becomes -nelo.' + required: true + default: '1' + version: + description: 'Optional full version override; leave blank to derive from the tag' + required: false + default: '' + modules: + description: 'Gradle publish tasks to run' + required: true + default: ':lib:publish' + type: choice + options: + - ':lib:publish' + - 'publish' + +permissions: + contents: read + packages: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Use exact JDK versions pinned with nix + - uses: DeterminateSystems/nix-installer-action@main + + # The version normally derives from the checked-out tag's gradle.properties plus the + # -nelo. suffix the root build.gradle appends, so it always matches the code being + # built. `version` is upstream's own project property, so the optional override needs + # no patched file; the overlay vendor-qualifies it either way. + - name: Publish to GitHub Packages + run: | + nix develop --command bash -c './gradlew ${{ inputs.modules }} \ + -PneloBuild="${{ inputs.neloBuild }}" \ + ${{ inputs.version != '' && format('-Pversion="{0}"', inputs.version) || '' }} \ + --console=plain --stacktrace' + env: + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml deleted file mode 100644 index ee90b1b8..00000000 --- a/.github/workflows/release-please.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Release-Please - -on: - push: - branches: - - main - -permissions: - contents: write - pull-requests: write - packages: write - issues: write - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - token: ${{ secrets.GITHUB_TOKEN }} - release-type: java-yoshi - package-name: com.github.growthbook.growthbook-sdk-java - command: manifest - - # The following steps only run if a new release was created - - name: Checkout code - if: ${{ steps.release.outputs.release_created }} - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Set up JDK 11 - if: ${{ steps.release.outputs.release_created }} - uses: actions/setup-java@v3 - with: - java-version: '11' - distribution: 'temurin' - cache: gradle - - - name: Build with Gradle - if: ${{ steps.release.outputs.release_created }} - run: ./gradlew build - - - name: Publish to GitHub Packages - if: ${{ steps.release.outputs.release_created }} - run: ./gradlew publish - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload Artifacts to GitHub Release - if: ${{ steps.release.outputs.release_created }} - uses: softprops/action-gh-release@v1 - with: - tag_name: v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }} - files: | - lib/build/libs/lib-*.jar - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index f1f94d25..54b22094 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ build bin .vscode .DS_Store + +/.direnv diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5c87ad8b..8ed0e8b8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.10.10" + ".": "0.11.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a433874..7fab006f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [0.11.0](https://github.com/growthbook/growthbook-sdk-java/compare/v0.10.10...0.11.0) (2026-08-04) + + +### ⚠ BREAKING CHANGES + +* update OkHttp dependencies to version 5.4.0 ([#218](https://github.com/growthbook/growthbook-sdk-java/issues/218)) + +### Features + +* add Caffeine cache adapter module ([#220](https://github.com/growthbook/growthbook-sdk-java/issues/220)) ([bee3e01](https://github.com/growthbook/growthbook-sdk-java/commit/bee3e010ac7b4a2be4c9df59ddbdda9c3470d44d)) +* add configuration validation at client start-up ([#223](https://github.com/growthbook/growthbook-sdk-java/issues/223)) ([f0fb1ae](https://github.com/growthbook/growthbook-sdk-java/commit/f0fb1aecbfdf8f713a39b6e8ca0c44b6f9eda3c2)) +* add custom fields ([#217](https://github.com/growthbook/growthbook-sdk-java/issues/217)) ([06c2b98](https://github.com/growthbook/growthbook-sdk-java/commit/06c2b98b68fd37695efc5ad9bd9fdf870707ff94)) +* add diagnostics API ([#219](https://github.com/growthbook/growthbook-sdk-java/issues/219)) ([32925a6](https://github.com/growthbook/growthbook-sdk-java/commit/32925a6b9140808197424eb2aa26ce73d899ae3b)) +* add JCache (JSR-107) cache adapter module ([#221](https://github.com/growthbook/growthbook-sdk-java/issues/221)) ([621121e](https://github.com/growthbook/growthbook-sdk-java/commit/621121e4d2fc84e2efa11213727601dc3e3cb044)) +* add remote evaluation support ([#216](https://github.com/growthbook/growthbook-sdk-java/issues/216)) ([393fdc8](https://github.com/growthbook/growthbook-sdk-java/commit/393fdc8fd4eec5f346556192fe19ad936905ab7d)) +* Typed feature access ([#224](https://github.com/growthbook/growthbook-sdk-java/issues/224)) ([45c57b4](https://github.com/growthbook/growthbook-sdk-java/commit/45c57b45fec74427c4acbae0e5de296d033e5d50)) + + +### Bug Fixes + +* apply 200 response payload when x-sse-support header is absent ([#231](https://github.com/growthbook/growthbook-sdk-java/issues/231)) ([e1e3b13](https://github.com/growthbook/growthbook-sdk-java/commit/e1e3b130fcf3abbe87c38c5e594f8f7141325407)) +* correct sticky bucketing logic in single-user and multi-user modes ([#211](https://github.com/growthbook/growthbook-sdk-java/issues/211)) ([1ffd7dc](https://github.com/growthbook/growthbook-sdk-java/commit/1ffd7dc30de0fc5e2e56c80cdb69d9ff746aeda1)) +* handle double forced variation values ([#213](https://github.com/growthbook/growthbook-sdk-java/issues/213)) ([0e5cb83](https://github.com/growthbook/growthbook-sdk-java/commit/0e5cb83fcb1126e7cdf4d6bf5fdf21bb37187a6f)) +* prevent unhandled exceptions when processing empty SSE event payloads ([#214](https://github.com/growthbook/growthbook-sdk-java/issues/214)) ([c509792](https://github.com/growthbook/growthbook-sdk-java/commit/c509792a3492ac443f3685b07de7fcff8dbcbf24)) +* update OkHttp dependencies to version 5.4.0 ([#218](https://github.com/growthbook/growthbook-sdk-java/issues/218)) ([72bb348](https://github.com/growthbook/growthbook-sdk-java/commit/72bb348765dc10cca78710dd1e1e6cd487ad4808)) + ## [0.10.10](https://github.com/growthbook/growthbook-sdk-java/compare/v0.10.9...0.10.10) (2026-05-08) diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..234bfcc9 --- /dev/null +++ b/build.gradle @@ -0,0 +1,48 @@ +/* + * Nelo fork overlay. + * + * Upstream has no root build script, so everything fork-specific lives here and every + * upstream file — lib/build.gradle, gradle.properties, the cache adapter modules — stays + * byte-identical. That keeps syncing with upstream a fast-forward instead of a merge. + * + * Upstream already declares a `GitHubPackages` publishing repository (and reads + * GITHUB_ACTOR / GITHUB_TOKEN from the environment); it just points at its own registry. + * We only redirect the URL to ours. + * + * WHY THIS FORK EXISTS: upstream does not publish com.github.growthbook:lib to Maven + * Central, and JitPack 403s in CI. So we rebuild upstream's tagged release unchanged and + * republish it to our own GitHub Packages registry, letting api-v2 consume it as a binary + * instead of building the SDK from source. No SDK behaviour is forked -- if upstream ever + * ships to Maven Central, this repo can be retired. + */ + +// Every artifact we publish is vendor-qualified as -nelo., so a Nelo +// rebuild can never be mistaken for -- or collide with -- a genuine upstream release, and +// we can re-cut the same upstream version (.2, .3) if a build needs redoing. The base +// version tracks upstream's gradle.properties, so it cannot go stale on the next sync. +// Re-cut with -PneloBuild=2; an explicit -Pversion=x.y.z-nelo.N is passed through as-is. +def neloBuild = findProperty('neloBuild') ?: '1' + +gradle.beforeProject { p -> + def v = p.version.toString() + if (v != 'unspecified' && !v.contains('-nelo.')) { + p.version = "${v}-nelo.${neloBuild}" + } +} + +subprojects { + // 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 adapter + // modules inherit it and Gradle rejects the publication outright: + // "groupId (com.github.growthbook ) is not a valid Maven identifier". + // Trim it here so `./gradlew publish` works for every module. + group = group.toString().trim() + + plugins.withId('maven-publish') { + publishing.repositories.withType(MavenArtifactRepository).all { repo -> + if (repo.name == 'GitHubPackages') { + repo.url = uri('https://maven.pkg.github.com/nelo/growthbook-sdk-java') + } + } + } +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..51ef7239 --- /dev/null +++ b/flake.lock @@ -0,0 +1,59 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1781577229, + "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", + "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", + "revCount": 1017464, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/DeterminateSystems/nixpkgs-weekly/0.1.1017464%2Brev-567a49d1913ce81ac6e9582e3553dd90a955875f/019f1749-32d6-7283-9e9a-861bd8478e6a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/DeterminateSystems/nixpkgs-weekly/0.1.995785.tar.gz" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..a81a8ec2 --- /dev/null +++ b/flake.nix @@ -0,0 +1,33 @@ +{ + description = "Nelo fork of growthbook-sdk-java — build & publish the upstream artifact on JDK 17"; + + inputs = { + /** + Prefer DeterminateSystem's nixpkgs-weekly flake over nixpkgs-unstable. + This lagging flake is bumped weekly to reduce the likelihood an update is breaking. + As such it also provides a significantly better cache-hit rate. + */ + nixpkgs.url = "https://flakehub.com/f/DeterminateSystems/nixpkgs-weekly/0.1.995785.tar.gz"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + devShells.default = pkgs.mkShell { + # This SDK builds with its bundled Gradle 7.5.1 wrapper, which only runs on + # JDK <= 18. JDK 17 is the LTS in that range. The resulting Java-8 bytecode + # runs fine on the JDK 25 API service that consumes this artifact. + packages = [ pkgs.jdk17 ]; + shellHook = '' + export JAVA_HOME="${pkgs.jdk17.home}" + ''; + }; + } + ); +} diff --git a/gradle.properties b/gradle.properties index 1b822858..1b826c19 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ # x-release-please-start-version -version=0.10.11-SNAPSHOT +version=0.11.0 # x-release-please-end group=com.github.growthbook \ No newline at end of file diff --git a/lib/src/main/java/growthbook/sdk/java/Version.java b/lib/src/main/java/growthbook/sdk/java/Version.java index 2e67b334..6d6595b0 100644 --- a/lib/src/main/java/growthbook/sdk/java/Version.java +++ b/lib/src/main/java/growthbook/sdk/java/Version.java @@ -8,6 +8,6 @@ public class Version { // The current version of the GrowthBook SDK for Java // x-release-please-start-version - public static final String SDK_VERSION = "0.10.11-SNAPSHOT"; + public static final String SDK_VERSION = "0.11.0"; // x-release-please-end } diff --git a/versions.txt b/versions.txt index dda3859f..f85eb944 100644 --- a/versions.txt +++ b/versions.txt @@ -1,3 +1,3 @@ # Format: # module:released-version:current-version -growthbook-sdk-java:0.10.10:0.10.11-SNAPSHOT \ No newline at end of file +growthbook-sdk-java:0.11.0:0.11.0 \ No newline at end of file