Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,21 @@ jobs:
if: needs.changes.outputs.rust == 'true'
permissions:
contents: read
env:
target: aarch64-apple-darwin
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Rust setup
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.settings.target }}
targets: ${{ env.target }}
components: clippy

- uses: ./.github/actions/setup-rust-cache
with:
target: ${{ matrix.settings.target }}
target: ${{ env.target }}

- name: Create .env file in root
run: |
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/docker-build-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Downcase GITHUB_REPOSITORY_OWNER
run: |
echo "REPOSITORY_OWNER=${GITHUB_REPOSITORY_OWNER@L}" >>${GITHUB_ENV}

- name: Build and Push Platform Image
id: build
uses: docker/build-push-action@v5
Expand All @@ -52,7 +56,7 @@ jobs:
file: apps/web/Dockerfile
platforms: linux/${{ matrix.platform }}
push: true
outputs: type=image,name=ghcr.io/${{ github.repository_owner }}/cap-web,push-by-digest=true
outputs: type=image,name=ghcr.io/${{ env.REPOSITORY_OWNER }}/cap-web,push-by-digest=true
cache-from: type=gha,scope=buildx-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=buildx-${{ matrix.platform }}

Expand Down Expand Up @@ -96,7 +100,11 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Downcase GITHUB_REPOSITORY_OWNER
run: |
echo "REPOSITORY_OWNER=${GITHUB_REPOSITORY_OWNER@L}" >>${GITHUB_ENV}

- name: Create Image Manifest
run: |
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/cap-web:${{ inputs.tag || 'latest' }} \
$(find /tmp/digests -type f -not -path "*/\.*" -exec basename {} \; | xargs -I {} echo "ghcr.io/${{ github.repository_owner }}/cap-web@sha256:{}")
docker buildx imagetools create -t ghcr.io/${{ env.REPOSITORY_OWNER }}/cap-web:${{ inputs.tag || 'latest' }} \
$(find /tmp/digests -type f -not -path "*/\.*" -exec basename {} \; | xargs -I {} echo "ghcr.io/${{ env.REPOSITORY_OWNER }}/cap-web@sha256:{}")
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/web/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker.io/docker/dockerfile:1

FROM node:22-alpine AS base
FROM node:24-alpine AS base
RUN corepack enable

FROM base AS builder
Expand Down
55 changes: 0 additions & 55 deletions apps/web/app/api/selfhosted/checkout/route.ts

This file was deleted.

50 changes: 0 additions & 50 deletions apps/web/app/api/selfhosted/migrations/route.ts

This file was deleted.

9 changes: 3 additions & 6 deletions apps/web/instrumentation.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import {
PutBucketPolicyCommand,
S3Client,
} from "@aws-sdk/client-s3";
import { db } from "@cap/database";
import { migrateDb } from "@cap/database/migrate";
import { buildEnv, serverEnv } from "@cap/env";
import { migrate } from "drizzle-orm/mysql2/migrator";
import path from "path";

