Skip to content

Commit 45f6f1f

Browse files
d-csclaude
andcommitted
feat(webapp): let the deployment S2 client endpoints be overridden
The S2 SDK honours only endpoints passed to its constructor — S2Environment.parse() is an opt-in helper the webapp never called — so the deployment event log always targeted hosted S2 and could not be pointed at the local s2-lite emulator. Realtime already has this knob (REALTIME_STREAMS_S2_ENDPOINT); deployments did not, which made a deployed-run end-to-end test impossible locally. S2_ACCOUNT_ENDPOINT and S2_BASIN_ENDPOINT are optional and unset in production, where the SDK's hosted defaults continue to apply. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent fe94700 commit 45f6f1f

4 files changed

Lines changed: 29 additions & 4 deletions

File tree

‎apps/webapp/app/env.server.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ const S2EnvSchema = z.preprocess(
7979
S2_ACCESS_TOKEN: z.string(),
8080
S2_DEPLOYMENT_LOGS_BASIN_NAME: z.string(),
8181
S2_DEPLOYMENT_STREAMS_LOCAL: z.string().default("0"),
82+
// Override the S2 service endpoints. Unset means the SDK's hosted defaults
83+
// (a.s2.dev / {basin}.b.s2.dev). Set both to point deployment event logs at a
84+
// local s2-lite (the docker compose `s2` service), which is what makes a
85+
// deployed-run e2e possible without hosted S2 credentials.
86+
S2_ACCOUNT_ENDPOINT: z.string().optional(),
87+
S2_BASIN_ENDPOINT: z.string().optional(),
8288
}),
8389
z.object({
8490
S2_ENABLED: z.literal("0"),

‎apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { type User } from "~/models/user.server";
1313
import { getUsername } from "~/utils/username";
1414
import { processGitMetadata } from "./BranchesPresenter.server";
1515
import { VercelProjectIntegrationDataSchema } from "~/v3/vercel/vercelProjectIntegrationSchema";
16-
import { S2 } from "@s2-dev/streamstore";
16+
import { createDeploymentS2Client } from "~/v3/s2Client.server";
1717
import { env } from "~/env.server";
1818
import { createRedisClient } from "~/redis.server";
1919
import { tryCatch } from "@trigger.dev/core";
@@ -30,7 +30,7 @@ const s2TokenRedis = createRedisClient("s2-token-cache", {
3030
clusterMode: env.CACHE_REDIS_CLUSTER_MODE_ENABLED === "1",
3131
});
3232

33-
const s2 = env.S2_ENABLED === "1" ? new S2({ accessToken: env.S2_ACCESS_TOKEN }) : undefined;
33+
const s2 = createDeploymentS2Client();
3434

3535
export type ErrorData = {
3636
name: string;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { S2 } from "@s2-dev/streamstore";
2+
import { env } from "~/env.server";
3+
4+
// The SDK honours only endpoints passed to the constructor — `S2Environment.parse()` is an
5+
// opt-in helper — so the endpoint env vars are read here explicitly. Unset means hosted S2.
6+
export function createDeploymentS2Client(): S2 | undefined {
7+
if (env.S2_ENABLED !== "1") {
8+
return undefined;
9+
}
10+
11+
const account = env.S2_ACCOUNT_ENDPOINT;
12+
const basin = env.S2_BASIN_ENDPOINT;
13+
14+
return new S2({
15+
accessToken: env.S2_ACCESS_TOKEN,
16+
...(account !== undefined || basin !== undefined ? { endpoints: { account, basin } } : {}),
17+
});
18+
}

‎apps/webapp/app/v3/services/deployment.server.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import {
2323
import { FEATURE_FLAG, type FeatureFlagKey } from "../featureFlags";
2424
import { flags } from "../featureFlags.server";
2525
import { globalFlagsRegistry } from "../globalFlagsRegistry.server";
26-
import { AppendInput, AppendRecord, S2 } from "@s2-dev/streamstore";
26+
import { AppendInput, AppendRecord } from "@s2-dev/streamstore";
27+
import { createDeploymentS2Client } from "~/v3/s2Client.server";
2728
import { createRedisClient } from "~/redis.server";
2829

2930
const S2_TOKEN_KEY_PREFIX = "s2-token:read:deployment-event-stream:project:";
@@ -35,7 +36,7 @@ const s2TokenRedis = createRedisClient("s2-token-cache", {
3536
tlsDisabled: env.CACHE_REDIS_TLS_DISABLED === "true",
3637
clusterMode: env.CACHE_REDIS_CLUSTER_MODE_ENABLED === "1",
3738
});
38-
const s2 = env.S2_ENABLED === "1" ? new S2({ accessToken: env.S2_ACCESS_TOKEN }) : undefined;
39+
const s2 = createDeploymentS2Client();
3940

4041
const DEPLOY_BUILD_PATH_ENV_FLAG: Partial<Record<RuntimeEnvironmentType, FeatureFlagKey>> = {
4142
PREVIEW: FEATURE_FLAG.deployBuildPathPreview,

0 commit comments

Comments
 (0)