Skip to content

Commit f0ee392

Browse files
committed
Update compute previews for AI and main
1 parent 3631a93 commit f0ee392

8 files changed

Lines changed: 236 additions & 29 deletions

File tree

.github/workflows/compute-preview.yml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
name: compute preview
22

33
on:
4+
push:
5+
branches:
6+
- main
47
pull_request:
58
types:
69
- opened
@@ -19,12 +22,15 @@ concurrency:
1922

2023
jobs:
2124
deploy-preview:
22-
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
25+
if: >-
26+
(github.event_name == 'pull_request' &&
27+
github.event.pull_request.head.repo.full_name == github.repository) ||
28+
(github.event_name == 'push' && github.ref == 'refs/heads/main')
2329
runs-on: ubuntu-latest
2430
steps:
2531
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2632
with:
27-
ref: ${{ github.event.pull_request.head.sha }}
33+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
2834

2935
- name: Setup pnpm
3036
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
@@ -52,11 +58,13 @@ jobs:
5258
- name: Deploy preview
5359
id: deploy
5460
env:
61+
ANTHROPIC_API_KEY: ${{ secrets.STUDIO_PREVIEW_ANTHROPIC_API_KEY }}
5562
PRISMA_API_TOKEN: ${{ secrets.STUDIO_PREVIEW_COMPUTE_TOKEN }}
56-
PREVIEW_BRANCH_NAME: ${{ github.event.pull_request.head.ref }}
63+
PREVIEW_BRANCH_NAME: ${{ github.event.pull_request.head.ref || github.ref_name }}
5764
run: node scripts/compute-preview/compute-preview-deploy.mjs
5865

5966
- name: Comment preview URL on PR
67+
if: github.event_name == 'pull_request'
6068
env:
6169
GITHUB_REPOSITORY: ${{ github.repository }}
6270
GITHUB_TOKEN: ${{ github.token }}
@@ -67,6 +75,13 @@ jobs:
6775
PREVIEW_VERSION_URL: ${{ steps.deploy.outputs.preview_version_url }}
6876
run: node scripts/compute-preview/compute-preview-comment.mjs
6977

78+
- name: Summarize main preview URL
79+
if: github.event_name == 'push'
80+
run: |
81+
echo "### Main Compute preview" >> "$GITHUB_STEP_SUMMARY"
82+
echo "" >> "$GITHUB_STEP_SUMMARY"
83+
echo "${{ steps.deploy.outputs.preview_service_url }}" >> "$GITHUB_STEP_SUMMARY"
84+
7085
destroy-preview:
7186
if: github.event_name == 'delete' && github.event.ref_type == 'branch'
7287
runs-on: ubuntu-latest

Architecture/compute-preview-deploy.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Compute Preview Deploys
22

3-
This document is normative for branch-scoped Compute preview deployments.
3+
This document is normative for branch-scoped and latest-main Compute preview
4+
deployments.
45

56
## Purpose
67

7-
Pull requests need a live Studio preview without manually creating and cleaning up
8-
Compute services for every branch.
8+
Pull requests and the latest `main` branch need live Studio previews without
9+
manually creating and cleaning up Compute services.
910

1011
The preview deployment path uses the existing `pnpm build:deploy` artifact and
1112
publishes it into the dedicated Compute project named `studio-preview`.
@@ -14,6 +15,7 @@ publishes it into the dedicated Compute project named `studio-preview`.
1415

1516
- A preview deploy MUST run when a pull request is opened, reopened, or updated
1617
with new commits.
18+
- A stable `main` preview deploy MUST run whenever `main` receives new commits.
1719
- Preview deploys MUST only run for branches inside this repository. Forked pull
1820
requests MUST NOT receive the Compute token.
1921
- A preview service MUST be destroyed when the corresponding Git branch is
@@ -24,7 +26,9 @@ publishes it into the dedicated Compute project named `studio-preview`.
2426

2527
## Service Naming
2628