export async function register() {
if (process.env.NEXT_PUBLIC_IS_CAP) return;
Expand Down Expand Up @@ -92,9 +90,8 @@ async function runMigrations() {
console.log("🔍 DB migrations triggered");
console.log("💿 Running DB migrations...");

await migrate(db() as any, {
migrationsFolder: path.join(process.cwd(), "/migrations"),
});
await migrateDb();

console.log("💿 Migrations run successfully!");
} catch (error) {
console.error("🚨 MIGRATION_FAILED", { error });
Expand Down
53 changes: 31 additions & 22 deletions apps/web/lib/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,43 +60,52 @@ class WorkflowRpcSecret extends Effect.Service<WorkflowRpcSecret>()(
"WorkflowRpcSecret",
{
sync: () => ({
authSecret: Redacted.make(serverEnv().WORKFLOWS_RPC_SECRET),
authSecret: Option.fromNullable(serverEnv().WORKFLOWS_RPC_SECRET).pipe(
Option.map(Redacted.make),
),
}),
},
) {}

const WorkflowRpcLive = Layer.scoped(
Workflows.RpcClient,
const WorkflowRpcLive = Layer.unwrapScoped(
Effect.gen(function* () {
const url = Option.getOrElse(
yield* Config.option(Config.string("WORKFLOWS_RPC_URL")),
() => "http://127.0.0.1:42169",
);

return yield* RpcClient.make(Workflows.RpcGroup).pipe(
const { authSecret } = yield* WorkflowRpcSecret;

if (Option.isNone(authSecret)) return Layer.empty;

const authMiddleware = RpcMiddleware.layerClient(
Workflows.SecretAuthMiddleware,
({ request }) =>
Effect.gen(function* () {
return {
...request,
headers: Headers.set(
request.headers,
"authorization",
Redacted.value(authSecret.value),
),
};
}),
);

const client = yield* RpcClient.make(Workflows.RpcGroup).pipe(
Effect.provide(
RpcClient.layerProtocolHttp({ url }).pipe(
Layer.provide(Workflows.RpcSerialization),
Layer.mergeAll(
RpcClient.layerProtocolHttp({ url }).pipe(
Layer.provide(Workflows.RpcSerialization),
),
authMiddleware,
),
),
);

return Layer.succeed(Workflows.RpcClient, client);
}),
).pipe(
Layer.provide(
RpcMiddleware.layerClient(Workflows.SecretAuthMiddleware, ({ request }) =>
Effect.gen(function* () {
const { authSecret } = yield* WorkflowRpcSecret;
return {
...request,
headers: Headers.set(
request.headers,
"authorization",
Redacted.value(authSecret),
),
};
}),
),
),
);

export const Dependencies = Layer.mergeAll(
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dev": "dotenv -e ../../.env -- next dev",
"build": "next build --turbopack",
"build:web": "next build --turbopack",
"build:web:docker": "cd ../.. && docker build -t cap-web-docker . --no-cache --progress=plain",
"build:docker": "cd ../.. && docker build -t cap-web-docker . --no-cache --progress=plain",
"start": "next start",
"compress-images": "bash tools/compress-images.sh"
},
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"scripts": {
"build": "dotenv -e .env -- turbo run build",
"build:web": "turbo run build:web",
"build:web:docker": "pnpm run --filter=@cap/web build:web:docker",
"build:web:docker": "pnpm run --filter=@cap/web build:docker",
"cap-setup": "dotenv -e .env -- node scripts/setup.js",
"db:generate": "dotenv -e .env -- pnpm --dir packages/database db:generate",
"db:push": "dotenv -e .env -- pnpm --dir packages/database db:push",
"db:studio": "dotenv -e .env -- pnpm --dir packages/database db:studio",
"db:generate": "dotenv -e .env -- pnpm --filter @cap/database db:generate",
"db:push": "dotenv -e .env -- pnpm --filter @cap/database db:push",
"db:studio": "dotenv -e .env -- pnpm --filter @cap/database db:studio",
"dev": "(pnpm run docker:up > /dev/null &) && sleep 5 && trap 'pnpm run docker:stop' EXIT && dotenv -e .env -- turbo run dev --env-mode=loose --ui tui",
"dev:desktop": "pnpm run --filter=@cap/desktop dev",
"dev:manual": "pnpm run docker:up && trap 'pnpm run docker:stop' EXIT && dotenv -e .env -- turbo run dev --filter=!@cap/storybook --no-cache --concurrency 1",
Expand All @@ -24,7 +24,8 @@
"env-setup": "node scripts/env-cli.js",
"check-tauri-versions": "node scripts/check-tauri-plugin-versions.js",
"clean": "find . -name node_modules -o -name .next -o -name .output -o -name .turbo -o -name dist -type d -prune | xargs rm -rf",
"lgtm-otel": "docker run -p 3010:3000 -p 4317:4317 -p 4318:4318 --rm -it docker.io/grafana/otel-lgtm"
"lgtm-otel": "docker run -p 3010:3000 -p 4317:4317 -p 4318:4318 --rm -it docker.io/grafana/otel-lgtm",
"with-env": "dotenv -e .env --"
},
"devDependencies": {
"@biomejs/biome": "2.2.0",
Expand Down
38 changes: 38 additions & 0 deletions packages/database/migrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import path from "node:path";
import { db } from "@cap/database";
import { DrizzleQueryError } from "drizzle-orm";
import { migrate } from "drizzle-orm/mysql2/migrator";

import { runOrgIdBackfill } from "./migrations/orgid_backfill.ts";

async function runMigrate() {
await migrate(db() as any, {
migrationsFolder: path.join(process.cwd(), "/migrations"),
});
}

function errorIsOrgIdMigration(e: unknown): e is DrizzleQueryError {
return (
e instanceof DrizzleQueryError &&
e.query ===
"ALTER TABLE `videos` MODIFY COLUMN `orgId` varchar(15) NOT NULL;"
);
}

export async function migrateDb() {
runMigrate()
.catch(async (e) => {
if (errorIsOrgIdMigration(e)) {
console.log("non-null videos.orgId migration failed, running backfill");

await runOrgIdBackfill();
await runMigrate();
} else throw e;
})
.catch((e) => {
if (errorIsOrgIdMigration(e))
throw new Error(
"videos.orgId backfill failed, you will need to manually update the videos.orgId column before attempting to migrate again.",
);
});
}
16 changes: 0 additions & 16 deletions packages/database/migrations/0003_outstanding_kylun.sql

This file was deleted.

Loading
Loading