deploy read-only Formulation viewer

This commit is contained in:
2026-08-13 17:45:01 -05:00
parent 04e15aca22
commit 9591742d1d
6 changed files with 41 additions and 20 deletions
+9
View File
@@ -0,0 +1,9 @@
.git
.astro
dist
generated
node_modules
var
.env*
*.png
*.html
+3 -8
View File
@@ -1,4 +1,4 @@
name: Build & Push Astro Site Image
name: Build & Deploy Formulation
on:
push:
@@ -12,7 +12,7 @@ jobs:
env:
REGISTRY_USERNAME: nicholas
IMAGE_REGISTRY: git.uuard.com
IMAGE_NAME: nicholas/recipe-book
IMAGE_NAME: nicholas/formulation
IMAGE_TAG: ${{ github.sha }}
runs-on: shared-ci
steps:
@@ -30,11 +30,6 @@ jobs:
python3 -m pip install --user -r requirements-dev.txt
scripts/validate-content
- name: 🏗️ Build Astro site
run: |
npm ci
npm run build
- name: 🔐 Gitea Registry Login
uses: docker/login-action@v3
with:
@@ -83,7 +78,7 @@ jobs:
chmod 600 ~/.kube/config
kubectl auth can-i update deployments --namespace nicholas
- name: Deploy recipe-book
- name: Deploy Formulation read-only viewer
run: |
set -euo pipefail
sed -E -i "s#newTag: [0-9a-f]+#newTag: ${IMAGE_TAG}#" k8s/kustomization.yaml
+20 -4
View File
@@ -1,7 +1,23 @@
FROM nginx:alpine
FROM node:24-alpine AS build
RUN rm -rf /usr/share/nginx/html/*
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run db:reset && npm run build
COPY dist /usr/share/nginx/html/
FROM node:24-alpine AS runtime
EXPOSE 80
ENV NODE_ENV=production \
FORMULATION_READ_ONLY=true \
HOST=0.0.0.0 \
PORT=8080
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY --from=build --chown=node:node /app/dist/app ./dist/app
COPY --from=build --chown=node:node /app/var/recipe-book.sqlite ./var/recipe-book.sqlite
COPY --from=build --chown=node:node /app/public ./public
USER node
EXPOSE 8080
CMD ["node", "dist/app/server/entry.mjs"]
+6 -6
View File
@@ -25,15 +25,15 @@ spec:
- name: gitea-registry
containers:
- name: recipe-book
image: git.uuard.com/nicholas/recipe-book
image: git.uuard.com/nicholas/formulation
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
path: /
path: /app/
port: http
initialDelaySeconds: 2
periodSeconds: 5
@@ -41,7 +41,7 @@ spec:
failureThreshold: 6
livenessProbe:
httpGet:
path: /
path: /app/
port: http
initialDelaySeconds: 10
periodSeconds: 10
@@ -50,10 +50,10 @@ spec:
resources:
requests:
cpu: 10m
memory: 32Mi
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
memory: 256Mi
securityContext:
allowPrivilegeEscalation: false
seccompProfile:
+2 -2
View File
@@ -6,5 +6,5 @@ resources:
- service.yaml
- ingress.yaml
images:
- name: git.uuard.com/nicholas/recipe-book
newTag: 7c17e3047560967dd58f8f7b8f0dd7387ba46aa5
- name: git.uuard.com/nicholas/formulation
newTag: latest
+1
View File
@@ -4,6 +4,7 @@ import { readOnlyMode } from "../lib/runtime";
const safeMethods = new Set(["GET", "HEAD", "OPTIONS"]);
export const onRequest = defineMiddleware(async ({ request, url, redirect }, next) => {
if (url.pathname === "/") return redirect("/app/", 302);
if (!readOnlyMode) return next();
if (!safeMethods.has(request.method)) {
return new Response("This Formulation instance is read-only.", { status: 405, headers: { Allow: "GET, HEAD, OPTIONS" } });