27-
- Preview services MUST be keyed by the pull request branch name.
29+
- Pull request preview services MUST be keyed by the pull request branch name.
30+
- The latest-main preview service MUST be keyed by the literal branch name
31+
`main`.
2832
- Because Compute service names need a filesystem- and URL-safe shape, the raw
2933
branch name MUST be normalized to a lowercase slug containing only
3034
alphanumeric segments separated by `-`.
@@ -45,8 +49,22 @@ publishes it into the dedicated Compute project named `studio-preview`.
4549
- If the service already exists, the helper MUST deploy a new version to that
4650
same service.
4751
- Deployments MUST use the published CLI entrypoint:
48-
- `bunx @prisma/compute-cli@latest deploy --skip-build --path deploy --entrypoint bundle/compute-entrypoint.js --http-port 8080`.
49-
- The Compute artifact MUST include `bundle/compute-entrypoint.js`, which defaults `STUDIO_DEMO_PORT` to `8080` before importing `bundle/server.bundle.js`. Preview deploys MUST NOT pass runtime environment variables through the Compute CLI while its deploy API rejects the CLI's `envVars` request key.
52+
`bunx @prisma/compute-cli@latest deploy --skip-build --path deploy --entrypoint bundle/compute-entrypoint.js --http-port 8080`.
53+
- The Compute artifact MUST include `bundle/compute-entrypoint.js`, which
54+
defaults `STUDIO_DEMO_PORT` to `8080` before importing
55+
`bundle/server.bundle.js`.
56+
- Preview deploys MUST pass runtime environment through a temporary Compute CLI
57+
env file rather than embedding secrets into the artifact.
58+
- Preview runtime env MUST include `STUDIO_DEMO_PORT=8080`,
59+
`STUDIO_DEMO_AI_ENABLED=true`, and `ANTHROPIC_API_KEY` from the GitHub
60+
Actions secret `STUDIO_PREVIEW_ANTHROPIC_API_KEY`.
61+
62+
## Main Preview
63+
64+
- The stable preview for the latest `main` MUST use `main` as the service key so
65+
the Compute service URL remains stable across pushes.
66+
- Successful `main` preview deploys SHOULD write the live service URL to the
67+
GitHub Actions job summary.
5068

5169
## PR Feedback
5270

Architecture/demo-compute-bundling.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ It is responsible for:
2424
4. copying Prisma Dev runtime assets into `bundle/` with their stable filenames
2525
5. bundling Prisma Streams local's worker into `touch/processor_worker.js`
2626
6. copying the worker's vendored `hash_vendor/` files into `touch/`
27-
7. writing a self-contained output directory whose entrypoint is `bundle/server.bundle.js`
27+
7. writing a self-contained output directory whose Compute entrypoint is
28+
`bundle/compute-entrypoint.js`
29+
8. writing `bundle/compute-entrypoint.js` so it defaults `STUDIO_DEMO_PORT` to
30+
`8080` before importing `bundle/server.bundle.js`
2831

2932
## Prisma Dev Runtime Assets
3033

31-
`@prisma/dev@0.24.6` exposes a Bun runtime-asset manifest for PGlite and also
34+
`@prisma/dev@0.24.13` exposes a Bun runtime-asset manifest for PGlite and also
3235
exports `copyPrismaDevRuntimeAssets()`.
3336

3437
That means when `build-compute.ts` bundles `demo/ppg-dev/server.ts` with Bun:
@@ -49,7 +52,8 @@ hashed Bun-emitted assets and the canonical names.
4952

5053
For the Compute artifact that means:
5154

52-
- the server entrypoint stays at `deploy/bundle/server.bundle.js`
55+
- the Compute entrypoint stays at `deploy/bundle/compute-entrypoint.js`
56+
- the bundled server stays at `deploy/bundle/server.bundle.js`
5357
- stable PGlite assets live in `deploy/bundle/`
5458
- the Streams worker must live at `deploy/touch/processor_worker.js`
5559
- the worker's vendored hashing modules must live at `deploy/touch/hash_vendor/`

FEATURES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ Compute project without hand-creating services for each branch.
3333
The preview workflow derives a stable Compute-safe service name from the branch,
3434
reuses that service across later pushes, posts the live URL back to the PR, and
3535
destroys the preview service when the branch is deleted.
36+
The same workflow deploys the latest `main` branch to a stable `main` Compute
37+
service URL, and preview deployments carry the configured Anthropic key so the
38+
demo's AI filtering, SQL generation, visualization, and Query Insights
39+
recommendation features are available in previews.
3640

3741
## Introspection Recovery and Retry
3842

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -676,12 +676,17 @@ This repo also maintains branch-scoped Compute previews for pull requests.
676676
duplicates.
677677
- The workflow updates one sticky PR comment with the live preview URL after a
678678
successful deploy.
679+
- Pushes to `main` deploy the latest default-branch build to the stable `main`
680+
Compute service and write that service URL to the GitHub Actions job summary.
679681
- When a Git branch is deleted, the same workflow destroys the matching preview
680682
service.
681683

