fix: rebuild hook
This commit is contained in:
49
README.md
49
README.md
@@ -1,48 +1,7 @@
|
|||||||
# Astro Starter Kit: Basics
|
# blog
|
||||||
|
|
||||||
```sh
|
`POST /webhook/rebuild` spawns npm run build and rebuilds
|
||||||
npm create astro@latest -- --template basics
|
|
||||||
```
|
|
||||||
|
|
||||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
|
docker entrypoint is `node --watch server.js`, fastify serves `dist` as static content
|
||||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics)
|
|
||||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json)
|
|
||||||
|
|
||||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
[manifests/ayaume.yaml](/manifests/ayaume.yaml) has k8s manifest examples
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 🚀 Project Structure
|
|
||||||
|
|
||||||
Inside of your Astro project, you'll see the following folders and files:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/
|
|
||||||
├── public/
|
|
||||||
│ └── favicon.svg
|
|
||||||
├── src/
|
|
||||||
│ ├── layouts/
|
|
||||||
│ │ └── Layout.astro
|
|
||||||
│ └── pages/
|
|
||||||
│ └── index.astro
|
|
||||||
└── package.json
|
|
||||||
```
|
|
||||||
|
|
||||||
To learn more about the folder structure of an Astro project, refer to [our guide on project structure](https://docs.astro.build/en/basics/project-structure/).
|
|
||||||
|
|
||||||
## 🧞 Commands
|
|
||||||
|
|
||||||
All commands are run from the root of the project, from a terminal:
|
|
||||||
|
|
||||||
| Command | Action |
|
|
||||||
| :------------------------ | :----------------------------------------------- |
|
|
||||||
| `npm install` | Installs dependencies |
|
|
||||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
|
||||||
| `npm run build` | Build your production site to `./dist/` |
|
|
||||||
| `npm run preview` | Preview your build locally, before deploying |
|
|
||||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
|
||||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
|
||||||
|
|
||||||
## 👀 Want to learn more?
|
|
||||||
|
|
||||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
|
||||||
|
|||||||
80
manifests/ayaume.yaml
Normal file
80
manifests/ayaume.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ayaume
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: blog-secrets
|
||||||
|
namespace: ayaume
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
webhook-secret: c2VjcmV0
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: blog
|
||||||
|
namespace: ayaume
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: blog
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: blog
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: blog
|
||||||
|
image: registry.ayau.me/blog:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
env:
|
||||||
|
- name: WEBHOOK_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: blog-secrets
|
||||||
|
key: webhook-secret
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "200m"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: blog
|
||||||
|
namespace: ayaume
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 3000
|
||||||
|
selector:
|
||||||
|
app: blog
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: blog-ingress
|
||||||
|
namespace: ayaume
|
||||||
|
annotations:
|
||||||
|
spec.ingressClassName: traefik
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: w.ayau.me
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: blog
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -3,10 +3,10 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "ASTRO_TELEMETRY_DISABLED=1 astro dev",
|
||||||
"build": "astro build",
|
"build": "ASTRO_TELEMETRY_DISABLED=1 astro build",
|
||||||
"preview": "astro preview",
|
"preview": "ASTRO_TELEMETRY_DISABLED=1 astro preview",
|
||||||
"astro": "astro"
|
"astro": "ASTRO_TELEMETRY_DISABLED=1 astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/mdx": "^4.0.8",
|
"@astrojs/mdx": "^4.0.8",
|
||||||
|
|||||||
74
server.js
74
server.js
@@ -3,9 +3,14 @@ import fastifyStatic from "@fastify/static";
|
|||||||
import { exec } from "node:child_process";
|
import { exec } from "node:child_process";
|
||||||
import { promisify } from "node:util";
|
import { promisify } from "node:util";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import crypto from "node:crypto";
|
|
||||||
|
|
||||||
const { WEBHOOK_SECRET } = process.env;
|
const { AUTH_TOKEN } = process.env;
|
||||||
|
|
||||||
|
const authMiddleware = async (request, reply) => {
|
||||||
|
if (request.headers.authorization !== `Bearer ${AUTH_TOKEN}`) {
|
||||||
|
return reply.code(401).send("Unauthorized");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
const fastify = Fastify({ logger: true });
|
const fastify = Fastify({ logger: true });
|
||||||
@@ -15,47 +20,38 @@ fastify.register(fastifyStatic, {
|
|||||||
prefix: "/",
|
prefix: "/",
|
||||||
});
|
});
|
||||||
|
|
||||||
const verifySignature = (payload, signature) => {
|
fastify.post(
|
||||||
const hmac = crypto.createHmac("sha256", WEBHOOK_SECRET);
|
"/webhook/rebuild",
|
||||||
const digest = "sha256=" + hmac.update(payload).digest("hex");
|
{ preHandler: authMiddleware },
|
||||||
return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature));
|
async (request, reply) => {
|
||||||
};
|
try {
|
||||||
|
const {
|
||||||
|
ref,
|
||||||
|
repository: { clone_url: repoUrl },
|
||||||
|
} = request.body;
|
||||||
|
|
||||||
const updateRepo = async (repoUrl) => {
|
const { code } = await execAsync("git rev-parse --git-dir")
|
||||||
try {
|
.then(() => ({ code: 0 }))
|
||||||
const { code } = await execAsync("git rev-parse --git-dir")
|
.catch((error) => ({ code: error.code }));
|
||||||
.then(() => ({ code: 0 }))
|
|
||||||
.catch((error) => ({ code: error.code }));
|
|
||||||
|
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
await execAsync("git init");
|
await execAsync("git init");
|
||||||
await execAsync(`git remote add origin ${repoUrl}`);
|
await execAsync(`git remote add origin ${repoUrl}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await execAsync(`git remote set-url origin ${repoUrl}`);
|
||||||
|
await execAsync("git fetch origin");
|
||||||
|
// we won't be able to reply later, so do it here
|
||||||
|
// this doesn't necessarily imply a successful build though
|
||||||
|
// TODO: healthcheck
|
||||||
|
reply.status(200).send("Updated successfully");
|
||||||
|
await execAsync(`git reset --hard ${ref}`);
|
||||||
|
await execAsync("npm run build");
|
||||||
|
} catch (error) {
|
||||||
|
reply.status(500).send("Update failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
await execAsync("git fetch origin");
|
|
||||||
await execAsync("git reset --hard origin/main");
|
|
||||||
await execAsync("npm run build");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to update repository:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
|
|
||||||
fastify.post("/webhook/rebuild", async (request, reply) => {
|
|
||||||
const signature = request.headers["x-gitea-signature"];
|
|
||||||
|
|
||||||
if (!signature || !verifySignature(JSON.stringify(request.body), signature)) {
|
|
||||||
return reply.status(401).send("Invalid signature");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const repoUrl = request.body.repository.clone_url;
|
|
||||||
await updateRepo(repoUrl);
|
|
||||||
reply.status(200).send("Updated successfully");
|
|
||||||
} catch (error) {
|
|
||||||
reply.status(500).send("Update failed");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fastify.listen({ port: 3000, host: "0.0.0.0" }, (err) => {
|
fastify.listen({ port: 3000, host: "0.0.0.0" }, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user