Skip to content

Commit 83abc13

Browse files
committed
pr previews, vibed <Co-Authored-By: Claude Mythos <noreply@anthropic.com>
1 parent e4e6a81 commit 83abc13

11 files changed

Lines changed: 108 additions & 2 deletions

File tree

.dockerignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules
2+
dist
3+
.astro
4+
.git
5+
.github
6+
.vscode
7+
.claude
8+
Dockerfile

Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM node:26-slim AS build
2+
RUN npm install --global bun
3+
WORKDIR /app
4+
COPY package.json bun.lock ./
5+
RUN bun install --frozen-lockfile
6+
COPY . .
7+
ARG PR_PREVIEW=""
8+
ENV PR_PREVIEW=$PR_PREVIEW
9+
RUN bun run build
10+
11+
FROM nginx:1.29-alpine
12+
COPY infra/nginx.conf /etc/nginx/nginx.conf
13+
COPY --from=build /app/dist /usr/share/nginx/html
14+
USER nobody
15+
CMD ["nginx", "-g", "daemon off;"]

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ dev: ## Start development server
3232
preview: ## Build and preview production locally
3333
bun run preview
3434

35+
.PHONY: pr-preview
36+
pr-preview: ## Build and serve the site as a PR preview locally
37+
PR_PREVIEW=local bun run build
38+
bun run preview
39+
3540
## Build
3641

3742
.PHONY: build

Procfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
web: nginx -g 'daemon off;'
2+
release: echo 'deployed'

astro.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import remarkPythonRefs from "./src/plugins/remark-python-refs";
88

99
const isDev = process.env.NODE_ENV === "development" || process.argv.includes("dev");
1010

11+
1112
// Load redirects generated by the migration script
1213
let redirects: Record<string, string> = {};
1314
try {

infra/nginx.conf

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
pid /tmp/nginx.pid;
2+
error_log /dev/stderr warn;
3+
4+
events {
5+
worker_connections 1024;
6+
}
7+
8+
http {
9+
include /etc/nginx/mime.types;
10+
default_type application/octet-stream;
11+
access_log /dev/stdout;
12+
13+
client_body_temp_path /tmp/client_temp;
14+
proxy_temp_path /tmp/proxy_temp;
15+
fastcgi_temp_path /tmp/fastcgi_temp;
16+
uwsgi_temp_path /tmp/uwsgi_temp;
17+
scgi_temp_path /tmp/scgi_temp;
18+
19+
gzip on;
20+
gzip_types text/css application/javascript application/json image/svg+xml text/plain application/xml;
21+
22+
server {
23+
listen unix:/var/run/cabotage/cabotage.sock;
24+
root /usr/share/nginx/html;
25+
index index.html;
26+
27+
location = /_health/ {
28+
add_header Content-Type text/plain;
29+
return 200 'OK';
30+
}
31+
32+
error_page 404 /404.html;
33+
34+
location / {
35+
try_files $uri $uri/ =404;
36+
}
37+
}
38+
}

src/components/BaseHead.astro

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ interface Props {
66
}
77
88
import { withBase, stripDescriptionLinks } from "../lib/utils";
9+
const isPrPreview = Boolean(process.env.PR_PREVIEW);
910
const { title, description: rawDescription = "The official blog of the Python core development team.", image } = Astro.props;
1011
const description = stripDescriptionLinks(rawDescription);
1112
const baseUrl = import.meta.env.DEV ? Astro.url.origin : Astro.site;
@@ -38,6 +39,7 @@ const ogImage = image ? new URL(image, baseUrl) : new URL(withBase("/og-default.
3839
</script>
3940

4041
<title>{title}</title>
42+
{isPrPreview && <meta name="robots" content="noindex" />}
4143
<meta name="description" content={description} />
4244
<meta name="generator" content={Astro.generator} />
4345

@@ -56,5 +58,11 @@ const ogImage = image ? new URL(image, baseUrl) : new URL(withBase("/og-default.
5658
<meta name="twitter:image" content={ogImage} />
5759

5860
<!-- Plausible Analytics -->
59-
<script is:inline defer data-domain="blog.python.org" src="https://analytics.python.org/js/script.hash.outbound-links.js"></script>
60-
<script is:inline>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
61+
{
62+
!isPrPreview && (
63+
<>
64+
<script is:inline defer data-domain="blog.python.org" src="https://analytics.python.org/js/script.hash.outbound-links.js" />
65+
<script is:inline set:html={"window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }"} />
66+
</>
67+
)
68+
}

src/components/PreviewBanner.astro

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
const prNumber = process.env.PR_PREVIEW;
3+
const isPrLinked = Boolean(prNumber && /^\d+$/.test(prNumber));
4+
const prUrl = `https://github.com/python/python-insider-blog/pull/${prNumber}`;
5+
---
6+
7+
{
8+
prNumber && (
9+
<div class="border-b border-amber-300 bg-amber-100 px-6 py-2 text-center text-sm text-amber-900 dark:border-amber-700 dark:bg-amber-950 dark:text-amber-200">
10+
This is a preview of{" "}
11+
{isPrLinked ? (
12+
<a href={prUrl} class="font-semibold underline">
13+
pull request #{prNumber}
14+
</a>
15+
) : (
16+
<span class="font-semibold">a work-in-progress build</span>
17+
)}
18+
{" "}— not the live site. Visit{" "}
19+
<a href="https://blog.python.org" class="font-semibold underline">
20+
blog.python.org
21+
</a>
22+
{" "}for the published blog.
23+
</div>
24+
)
25+
}

src/layouts/BaseLayout.astro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
import BaseHead from "../components/BaseHead.astro";
33
import Header from "../components/Header.astro";
4+
import PreviewBanner from "../components/PreviewBanner.astro";
45
import Footer from "../components/Footer.astro";
56
import "../assets/styles/global.css";
67
@@ -20,6 +21,7 @@ const { title, description, image, fullWidth = false } = Astro.props;
2021
<BaseHead title={title} description={description} image={image} />
2122
</head>
2223
<body class="flex min-h-screen flex-col bg-[#fafaf9] text-[#1a1a2e] dark:bg-[#0f1117] dark:text-[#e4e4e7]">
24+
<PreviewBanner />
2325
<Header />
2426
<main class:list={[
2527
"flex-1",

src/pages/og/[...slug].png.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getFonts } from "../../lib/og-fonts";
88
export const prerender = true;
99

1010
export const getStaticPaths: GetStaticPaths = async () => {
11+
if (process.env.PR_PREVIEW) return [];
1112
const posts = await getCollection("posts");
1213
return posts
1314
.filter((p) => p.data.published)

0 commit comments

Comments
 (0)