From 1e486c267a6635ed854fc970e2e567b1fda67eb9 Mon Sep 17 00:00:00 2001 From: gunshiz Date: Sat, 29 Aug 2026 06:05:06 +0000 Subject: [PATCH] feat(ci): build and deploy immutable revisions --- .gitea/workflows/ci.yml | 143 ++++++++++++++++++++++++++++++++++++++++ k8s/base/ci-rbac.yaml | 2 +- 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/ci.yml diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..e71fa6e --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,143 @@ +name: CI + +on: + push: + pull_request: + +env: + REGISTRY_IMAGE: registry.neko-piranha.ts.net/astral/buzz-sheet + REGISTRY_HOST: registry.neko-piranha.ts.net + DEPLOY_NAMESPACE: buzz-sheet + +jobs: + verify: + name: Verify + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.14 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Run unit and integration tests + run: bun run test + + - name: Check TypeScript + run: bunx tsc --noEmit + + - name: Lint + run: bun run lint + + - name: Set up kubectl + uses: azure/setup-kubectl@v4 + + - name: Validate Kubernetes manifests + run: kubectl kustomize k8s/ >/dev/null + + build-and-deploy: + name: Build immutable images and deploy + needs: verify + if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main' + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Sign in to the container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY_HOST }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Build and push application image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + target: app + platforms: linux/amd64,linux/arm64 + push: true + provenance: false + tags: ${{ env.REGISTRY_IMAGE }}:${{ gitea.sha }} + build-args: | + NEXT_DEPLOYMENT_ID=${{ gitea.sha }} + VCS_REF=${{ gitea.sha }} + + - name: Build and push migration image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + target: migration + platforms: linux/amd64,linux/arm64 + push: true + provenance: false + tags: ${{ env.REGISTRY_IMAGE }}:migrate-${{ gitea.sha }} + build-args: VCS_REF=${{ gitea.sha }} + + - name: Set up kubectl + uses: azure/setup-kubectl@v4 + + - name: Migrate, then roll out the immutable revision + env: + KUBE_CONFIG_B64: ${{ secrets.KUBE_CONFIG_B64 }} + REVISION: ${{ gitea.sha }} + shell: bash + run: | + set -Eeuo pipefail + + kube_dir="$RUNNER_TEMP/buzz-sheet-kube" + mkdir -p "$kube_dir" + chmod 700 "$kube_dir" + export KUBECONFIG="$kube_dir/config" + printf '%s' "$KUBE_CONFIG_B64" | base64 --decode >"$KUBECONFIG" + chmod 600 "$KUBECONFIG" + + revision_short="${REVISION:0:12}" + migration_dir="$RUNNER_TEMP/buzz-sheet-migration-$revision_short" + migration_manifest="$RUNNER_TEMP/buzz-sheet-migration-$revision_short.yaml" + cp -R k8s/migration "$migration_dir" + sed -i "s/name: buzz-sheet-migrate$/name: buzz-sheet-migrate-$revision_short/" "$migration_dir/job.yaml" + sed -i "s#newName: .*#newName: $REGISTRY_IMAGE#" "$migration_dir/kustomization.yaml" + sed -i "s/newTag: .*/newTag: migrate-$REVISION/" "$migration_dir/kustomization.yaml" + kubectl kustomize "$migration_dir" >"$migration_manifest" + + migration_resource="$(kubectl --namespace "$DEPLOY_NAMESPACE" create -f "$migration_manifest" -o name)" + if ! kubectl --namespace "$DEPLOY_NAMESPACE" wait \ + --for=condition=complete \ + --timeout=10m \ + "$migration_resource"; then + kubectl --namespace "$DEPLOY_NAMESPACE" logs "$migration_resource" --all-containers=true || true + exit 1 + fi + + kubectl --namespace "$DEPLOY_NAMESPACE" patch configmap buzz-sheet-config \ + --type=merge \ + --patch "{\"data\":{\"NEXT_DEPLOYMENT_ID\":\"$REVISION\"}}" + kubectl --namespace "$DEPLOY_NAMESPACE" set image \ + deployment/buzz-sheet \ + app="$REGISTRY_IMAGE:$REVISION" + kubectl --namespace "$DEPLOY_NAMESPACE" set image \ + deployment/buzz-sheet-worker \ + worker="$REGISTRY_IMAGE:$REVISION" + kubectl --namespace "$DEPLOY_NAMESPACE" rollout status \ + deployment/buzz-sheet \ + --timeout=10m + kubectl --namespace "$DEPLOY_NAMESPACE" rollout status \ + deployment/buzz-sheet-worker \ + --timeout=10m diff --git a/k8s/base/ci-rbac.yaml b/k8s/base/ci-rbac.yaml index 006a550..d5439df 100644 --- a/k8s/base/ci-rbac.yaml +++ b/k8s/base/ci-rbac.yaml @@ -27,7 +27,7 @@ rules: - apiGroups: ["apps"] resources: ["deployments"] resourceNames: ["buzz-sheet", "buzz-sheet-worker"] - verbs: ["get", "patch", "update"] + verbs: ["get", "watch", "patch", "update"] - apiGroups: ["apps"] resources: ["replicasets"] verbs: ["get", "list", "watch"]