mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-06-26 18:26:38 +00:00
playwright
This commit is contained in:
parent
3cef889564
commit
3178504069
9
.github/workflows/ci.yaml
vendored
9
.github/workflows/ci.yaml
vendored
@ -69,11 +69,4 @@ jobs:
|
||||
- name: Setup and Build
|
||||
uses: ./.github/actions/setup-and-build
|
||||
with:
|
||||
sentry-auth-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
uses: cloudflare/wrangler-action@v3
|
||||
with:
|
||||
command: pages deploy
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
sentry-auth-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
23
.github/workflows/playwright.yml
vendored
23
.github/workflows/playwright.yml
vendored
@ -1,11 +1,12 @@
|
||||
name: Playwright Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
deployment_status:
|
||||
jobs:
|
||||
test:
|
||||
name: 'Playwright Tests'
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'pull_request' || (github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success') }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -26,19 +27,15 @@ jobs:
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install chromium
|
||||
|
||||
- name: Run Playwright tests with supabase
|
||||
run: pnpm test:e2e:supabase
|
||||
- name: Get Vercel Preview URL
|
||||
if: ${{ github.event_name == 'deployment_status' }}
|
||||
run: |
|
||||
echo "PLAYWRIGHT_TEST_BASE_URL=${{ github.event.deployment_status.target_url }}" >> $GITHUB_ENV
|
||||
echo "Testing against Vercel Preview URL: ${{ github.event.deployment_status.target_url }}"
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
|
||||
- name: Run Playwright tests without supabase
|
||||
run: pnpm test:e2e:legacy
|
||||
- name: Run Playwright tests
|
||||
if: ${{ github.event_name == 'deployment_status' }}
|
||||
run: npx playwright test
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
|
@ -109,75 +109,6 @@ Run the test suite with:
|
||||
pnpm test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment
|
||||
|
||||
### Deploy to Cloudflare Pages
|
||||
```bash
|
||||
pnpm run deploy
|
||||
```
|
||||
Ensure you have required permissions and that Wrangler is configured.
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker Deployment
|
||||
|
||||
This section outlines the methods for deploying the application using Docker. The processes for **Development** and **Production** are provided separately for clarity.
|
||||
|
||||
---
|
||||
|
||||
### 🧑💻 Development Environment
|
||||
|
||||
#### Build Options
|
||||
|
||||
**Option 1: Helper Scripts**
|
||||
```bash
|
||||
# Development build
|
||||
npm run dockerbuild
|
||||
```
|
||||
|
||||
**Option 2: Direct Docker Build Command**
|
||||
```bash
|
||||
docker build . --target bolt-ai-development
|
||||
```
|
||||
|
||||
**Option 3: Docker Compose Profile**
|
||||
```bash
|
||||
docker-compose --profile development up
|
||||
```
|
||||
|
||||
#### Running the Development Container
|
||||
```bash
|
||||
docker run -p 5173:5173 --env-file .env.local bolt-ai:development
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🏭 Production Environment
|
||||
|
||||
#### Build Options
|
||||
|
||||
**Option 1: Helper Scripts**
|
||||
```bash
|
||||
# Production build
|
||||
npm run dockerbuild:prod
|
||||
```
|
||||
|
||||
**Option 2: Direct Docker Build Command**
|
||||
```bash
|
||||
docker build . --target bolt-ai-production
|
||||
```
|
||||
|
||||
**Option 3: Docker Compose Profile**
|
||||
```bash
|
||||
docker-compose --profile production up
|
||||
```
|
||||
|
||||
#### Running the Production Container
|
||||
```bash
|
||||
docker run -p 5173:5173 --env-file .env.local bolt-ai:production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
@ -1,31 +1,38 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import { createRequestHandler } from '~/lib/remix-types';
|
||||
// We'll import the server build at runtime, not during compilation
|
||||
// Build path will be available after the build is complete
|
||||
|
||||
/*
|
||||
* We'll import the server build at runtime, not during compilation
|
||||
* Build path will be available after the build is complete
|
||||
*/
|
||||
|
||||
// Add Sentry's request handler to wrap the Remix request handler
|
||||
const handleRequest = async (request: Request) => {
|
||||
try {
|
||||
// Dynamically import the server build at runtime
|
||||
// In a real Vercel deployment, the server build will be available
|
||||
// This is just a placeholder for type checking
|
||||
const build = { /* production build will be available at runtime */ };
|
||||
|
||||
/*
|
||||
* Dynamically import the server build at runtime
|
||||
* In a real Vercel deployment, the server build will be available
|
||||
* This is just a placeholder for type checking
|
||||
*/
|
||||
const build = {
|
||||
/* production build will be available at runtime */
|
||||
};
|
||||
|
||||
// Create the request handler
|
||||
const handler = createRequestHandler({
|
||||
build: build as any,
|
||||
mode: process.env.NODE_ENV,
|
||||
getLoadContext: () => ({
|
||||
env: process.env
|
||||
})
|
||||
env: process.env,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
// Handle the request
|
||||
return handler(request);
|
||||
} catch (error) {
|
||||
// Log the error with Sentry
|
||||
Sentry.captureException(error);
|
||||
|
||||
|
||||
// Return a basic error response
|
||||
return new Response('Server Error', { status: 500 });
|
||||
}
|
||||
@ -39,4 +46,4 @@ export const DELETE = handleRequest;
|
||||
export const HEAD = handleRequest;
|
||||
export const OPTIONS = handleRequest;
|
||||
|
||||
export const runtime = 'edge';
|
||||
export const runtime = 'edge';
|
||||
|
@ -4,7 +4,7 @@ import { sentryHandleError } from '~/lib/sentry';
|
||||
* Using our conditional Sentry implementation instead of direct import
|
||||
* This avoids loading Sentry in development environments
|
||||
*/
|
||||
import type { AppLoadContext, EntryContext } from '~/lib/remix-types';
|
||||
import type { AppLoadContext } from '~/lib/remix-types';
|
||||
import { RemixServer } from '@remix-run/react';
|
||||
import { isbot } from 'isbot';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
@ -26,9 +26,21 @@ export default async function handleRequest(
|
||||
const isBot = isbot(userAgent || '');
|
||||
|
||||
// Create the HTML string
|
||||
const markup = renderToString(
|
||||
<RemixServer context={remixContext} url={request.url} />
|
||||
);
|
||||
const markup = renderToString(<RemixServer context={remixContext} url={request.url} />);
|
||||
|
||||
// If this is a bot request, we can wait for all data to be ready
|
||||
if (isBot) {
|
||||
/*
|
||||
* In Cloudflare, we had:
|
||||
* await readable.allReady;
|
||||
*
|
||||
* For Vercel, we could do additional processing for bots
|
||||
* such as waiting for all data fetching to complete.
|
||||
* Future enhancement: add mechanism to ensure all data is loaded
|
||||
* before rendering for bots (important for SEO)
|
||||
*/
|
||||
console.log(`Bot detected: ${userAgent}`);
|
||||
}
|
||||
|
||||
// @ts-ignore - Fix for incompatible EntryContext types between different remix versions
|
||||
const head = renderHeadToString({ request, remixContext, Head });
|
||||
|
@ -200,7 +200,7 @@ async function loadAsyncHooksContextManager() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function createTracer(appContext: AppLoadContext) {
|
||||
export async function createTracer(_appContext: AppLoadContext) {
|
||||
const honeycombApiKey = process.env.HONEYCOMB_API_KEY;
|
||||
const honeycombDataset = process.env.HONEYCOMB_DATASET;
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
// This file provides compatibility types to smoothly migrate from Cloudflare to Vercel
|
||||
|
||||
import type {
|
||||
import type {
|
||||
ActionFunctionArgs as VercelActionFunctionArgs,
|
||||
LoaderFunctionArgs as VercelLoaderFunctionArgs,
|
||||
AppLoadContext as VercelAppLoadContext,
|
||||
EntryContext as VercelEntryContext
|
||||
EntryContext as VercelEntryContext,
|
||||
} from '@vercel/remix';
|
||||
|
||||
// Re-export necessary types with compatible names
|
||||
@ -14,7 +14,7 @@ export type LoaderFunction = (args: LoaderFunctionArgs) => Promise<Response> | R
|
||||
export type ActionFunction = (args: ActionFunctionArgs) => Promise<Response> | Response;
|
||||
export type AppLoadContext = VercelAppLoadContext;
|
||||
export type EntryContext = VercelEntryContext;
|
||||
export type MetaFunction = () => Array<{
|
||||
export type MetaFunction = () => Array<{
|
||||
title?: string;
|
||||
name?: string;
|
||||
content?: string;
|
||||
@ -22,7 +22,7 @@ export type MetaFunction = () => Array<{
|
||||
}>;
|
||||
export type LinksFunction = () => Array<{ rel: string; href: string }>;
|
||||
|
||||
// Re-export json function
|
||||
// Re-export json function
|
||||
export function json<T>(data: T, init?: ResponseInit): Response {
|
||||
return new Response(JSON.stringify(data), {
|
||||
...init,
|
||||
@ -34,14 +34,16 @@ export function json<T>(data: T, init?: ResponseInit): Response {
|
||||
}
|
||||
|
||||
// Export a createRequestHandler function
|
||||
export function createRequestHandler(options: {
|
||||
export function createRequestHandler(_options: {
|
||||
build: any;
|
||||
mode?: string;
|
||||
getLoadContext?: (req: Request) => AppLoadContext;
|
||||
}) {
|
||||
return async (request: Request) => {
|
||||
// This is a simplified handler for type checking
|
||||
// The real implementation will use Vercel's handler
|
||||
return new Response("Not implemented", { status: 501 });
|
||||
return async (_request: Request) => {
|
||||
/*
|
||||
* This is a simplified handler for type checking
|
||||
* The real implementation will use Vercel's handler
|
||||
*/
|
||||
return new Response('Not implemented', { status: 501 });
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { LoaderFunction } from '~/lib/remix-types';
|
||||
import { providerBaseUrlEnvKeys } from '~/utils/constants';
|
||||
|
||||
export const loader: LoaderFunction = async ({ context, request }) => {
|
||||
export const loader: LoaderFunction = async ({ context: _, request }) => {
|
||||
const url = new URL(request.url);
|
||||
const provider = url.searchParams.get('provider');
|
||||
|
||||
@ -10,6 +10,7 @@ export const loader: LoaderFunction = async ({ context, request }) => {
|
||||
}
|
||||
|
||||
const envVarName = providerBaseUrlEnvKeys[provider].apiTokenKey;
|
||||
|
||||
// Use only process.env since context.env might be undefined
|
||||
const isSet = !!process.env[envVarName];
|
||||
|
||||
|
@ -29,7 +29,7 @@ export async function action(args: ActionFunctionArgs) {
|
||||
}
|
||||
|
||||
async function pingTelemetryAction({ request }: ActionFunctionArgs) {
|
||||
const { event, data } = await request.json() as {
|
||||
const { event, data } = (await request.json()) as {
|
||||
event: string;
|
||||
data: any;
|
||||
};
|
||||
|
@ -111,76 +111,6 @@ pnpm test
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment
|
||||
|
||||
### Deploy to Cloudflare Pages
|
||||
```bash
|
||||
pnpm run deploy
|
||||
```
|
||||
Ensure you have required permissions and that Wrangler is configured.
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker Deployment
|
||||
|
||||
This section outlines the methods for deploying the application using Docker. The processes for **Development** and **Production** are provided separately for clarity.
|
||||
|
||||
---
|
||||
|
||||
### 🧑💻 Development Environment
|
||||
|
||||
#### Build Options
|
||||
|
||||
**Option 1: Helper Scripts**
|
||||
```bash
|
||||
# Development build
|
||||
npm run dockerbuild
|
||||
```
|
||||
|
||||
**Option 2: Direct Docker Build Command**
|
||||
```bash
|
||||
docker build . --target bolt-ai-development
|
||||
```
|
||||
|
||||
**Option 3: Docker Compose Profile**
|
||||
```bash
|
||||
docker-compose --profile development up
|
||||
```
|
||||
|
||||
#### Running the Development Container
|
||||
```bash
|
||||
docker run -p 5173:5173 --env-file .env.local bolt-ai:development
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🏭 Production Environment
|
||||
|
||||
#### Build Options
|
||||
|
||||
**Option 1: Helper Scripts**
|
||||
```bash
|
||||
# Production build
|
||||
npm run dockerbuild:prod
|
||||
```
|
||||
|
||||
**Option 2: Direct Docker Build Command**
|
||||
```bash
|
||||
docker build . --target bolt-ai-production
|
||||
```
|
||||
|
||||
**Option 3: Docker Compose Profile**
|
||||
```bash
|
||||
docker-compose --profile production up
|
||||
```
|
||||
|
||||
#### Running the Production Container
|
||||
```bash
|
||||
docker run -p 5173:5173 --env-file .env.local bolt-ai:production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Coolify Deployment
|
||||
|
||||
For an easy deployment process, use [Coolify](https://github.com/coollabsio/coolify):
|
||||
|
@ -219,7 +219,7 @@ When you add a new model to the MODEL_LIST array, it will immediately be availab
|
||||
- `pnpm test`: Runs the test suite using Vitest.
|
||||
- `pnpm run typecheck`: Runs TypeScript type checking.
|
||||
- `pnpm run typegen`: Generates TypeScript types using Wrangler.
|
||||
- `pnpm run deploy`: Builds the project and deploys it to Cloudflare Pages.
|
||||
- `pnpm run deploy`: Builds the project and deploys it to Vercel.
|
||||
|
||||
---
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
const port = 5175;
|
||||
const usePreviewUrl = !!process.env.PLAYWRIGHT_TEST_BASE_URL;
|
||||
const baseURL = usePreviewUrl ? process.env.PLAYWRIGHT_TEST_BASE_URL : `http://localhost:${port}`;
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e',
|
||||
@ -11,7 +13,7 @@ export default defineConfig({
|
||||
reporter: 'html',
|
||||
timeout: 60000, // Increase global timeout to 60 seconds
|
||||
use: {
|
||||
baseURL: `http://localhost:${port}`,
|
||||
baseURL,
|
||||
trace: 'on',
|
||||
},
|
||||
projects: [
|
||||
@ -20,11 +22,13 @@ export default defineConfig({
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
],
|
||||
webServer: {
|
||||
command: `pnpm dev --port ${port}`,
|
||||
port,
|
||||
timeout: 120000, // 2 minutes
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
},
|
||||
webServer: usePreviewUrl
|
||||
? undefined
|
||||
: {
|
||||
command: `pnpm dev --port ${port}`,
|
||||
port,
|
||||
timeout: 120000, // 2 minutes
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
},
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user