Skip to content

Commit f4cc6e3

Browse files
BrendonovichEC2 Default User
andauthored
Staging cluster deployment (#1183)
* bruh * workflow cluster stuff * fix vercel deploy * attempt @vercel/otel integration * vercel otel idk * aurora db * separate shard db * more stuff * make aws credentials optional * cleanup * types * types * update infra * workflow secret * remove aws keys from ecs * update deps * reorganise error handling a bit * fixup envs * fix handleDomainError * log if no rpc auth header * remove some NEXT_PUBLIC envs + add s3 buffer * fix ECS credentials * formatting * restrict loom import to team * remove unused env --------- Co-authored-by: EC2 Default User <ec2-user@ip-172-31-19-0.ec2.internal>
1 parent 16bf692 commit f4cc6e3

24 files changed

Lines changed: 1113 additions & 189 deletions

File tree

.dockerignore

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
target/
2-
node_modules/
3-
crates/
1+
target
2+
crates
3+
**/node_modules
4+
**/.next

.github/workflows/ci.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ jobs:
115115
echo 'VITE_POSTHOG_KEY=${{ secrets.NEXT_PUBLIC_POSTHOG_KEY }}' >> .env
116116
echo 'VITE_POSTHOG_HOST=${{ secrets.NEXT_PUBLIC_POSTHOG_HOST }}' >> .env
117117
echo 'VITE_SERVER_URL=${{ secrets.NEXT_PUBLIC_WEB_URL }}' >> .env
118-
echo "NEXT_PUBLIC_CAP_AWS_REGION=${{ secrets.NEXT_PUBLIC_CAP_AWS_REGION }}" >> .env
119-
echo "NEXT_PUBLIC_CAP_AWS_BUCKET=${{ secrets.NEXT_PUBLIC_CAP_AWS_BUCKET }}" >> .env
120118
121119
cat .env >> $GITHUB_ENV
122120
@@ -185,8 +183,6 @@ jobs:
185183
echo 'VITE_POSTHOG_KEY=${{ secrets.NEXT_PUBLIC_POSTHOG_KEY }}' >> .env
186184
echo 'VITE_POSTHOG_HOST=${{ secrets.NEXT_PUBLIC_POSTHOG_HOST }}' >> .env
187185
echo 'VITE_SERVER_URL=${{ secrets.NEXT_PUBLIC_WEB_URL }}' >> .env
188-
echo "NEXT_PUBLIC_CAP_AWS_REGION=${{ secrets.NEXT_PUBLIC_CAP_AWS_REGION }}" >> .env
189-
echo "NEXT_PUBLIC_CAP_AWS_BUCKET=${{ secrets.NEXT_PUBLIC_CAP_AWS_BUCKET }}" >> .env
190186
191187
- name: Copy .env to apps/desktop
192188
run: cp .env apps/desktop/.env

.github/workflows/docker-build-web.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ jobs:
3636
run: |
3737
echo "WEB_URL=http://localhost:3000" > .env
3838
echo "NEXT_PUBLIC_DOCKER_BUILD=true" >> .env
39-
echo "NEXT_PUBLIC_CAP_AWS_BUCKET=capso" >> .env
40-
echo "NEXT_PUBLIC_CAP_AWS_REGION=us-east-1" >> .env
4139
4240
- name: Login to GitHub Container Registry
4341
uses: docker/login-action@v3

.github/workflows/publish.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,6 @@ jobs:
185185
echo 'VITE_POSTHOG_KEY=${{ secrets.VITE_POSTHOG_KEY }}' >> .env
186186
echo 'VITE_POSTHOG_HOST=${{ secrets.VITE_POSTHOG_HOST }}' >> .env
187187
echo 'VITE_SERVER_URL=${{ secrets.NEXT_PUBLIC_WEB_URL }}' >> .env
188-
echo "NEXT_PUBLIC_CAP_AWS_REGION=${{ secrets.NEXT_PUBLIC_CAP_AWS_REGION }}" >> .env
189-
echo "NEXT_PUBLIC_CAP_AWS_BUCKET=${{ secrets.NEXT_PUBLIC_CAP_AWS_BUCKET }}" >> .env
190188
echo 'RUST_TARGET_TRIPLE=${{ matrix.settings.target }}' >> .env
191189
192190
- name: Build app

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
auto-install-peers = true
2+
force-legacy-deploy = true

CLAUDE.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ import { getCurrentUser } from "@cap/database/auth/session";
171171
export async function updateVideo(data: FormData) {
172172
const user = await getCurrentUser();
173173
if (!user?.id) throw new Error("Unauthorized");
174-
174+
175175
// Database operations with Drizzle
176176
return await db().update(videos).set({ ... }).where(eq(videos.id, id));
177177
}
@@ -220,7 +220,6 @@ const updateMutation = useMutation({
220220

221221
### Build/Client (selected)
222222
- `NEXT_PUBLIC_WEB_URL`
223-
- `NEXT_PUBLIC_CAP_AWS_BUCKET`, `NEXT_PUBLIC_CAP_AWS_REGION`
224223
- `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST`
225224
- `NEXT_PUBLIC_DOCKER_BUILD` (enables Next.js standalone output)
226225

@@ -268,7 +267,7 @@ const updateMutation = useMutation({
268267
- **Connection errors**: Verify Docker containers are running
269268
- **Schema drift**: Run `pnpm --dir packages/database db:check`
270269

271-
### Desktop App Issues
270+
### Desktop App Issues
272271
- **IPC binding errors**: Restart dev server to regenerate `tauri.ts`
273272
- **Rust compile errors**: Check Cargo.toml dependencies
274273
- **Permission issues**: macOS/Windows may require app permissions
@@ -392,8 +391,8 @@ Minimize `useEffect` usage: compute during render, handle logic in event handler
392391

393392
### Media Processing Flow
394393
```
395-
Desktop Recording → Local Files → Upload to S3 →
396-
Background Processing (tasks service) →
394+
Desktop Recording → Local Files → Upload to S3 →
395+
Background Processing (tasks service) →
397396
Transcription/AI Enhancement → Database Storage
398397
```
399398

apps/web-cluster/src/runner/index.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ClusterWorkflowEngine, RunnerAddress } from "@effect/cluster";
44
import * as NodeSdk from "@effect/opentelemetry/NodeSdk";
55
import {
66
FetchHttpClient,
7+
Headers,
78
HttpApiBuilder,
89
HttpMiddleware,
910
HttpRouter,
@@ -24,6 +25,12 @@ import { ContainerMetadata } from "../cluster/container-metadata.ts";
2425
import { DatabaseLive, ShardDatabaseLive } from "../shared/database.ts";
2526
import { HealthServerLive } from "./health-server.ts";
2627

28+
class RpcAuthSecret extends Effect.Service<RpcAuthSecret>()("RpcAuthSecret", {
29+
effect: Effect.map(Config.string("WORKFLOWS_RPC_SECRET"), (v) => ({
30+
authSecret: v,
31+
})),
32+
}) {}
33+
2734
const ClusterWorkflowLive = Layer.unwrapEffect(
2835
Effect.gen(function* () {
2936
const containerMeta = yield* ContainerMetadata;
@@ -48,6 +55,28 @@ const RpcsLive = RpcServer.layer(Workflows.RpcGroup).pipe(
4855
Layer.provide(Workflows.WorkflowsLayer),
4956
Layer.provide(ClusterWorkflowLive),
5057
Layer.provide(RpcServer.layerProtocolHttp({ path: "/" })),
58+
Layer.provide(
59+
Layer.effect(
60+
Workflows.SecretAuthMiddleware,
61+
Effect.gen(function* () {
62+
const { authSecret } = yield* RpcAuthSecret;
63+
64+
return Workflows.SecretAuthMiddleware.of(
65+
Effect.fn(function* (options) {
66+
const authHeader = Headers.get(options.headers, "authorization");
67+
if (Option.isNone(authHeader) || authHeader.value !== authSecret) {
68+
if (Option.isNone(authHeader))
69+
yield* Effect.log("No auth header provided");
70+
71+
return yield* new Workflows.InvalidRpcAuth();
72+
}
73+
74+
return yield* options.next;
75+
}),
76+
);
77+
}),
78+
),
79+
),
5180
Layer.provide(Workflows.RpcSerialization),
5281
);
5382

@@ -92,6 +121,7 @@ HttpRouter.Default.serve().pipe(
92121
Layer.provide(FetchHttpClient.layer),
93122
Layer.provide(DatabaseLive),
94123
Layer.provide(TracingLayer),
124+
Layer.provide(RpcAuthSecret.Default),
95125
Layer.launch,
96126
NodeRuntime.runMain,
97127
);

apps/web/Dockerfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm i --fro
1212

1313
ARG NEXT_PUBLIC_DOCKER_BUILD=true
1414
ENV NEXT_PUBLIC_WEB_URL=http://localhost:3000
15-
ENV NEXT_PUBLIC_CAP_AWS_BUCKET=capso
16-
ENV NEXT_PUBLIC_CAP_AWS_REGION=us-east-1
1715

1816
RUN pnpm run build:web
1917

apps/web/lib/server.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ import {
1616
import { type HttpAuthMiddleware, Video } from "@cap/web-domain";
1717
import {
1818
FetchHttpClient,
19+
Headers,
1920
type HttpApi,
2021
HttpApiBuilder,
2122
HttpApiClient,
2223
HttpMiddleware,
2324
HttpServer,
2425
} from "@effect/platform";
25-
import { RpcClient } from "@effect/rpc";
26+
import { RpcClient, RpcMessage, RpcMiddleware } from "@effect/rpc";
2627
import {
2728
Cause,
2829
Config,
@@ -31,6 +32,7 @@ import {
3132
Layer,
3233
ManagedRuntime,
3334
Option,
35+
Redacted,
3436
} from "effect";
3537
import { cookies } from "next/headers";
3638

@@ -50,11 +52,21 @@ const CookiePasswordAttachmentLive = Layer.effect(
5052
}),
5153
);
5254

55+
class WorkflowRpcSecret extends Effect.Service<WorkflowRpcSecret>()(
56+
"WorkflowRpcSecret",
57+
{
58+
effect: Effect.map(
59+
Config.redacted(Config.string("WORKFLOWS_RPC_SECRET")),
60+
(v) => ({ authSecret: v }),
61+
),
62+
},
63+
) {}
64+
5365
const WorkflowRpcLive = Layer.scoped(
5466
Workflows.RpcClient,
5567
Effect.gen(function* () {
5668
const url = Option.getOrElse(
57-
yield* Config.option(Config.string("REMOTE_WORKFLOW_URL")),
69+
yield* Config.option(Config.string("WORKFLOWS_RPC_URL")),
5870
() => "http://127.0.0.1:42169",
5971
);
6072

@@ -66,6 +78,22 @@ const WorkflowRpcLive = Layer.scoped(
6678
),
6779
);
6880
}),
81+
).pipe(
82+
Layer.provide(
83+
RpcMiddleware.layerClient(Workflows.SecretAuthMiddleware, ({ request }) =>
84+
Effect.gen(function* () {
85+
const { authSecret } = yield* WorkflowRpcSecret;
86+
return {
87+
...request,
88+
headers: Headers.set(
89+
request.headers,
90+
"authorization",
91+
Redacted.value(authSecret),
92+
),
93+
};
94+
}),
95+
),
96+
),
6997
);
7098

7199
export const Dependencies = Layer.mergeAll(
@@ -79,7 +107,13 @@ export const Dependencies = Layer.mergeAll(
79107
WorkflowRpcLive,
80108
layerTracer,
81109
).pipe(
82-
Layer.provideMerge(Layer.mergeAll(Database.Default, FetchHttpClient.layer)),
110+
Layer.provideMerge(
111+
Layer.mergeAll(
112+
Database.Default,
113+
FetchHttpClient.layer,
114+
WorkflowRpcSecret.Default,
115+
),
116+
),
83117
);
84118

85119
// purposefully not exposed
@@ -132,6 +166,7 @@ export const apiToHandler = (
132166
Layer.provide(
133167
HttpApiBuilder.middleware(Effect.provide(CookiePasswordAttachmentLive)),
134168
),
169+
Layer.provide(layerTracer),
135170
Layer.provideMerge(Dependencies),
136171
HttpApiBuilder.toWebHandler,
137172
(v) => (req: Request) => v.handler(req),

crates/recording/src/output_pipeline/core.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl TaskPool {
128128
let res = future.await;
129129
match &res {
130130
Ok(_) => info!("Task finished successfully"),
131-
Err(err) => error!("Task failed: {}", err),
131+
Err(err) => error!("Task failed: {:#}", err),
132132
}
133133
res
134134
}

0 commit comments

Comments
 (0)