diff --git a/.fernignore b/.fernignore index 8c55e60..670bab1 100644 --- a/.fernignore +++ b/.fernignore @@ -5,6 +5,7 @@ LICENSE README.md .github/CODEOWNERS .github/workflows/ci.yml +.github/workflows/sdk-e2e-status.yml WASM_VERSION .gitignore scripts/ diff --git a/.github/workflows/sdk-e2e-status.yml b/.github/workflows/sdk-e2e-status.yml new file mode 100644 index 0000000..f1e2076 --- /dev/null +++ b/.github/workflows/sdk-e2e-status.yml @@ -0,0 +1,50 @@ +name: sdk-e2e status + +# Makes `sdk-e2e` a commit status on every PR so it can be a required check +# without blocking ordinary PRs: +# +# - update-wasm-v* branches (rules engine bumps opened by schematic-bot from +# schematic-api's rulesengine_release.yml): `pending` until the SDK E2E run +# that the release workflow dispatches in schematic-api reports back +# (its report-status job posts success/failure to this same context). +# - every other PR: `success` immediately; SDK E2E is not required. +# +# A new push to a bump branch resets the status to pending; re-run schematic-api's +# sdk_e2e.yml with sdk-ref= to report on the new head. +# +# pull_request_target so the token can write statuses on fork PRs too. Nothing +# from the PR is checked out or executed here. + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: {} + +jobs: + status: + runs-on: ubuntu-latest + permissions: + statuses: write + steps: + - name: Set sdk-e2e status + env: + GH_TOKEN: ${{ github.token }} + HEAD_REF: ${{ github.event.pull_request.head.ref }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + E2E_URL: https://github.com/SchematicHQ/schematic-api/actions/workflows/sdk_e2e.yml + run: | + case "$HEAD_REF" in + update-wasm-v*) + state=pending + description="Waiting for the SDK E2E run in schematic-api" + ;; + *) + state=success + description="Not a rules engine WASM bump; SDK E2E not required" + ;; + esac + echo "$HEAD_REF @ ${HEAD_SHA:0:8}: sdk-e2e=$state ($description)" + gh api "repos/$GITHUB_REPOSITORY/statuses/$HEAD_SHA" \ + -f state="$state" -f context=sdk-e2e \ + -f description="$description" -f target_url="$E2E_URL" > /dev/null diff --git a/sample-app/src/main/java/sample/App.java b/sample-app/src/main/java/sample/App.java index 75211c2..9212fd6 100644 --- a/sample-app/src/main/java/sample/App.java +++ b/sample-app/src/main/java/sample/App.java @@ -22,6 +22,7 @@ import com.schematic.api.cache.LocalCache; import com.schematic.api.cache.RedisCacheConfig; import com.schematic.api.datastream.DatastreamOptions; +import com.schematic.api.logger.LogLevel; import com.schematic.api.types.CheckFlagRequestBody; import com.schematic.api.types.EventBodyIdentify; import com.schematic.api.types.EventBodyIdentifyCompany; @@ -101,6 +102,9 @@ private static void handleConfigure(HttpExchange exchange) throws IOException { boolean useDataStream = Boolean.TRUE.equals(config.get("useDataStream")); String redisUrl = (String) config.get("redisUrl"); String replicatorUrl = (String) config.get("replicatorUrl"); + // Optional Redis key prefix, as a README-following user would set it. In + // replicator mode it must match the keys the replicator writes ("schematic:"). + String redisKeyPrefix = (String) config.get("redisKeyPrefix"); // Parse flag defaults Map flagDefaults = new HashMap<>(); @@ -120,7 +124,9 @@ private static void handleConfigure(HttpExchange exchange) throws IOException { } } - Schematic.Builder builder = Schematic.builder().apiKey(apiKey); + // Debug so the SDK's "falling back to API" and replicator health lines + // show up in the E2E job's test app log, as in the other testapps. + Schematic.Builder builder = Schematic.builder().apiKey(apiKey).logLevel(LogLevel.DEBUG); if (baseUrl != null) { builder.basePath(baseUrl); @@ -151,16 +157,27 @@ private static void handleConfigure(HttpExchange exchange) throws IOException { // DataStream configuration if (useDataStream) { - DatastreamOptions.Builder dsBuilder = - DatastreamOptions.builder().cacheTTL(Duration.ofMillis(CACHE_TTL_MS)); + // Entity caches keep the SDK default TTL, matching the other testapps. + // The short CACHE_TTL_MS is only for the flag-check cache above; in + // replicator mode the replicator owns the Redis entries and a short TTL + // on the SDK's write-back (track -> company metrics update) expires them, + // after which every check logs "Company not found in cache". + DatastreamOptions.Builder dsBuilder = DatastreamOptions.builder(); if (redisUrl != null) { - dsBuilder.redisCache( - RedisCacheConfig.builder().endpoint(redisUrl).build()); + RedisCacheConfig.Builder redisConfig = RedisCacheConfig.builder().endpoint(redisUrl); + if (redisKeyPrefix != null && !redisKeyPrefix.isEmpty()) { + redisConfig.keyPrefix(redisKeyPrefix); + } + dsBuilder.redisCache(redisConfig.build()); } if (replicatorUrl != null) { - dsBuilder.withReplicatorMode(replicatorUrl); + // The health URL is the replicator's readiness endpoint, as in the + // other testapps. The bare base URL is a 404, which the SDK reads + // as "not ready", so every check fell back to the REST API and + // replicator mode was never exercised here. + dsBuilder.withReplicatorMode(replicatorUrl + "/ready"); } builder.datastreamOptions(dsBuilder.build());