682-
The workflow expects the GitHub Actions secret
683-
`STUDIO_PREVIEW_COMPUTE_TOKEN`, which should contain a Compute API token for the
684-
`studio-preview` project.
684+
The workflow expects these GitHub Actions secrets:
685+
686+
- `STUDIO_PREVIEW_COMPUTE_TOKEN`, a Compute API token for the `studio-preview`
687+
project
688+
- `STUDIO_PREVIEW_ANTHROPIC_API_KEY`, the Anthropic key used to enable Studio AI
689+
features in Compute previews
685690

686691
For branch-deletion cleanup to happen automatically, the workflow must be
687692
present on the default branch. In practice that means merging the preview

scripts/compute-preview/compute-preview-deploy.mjs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@
22

33
import { execFile } from "node:child_process";
44
import { appendFileSync } from "node:fs";
5+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
6+
import { tmpdir } from "node:os";
7+
import { join } from "node:path";
58
import { promisify } from "node:util";
69

710
import {
811
PREVIEW_PROJECT_NAME,
12+
buildComputeDeployArgs,
13+
buildPreviewRuntimeEnv,
914
findNamedProject,
1015
findNamedService,
16+
formatDotenvFile,
1117
sanitizeComputeServiceName,
1218
} from "./compute-preview-utils.mjs";
1319

1420
const execFileAsync = promisify(execFile);
1521

1622
async function main() {
1723
const branchName = getRequiredEnv("PREVIEW_BRANCH_NAME");
24+
const anthropicApiKey = getRequiredEnv("ANTHROPIC_API_KEY");
1825
const projectName = process.env.PREVIEW_PROJECT_NAME ?? PREVIEW_PROJECT_NAME;
1926
const deployPath = process.env.PREVIEW_DEPLOY_PATH ?? "deploy";
2027
const entrypoint =
@@ -28,18 +35,35 @@ async function main() {
2835
region: project.defaultRegion ?? "eu-west-3",
2936
serviceName,
3037
});
31-
const deployResult = await runComputeJson([
32-
"deploy",
33-
"--skip-build",
34-
"--path",
35-
deployPath,
36-
"--entrypoint",
37-
entrypoint,
38-
"--http-port",
39-
httpPort,
40-
"--service",
41-
service.id,
42-
]);
38+
const runtimeEnvDir = await mkdtemp(
39+
join(tmpdir(), "studio-compute-preview-env-"),
40+
);
41+
const runtimeEnvPath = join(runtimeEnvDir, ".env");
42+
let deployResult;
43+
44+
try {
45+
await writeFile(
46+
runtimeEnvPath,
47+
formatDotenvFile(
48+
buildPreviewRuntimeEnv({
49+
anthropicApiKey,
50+
httpPort,
51+
}),
52+
),
53+
{ mode: 0o600 },
54+
);
55+
deployResult = await runComputeJson(
56+
buildComputeDeployArgs({
57+
deployPath,
58+
entrypoint,
59+
envFilePath: runtimeEnvPath,
60+
httpPort,
61+
serviceId: service.id,
62+
}),
63+
);
64+
} finally {
65+
await rm(runtimeEnvDir, { force: true, recursive: true });
66+
}
4367

4468
const result = {
4569
branchName,

scripts/compute-preview/compute-preview-utils.mjs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,50 @@ export function findNamedService(services, serviceName) {
3939
return services.find((service) => service.name === serviceName);
4040
}
4141

42+
export function buildPreviewRuntimeEnv(args) {
43+
const { anthropicApiKey, httpPort } = args;
44+
45+
return {
46+
ANTHROPIC_API_KEY: anthropicApiKey,
47+
STUDIO_DEMO_AI_ENABLED: "true",
48+
STUDIO_DEMO_PORT: httpPort,
49+
};
50+
}
51+
52+
export function formatDotenvFile(env) {
53+
return `${Object.entries(env)
54+
.map(([key, value]) => `${key}=${JSON.stringify(value)}`)
55+
.join("\n")}\n`;
56+
}
57+
58+
export function buildComputeDeployArgs(args) {
59+
const {
60+
deployPath,
61+
entrypoint,
62+
envFilePath,
63+
httpPort,
64+
serviceId,
65+
} = args;
66+
const deployArgs = [
67+
"deploy",
68+
"--skip-build",
69+
"--path",
70+
deployPath,
71+
"--entrypoint",
72+
entrypoint,
73+
"--http-port",
74+
httpPort,
75+
];
76+
77+
if (envFilePath) {
78+
deployArgs.push("--env", envFilePath);
79+
}
80+
81+
deployArgs.push("--service", serviceId);
82+
83+
return deployArgs;
84+
}
85+
4286
export function buildPreviewCommentBody(args) {
4387
const {
4488
branchName,

0 commit comments

Comments
 (0)