ci: deploy Next preview from next branch
Build and Deploy Next Preview / build-migrate-deploy (push) Failing after 5m14s
Build and Deploy Next Preview / build-migrate-deploy (push) Failing after 5m14s
This commit is contained in:
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
@@ -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"]
|
||||||
|
|||||||
Reference in New Issue
Block a user