Skip to content

Commit 80e573f

Browse files
authored
feat(frontend): PR preview banner (#11412)
## Changes 🏗️ <img width="900" height="757" alt="Screenshot 2025-11-19 at 12 18 38" src="https://github.com/user-attachments/assets/e2c2a4cf-a05e-431e-853d-fb0a68729e54" /> When the dev environment is used for a PR preview, show a banner at the top of the page to indicate this. ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Create a PR preview against Dev - [x] Check it shows the banner once this is merged - [x] Or try locally with the env var set ### For configuration changes: `NEXT_PUBLIC_PREVIEW_STEALING_DEV` is set programmatically via our Infra CI.
1 parent 06d20e7 commit 80e573f

File tree

5 files changed

+67
-22
lines changed

5 files changed

+67
-22
lines changed
Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
1-
NEXT_PUBLIC_SUPABASE_URL=http://localhost:8000
2-
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
1+
# Supabase
2+
NEXT_PUBLIC_SUPABASE_URL=http://localhost:8000
3+
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
34

4-
NEXT_PUBLIC_AGPT_SERVER_URL=http://localhost:8006/api
5-
NEXT_PUBLIC_AGPT_WS_SERVER_URL=ws://localhost:8001/ws
6-
NEXT_PUBLIC_FRONTEND_BASE_URL=http://localhost:3000
5+
# Back-end services
6+
NEXT_PUBLIC_AGPT_SERVER_URL=http://localhost:8006/api
7+
NEXT_PUBLIC_AGPT_WS_SERVER_URL=ws://localhost:8001/ws
8+
NEXT_PUBLIC_FRONTEND_BASE_URL=http://localhost:3000
79

8-
NEXT_PUBLIC_APP_ENV=local
9-
NEXT_PUBLIC_BEHAVE_AS=LOCAL
10+
# Env config
11+
NEXT_PUBLIC_APP_ENV=local
12+
NEXT_PUBLIC_BEHAVE_AS=LOCAL
1013

11-
NEXT_PUBLIC_LAUNCHDARKLY_ENABLED=false
12-
NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID=687ab1372f497809b131e06e
14+
# Feature flags
15+
NEXT_PUBLIC_LAUNCHDARKLY_ENABLED=false
16+
NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID=687ab1372f497809b131e06e
1317

14-
NEXT_PUBLIC_REACT_QUERY_DEVTOOL=true
15-
16-
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-FH2XK2W4GN
18+
# Debugging
19+
NEXT_PUBLIC_REACT_QUERY_DEVTOOL=true
20+
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-FH2XK2W4GN
1721

1822
# Google Drive Picker
1923
NEXT_PUBLIC_GOOGLE_CLIENT_ID=
2024
NEXT_PUBLIC_GOOGLE_API_KEY=
2125
NEXT_PUBLIC_GOOGLE_APP_ID=
22-
26+
27+
# Cloudflare CAPTCHA
28+
NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=
29+
NEXT_PUBLIC_TURNSTILE=disabled
30+
31+
# PR previews
32+
NEXT_PUBLIC_PREVIEW_STEALING_DEV=

autogpt_platform/frontend/playwright.config.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import dotenv from "dotenv";
88
import path from "path";
99
dotenv.config({ path: path.resolve(__dirname, ".env") });
1010
dotenv.config({ path: path.resolve(__dirname, "../backend/.env") });
11-
/**
12-
* See https://playwright.dev/docs/test-configuration.
13-
*/
11+
1412
export default defineConfig({
1513
testDir: "./src/tests",
1614
/* Global setup file that runs before all tests */
@@ -62,7 +60,7 @@ export default defineConfig({
6260
/* Maximum time one test can run for */
6361
timeout: 25000,
6462

65-
/* Configure web server to start automatically */
63+
/* Configure web server to start automatically (local dev only) */
6664
webServer: {
6765
command: "pnpm start",
6866
url: "http://localhost:3000",

autogpt_platform/frontend/src/app/layout.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import "./globals.css";
66

77
import { Providers } from "@/app/providers";
88
import { CookieConsentBanner } from "@/components/molecules/CookieConsentBanner/CookieConsentBanner";
9+
import { PreviewBanner } from "@/components/molecules/PreviewBanner/PreviewBanner";
910
import TallyPopupSimple from "@/components/molecules/TallyPoup/TallyPopup";
1011
import { Toaster } from "@/components/molecules/Toast/toaster";
11-
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
12-
import { headers } from "next/headers";
1312
import { SetupAnalytics } from "@/services/analytics";
1413
import { VercelAnalyticsWrapper } from "@/services/analytics/VercelAnalyticsWrapper";
14+
import { environment } from "@/services/environment";
15+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
16+
import { headers } from "next/headers";
1517

1618
export const metadata: Metadata = {
1719
title: "AutoGPT Platform",
@@ -25,6 +27,7 @@ export default async function RootLayout({
2527
}>) {
2628
const headersList = await headers();
2729
const host = headersList.get("host") || "";
30+
const previewStealingDev = environment.getPreviewStealingDev();
2831

2932
return (
3033
<html
@@ -49,6 +52,9 @@ export default async function RootLayout({
4952
disableTransitionOnChange
5053
>
5154
<div className="flex min-h-screen flex-col items-stretch justify-items-stretch">
55+
{previewStealingDev && environment.isDev() ? (
56+
<PreviewBanner branchName={previewStealingDev} />
57+
) : null}
5258
{children}
5359
<TallyPopupSimple />
5460
<VercelAnalyticsWrapper />
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
type Props = {
2+
branchName: string;
3+
};
4+
5+
export function PreviewBanner({ branchName }: Props) {
6+
if (!branchName) {
7+
return null;
8+
}
9+
10+
return (
11+
<div className="sticky top-0 z-50 w-full bg-green-500 px-4 py-2 text-center text-sm font-medium text-white">
12+
This is a Preview build for the branch:{" "}
13+
<span className="font-mono font-semibold">{branchName}</span>
14+
</div>
15+
);
16+
}

autogpt_platform/frontend/src/services/environment/index.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,26 @@ function getEnvironmentStr() {
6060
return `app:${getAppEnv().toLowerCase()}-behave:${getBehaveAs().toLowerCase()}`;
6161
}
6262

63-
function isProd() {
63+
function getPreviewStealingDev() {
64+
return process.env.NEXT_PUBLIC_PREVIEW_STEALING_DEV || "";
65+
}
66+
67+
function isProductionBuild() {
6468
return process.env.NODE_ENV === "production";
6569
}
6670

67-
function isDev() {
71+
function isDevelopmentBuild() {
6872
return process.env.NODE_ENV === "development";
6973
}
7074

75+
function isDev() {
76+
return isCloud() && getAppEnv() === AppEnv.DEV;
77+
}
78+
79+
function isProd() {
80+
return isCloud() && getAppEnv() === AppEnv.PROD;
81+
}
82+
7183
function isCloud() {
7284
return getBehaveAs() === BehaveAs.CLOUD;
7385
}
@@ -103,11 +115,14 @@ export const environment = {
103115
getAGPTWsServerUrl,
104116
getSupabaseUrl,
105117
getSupabaseAnonKey,
118+
getPreviewStealingDev,
106119
// Assertions
107120
isServerSide,
108121
isClientSide,
109-
isProd,
122+
isProductionBuild,
123+
isDevelopmentBuild,
110124
isDev,
125+
isProd,
111126
isCloud,
112127
isLocal,
113128
isVercelPreview,

0 commit comments

Comments
 (0)