Skip to content

Commit 7a328f4

Browse files
authored
feat(astro): Add support for Astro on CF Workers (#19265)
closes #19215 closes [JS-1656](https://linear.app/getsentry/issue/JS-1656/support-astro-on-cloudflare-workers) This allows to deploy Astro on CF Workers and instrument it with Sentry The main issue was that within CF Workers everything needs to be wrapped with `withSentry` from the `@sentry/cloudflare` SDK. With this PR the config cannot be changed via code and it is for now only possible to update the config on Cloudflare via [Environment Variables](https://developers.cloudflare.com/workers/configuration/environment-variables/). I couldn't come up with a nice solution to have the config and bundle it with the entrypoint of `@astro/cloudflare`. ### Future ideas However, in `@astro/cloudflare@13` the entry point is not [exporting a function](https://github.com/withastro/astro/blob/%40astrojs/cloudflare%4012.6.12/packages/integrations/cloudflare/src/entrypoints/server.ts) anymore, but a real module: https://github.com/withastro/astro/blob/%40astrojs/cloudflare%4013.0.0-beta.6/packages/integrations/cloudflare/src/entrypoints/server.ts With this we could possibly change the entrypoint entirely to a Sentry entrypoint where `withSentry` is available as code. ### Merge checks - [x] Create docs issue to update Astro on Cloudflare docs
1 parent b1d25bb commit 7a328f4

23 files changed

Lines changed: 652 additions & 5 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# build output
2+
dist/
3+
4+
# generated types
5+
.astro/
6+
7+
# dependencies
8+
node_modules/
9+
10+
# logs
11+
npm-debug.log*
12+
yarn-debug.log*
13+
yarn-error.log*
14+
pnpm-debug.log*
15+
16+
# environment variables
17+
.env
18+
.env.production
19+
20+
# macOS-specific files
21+
.DS_Store
22+
23+
# jetbrains setting folder
24+
.idea/
25+
26+
test-results
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@sentry:registry=http://127.0.0.1:4873
2+
@sentry-internal:registry=http://127.0.0.1:4873
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import cloudflare from '@astrojs/cloudflare';
2+
import sentry from '@sentry/astro';
3+
// @ts-check
4+
import { defineConfig } from 'astro/config';
5+
6+
// https://astro.build/config
7+
export default defineConfig({
8+
integrations: [
9+
sentry({
10+
debug: true,
11+
sourceMapsUploadOptions: {
12+
enabled: false,
13+
},
14+
}),
15+
],
16+
output: 'server',
17+
adapter: cloudflare(),
18+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "astro-5-cf-workers",
3+
"type": "module",
4+
"version": "0.0.1",
5+
"scripts": {
6+
"dev": "astro dev",
7+
"build": "astro build",
8+
"preview": "wrangler dev --port 3030",
9+
"test:build": "pnpm install && pnpm build",
10+
"test:assert": "TEST_ENV=production playwright test"
11+
},
12+
"dependencies": {
13+
"@astrojs/cloudflare": "^12.6.12",
14+
"@playwright/test": "~1.56.0",
15+
"@sentry-internal/test-utils": "link:../../../test-utils",
16+
"@sentry/astro": "latest || *",
17+
"@sentry/cloudflare": "latest || *",
18+
"astro": "^5.17.1"
19+
},
20+
"devDependencies": {
21+
"wrangler": "^4.63.0"
22+
},
23+
"pnpm": {
24+
"overrides": {
25+
"esbuild": "0.24.0"
26+
}
27+
},
28+
"volta": {
29+
"extends": "../../package.json"
30+
}
31+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { getPlaywrightConfig } from '@sentry-internal/test-utils';
2+
3+
const testEnv = process.env.TEST_ENV;
4+
5+
if (!testEnv) {
6+
throw new Error('No test env defined');
7+
}
8+
9+
const config = getPlaywrightConfig({
10+
startCommand: 'pnpm preview',
11+
port: 3030,
12+
});
13+
14+
export default config;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as Sentry from '@sentry/astro';
2+
3+
Sentry.init({
4+
dsn: import.meta.env.PUBLIC_E2E_TEST_DSN,
5+
environment: 'qa',
6+
tracesSampleRate: 1.0,
7+
tunnel: 'http://localhost:3031/', // proxy server
8+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as Sentry from '@sentry/astro';
2+
3+
Sentry.init({
4+
dsn: import.meta.env.PUBLIC_E2E_TEST_DSN,
5+
environment: 'qa',
6+
tracesSampleRate: 1.0,
7+
tunnel: 'http://localhost:3031/', // proxy server
8+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { defineAction, ActionError } from 'astro:actions';
2+
import { z } from 'astro:schema';
3+
4+
export const server = {
5+
testAction: defineAction({
6+
input: z.object({
7+
name: z.string(),
8+
shouldError: z.boolean().optional(),
9+
}),
10+
handler: async input => {
11+
if (input.shouldError) {
12+
throw new ActionError({
13+
code: 'BAD_REQUEST',
14+
message: 'Test Action Error',
15+
});
16+
}
17+
18+
return {
19+
status: 'success',
20+
name: input.name,
21+
};
22+
},
23+
}),
24+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width" />
6+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7+
<meta name="generator" content={Astro.generator} />
8+
<title>Astro Basics</title>
9+
</head>
10+
<body>
11+
<slot />
12+
</body>
13+
</html>
14+
15+
<style>
16+
html,
17+
body {
18+
margin: 0;
19+
width: 100%;
20+
height: 100%;
21+
}
22+
</style>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
import Layout from '../../layouts/Layout.astro';
3+
4+
export const prerender = false;
5+
---
6+
7+
<Layout title="Action Test">
8+
<h1>Action Test Page</h1>
9+
<form id="test-form">
10+
<input type="text" name="name" value="test" />
11+
<button type="submit">Submit Action</button>
12+
</form>
13+
<div id="result"></div>
14+
15+
<script>
16+
import { actions } from 'astro:actions';
17+
18+
const form = document.getElementById('test-form') as HTMLFormElement;
19+
const result = document.getElementById('result') as HTMLDivElement;
20+
21+
form.addEventListener('submit', async e => {
22+
e.preventDefault();
23+
try {
24+
const response = await actions.testAction({ name: 'test', shouldError: false });
25+
result.textContent = JSON.stringify(response);
26+
} catch (err) {
27+
result.textContent = `Error: ${err}`;
28+
}
29+
});
30+
</script>
31+
</Layout>

0 commit comments

Comments
 (0)