ci: deploy Next preview from next branch
Build and Deploy Next Preview / build-migrate-deploy (push) Failing after 5m14s

This commit is contained in:
2026-10-09 11:21:13 +00:00 Unverified
parent 7d3521dca8
commit 5d6a706565
7 changed files with 217 additions and 1 deletions
+94
View File
@@ -0,0 +1,94 @@
name: Build and Deploy Next Preview
on:
workflow_dispatch:
push:
branches:
- next
concurrency:
group: buzz-next-deploy
cancel-in-progress: false
jobs:
build-migrate-deploy:
if: gitea.ref == 'refs/heads/next'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install kubectl
run: |
set -euo pipefail
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSLO "https://dl.k8s.io/release/v1.35.0/bin/linux/${ARCH}/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/kubectl
- name: Configure kubectl
env:
KUBE_TOKEN: ${{ secrets.KUBE_TOKEN }}
run: |
set -euo pipefail
kubectl config set-cluster buzz --server=https://astrxl-la3.neko-piranha.ts.net:6443 --insecure-skip-tls-verify=true
kubectl config set-credentials ci-deployer --token="$KUBE_TOKEN"
kubectl config set-context buzz --cluster=buzz --user=ci-deployer --namespace=buzz
kubectl config use-context buzz
- name: Prepare shared environment for preview build
run: |
set -euo pipefail
kubectl get secret buzz-env -n buzz \
-o go-template='{{range $k,$v := .data}}{{$k}}={{$v|base64decode}}{{"\n"}}{{end}}' > .env
chmod 600 .env
sed -i '/^BASE_URL=/d' .env
sed -i '/^BETTER_AUTH_URL=/d;/^DISCORD_REDIRECT_URI=/d' .env
printf '%s\n' \
'BASE_URL=https://buzz-next.sudloh.com' \
'BETTER_AUTH_URL=https://buzz-next.sudloh.com' \
'DISCORD_REDIRECT_URI=https://buzz-next.sudloh.com/rubgram/callback' >> .env
- name: Build and push immutable preview images
env:
TAG: ${{ gitea.sha }}
IMAGE_REPOSITORY: registry.neko-piranha.ts.net/${{ gitea.repository }}
run: |
set -euo pipefail
docker build -t "$IMAGE_REPOSITORY:frontend-next-$TAG" .
docker build --target migration -t "$IMAGE_REPOSITORY:migration-next-$TAG" .
docker push "$IMAGE_REPOSITORY:frontend-next-$TAG"
docker push "$IMAGE_REPOSITORY:migration-next-$TAG"
- name: Run database migration
env:
TAG: ${{ gitea.sha }}
IMAGE_REPOSITORY: registry.neko-piranha.ts.net/${{ gitea.repository }}
run: |
set -euo pipefail
JOB="db-migrate-next-${TAG}"
kubectl delete job "$JOB" -n buzz --ignore-not-found
kubectl create job "$JOB" \
--image="$IMAGE_REPOSITORY:migration-next-$TAG" \
-n buzz --dry-run=client -o json -- bun dr push \
| jq '.spec.template.spec.containers[0].envFrom = [{"secretRef":{"name":"buzz-env"}}] | .spec.template.spec.containers[0].imagePullPolicy = "Always"' \
| kubectl apply -f -
if ! kubectl wait --for=condition=complete "job/$JOB" -n buzz --timeout=600s; then
kubectl describe job "$JOB" -n buzz || true
POD=$(kubectl get pods -n buzz -l "job-name=$JOB" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
if [ -n "$POD" ]; then
kubectl logs "$POD" -n buzz --all-containers=true || true
fi
exit 1
fi
- name: Apply preview resources and wait for rollout
env:
TAG: ${{ gitea.sha }}
IMAGE_REPOSITORY: registry.neko-piranha.ts.net/${{ gitea.repository }}
run: |
set -euo pipefail
kubectl kustomize k8s/next \
| sed "s|${IMAGE_REPOSITORY}:frontend-next-__TAG__|${IMAGE_REPOSITORY}:frontend-next-${TAG}|g" \
| kubectl apply -f -
kubectl rollout status deployment/app-next -n buzz --timeout=180s
+13
View File
@@ -1,5 +1,18 @@
# Buzz Events — k3s Deployment # Buzz Events — k3s Deployment
## Next.js Preview (`next` branch)
- The `next` branch deploys a separate preview at `buzz-next.sudloh.com` using only `k8s/next/` resources: Deployment, Service, and Ingress named `app-next` with label `component: app-next`.
- The preview shares the `buzz` namespace and existing `buzz-env` secret, including its database credentials. `BASE_URL`, `BETTER_AUTH_URL`, and `DISCORD_REDIRECT_URI` are overridden for preview build and runtime behavior so production auth URLs in the shared secret cannot redirect preview traffic.
- Register `https://buzz-next.sudloh.com/rubgram/callback` as an allowed redirect URI in the Discord OAuth application used by `buzz-env`. DNS and HTTPS/TLS for `buzz-next.sudloh.com` must also be routed to the cluster ingress before preview auth is usable.
- The preview currently has no backend deployment. No backend images or production image tags are built, pushed, or rolled out by `.github/workflows/build-next.yml`.
- Each run builds immutable `frontend-next-$SHA` and `migration-next-$SHA` images. It waits for the uniquely named `db-migrate-next-$SHA` Job to complete successfully before applying preview resources, so a failed or timed-out migration does not deploy the app.
- The workflow is limited to the local `next` branch (push or manual dispatch from `next`) and does not alter the existing main/dev workflow or root `k8s/kustomization.yaml`.
- The database is shared with production: any schema migration from the preview also affects production. No schema changes are included in this preview setup; review compatibility and production impact before introducing future schema changes.
Bootstrap/application is performed by the next workflow after migration; do not apply the root `k8s/` kustomization for this preview because it manages production and backend resources.
Before the first workflow run, update the existing deployer permissions with `kubectl apply -f k8s/role.yaml` so it can create the preview Deployment (the existing Role already permits creating Services and Ingresses).
## Architecture Decisions ## Architecture Decisions
### Ingress ### Ingress
+64
View File
@@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-next
labels:
app: buzz
component: app-next
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: buzz
component: app-next
template:
metadata:
labels:
app: buzz
component: app-next
spec:
terminationGracePeriodSeconds: 5
containers:
- name: app-next
image: registry.neko-piranha.ts.net/astral/buzz:frontend-next-__TAG__
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
protocol: TCP
envFrom:
- secretRef:
name: buzz-env
env:
- name: BASE_URL
value: https://buzz-next.sudloh.com
- name: BETTER_AUTH_URL
value: https://buzz-next.sudloh.com
- name: DISCORD_REDIRECT_URI
value: https://buzz-next.sudloh.com/rubgram/callback
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 10
periodSeconds: 60
timeoutSeconds: 30
failureThreshold: 3
readinessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 15
+19
View File
@@ -0,0 +1,19 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-next
annotations:
traefik.ingress.kubernetes.io/read-timeout: "200"
spec:
ingressClassName: traefik
rules:
- host: buzz-next.sudloh.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-next
port:
number: 3000
+9
View File
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: buzz
resources:
- deployment-app-next.yaml
- service-app-next.yaml
- ingress-app-next.yaml
+17
View File
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: app-next
labels:
app: buzz
component: app-next
spec:
selector:
app: buzz
component: app-next
ports:
- port: 3000
targetPort: 3000
protocol: TCP
name: http
type: ClusterIP
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
rules: rules:
- apiGroups: ["apps"] - apiGroups: ["apps"]
resources: ["deployments"] resources: ["deployments"]
verbs: ["get", "list", "watch", "update", "patch"] verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""] - apiGroups: [""]
resources: ["pods"] resources: ["pods"]
verbs: ["get", "list", "watch"] verbs: ["get", "list", "watch"]