From 1d361670119c86bd30909bdaa1376694455b224b Mon Sep 17 00:00:00 2001 From: gunshiz Date: Tue, 22 Sep 2026 18:41:24 +0700 Subject: [PATCH] ci : revert to old version --- .gitea/workflows/ci.yml | 203 +++++++++++++++++++++++----------------- 1 file changed, 117 insertions(+), 86 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 4257f84..b4195b3 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -2,56 +2,40 @@ name: CI on: push: - branches: [main] - schedule: - - cron: '17 3 * * 1' - -concurrency: - group: buzz-sheet-${{ gitea.ref }} - cancel-in-progress: false + branches: + - main env: BASE_URL: https://guide.sudloh.com NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID: ca-pub-9687404323559597 REGISTRY_IMAGE: registry.neko-piranha.ts.net/astral/buzz-sheet DEPLOY_NAMESPACE: buzz-sheet + KUBE_API_SERVER: https://100.112.189.33:6443/ jobs: verify: - name: Verify and audit + name: Verify runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 15 steps: - - name: Check out repository and history - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - with: - fetch-depth: 0 - persist-credentials: false + - name: Check out repository + uses: actions/checkout@v4 - name: Set up Bun - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.14 - name: Set up kubectl - uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4 - with: - version: v1.34.1 + uses: azure/setup-kubectl@v4 - name: Verify application and manifests run: | bun install --frozen-lockfile - bun run security:audit bun run test bun run typecheck bun run lint kubectl kustomize k8s/ >/dev/null - - name: Scan Git history for secrets - run: | - docker run --rm --cap-drop=ALL --security-opt=no-new-privileges \ - --volume "$PWD:/repo:ro" --workdir /repo \ - ghcr.io/gitleaks/gitleaks@sha256:691af3c7c5a48b16f187ce3446d5f194838f91238f27270ed36eef6359a574d9 \ - git --redact=100 --no-banner --log-opts=--all . build-and-deploy: - name: Build, scan and deploy immutable images + name: Build immutable images and deploy needs: verify if: >- gitea.event_name == 'push' && @@ -61,83 +45,130 @@ jobs: timeout-minutes: 45 steps: - name: Check out repository - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - with: - persist-credentials: false - - name: Build and scan application and migration images - env: - REVISION: ${{ gitea.sha }} + uses: actions/checkout@v4 + + - name: Build and push application image run: | - set -Eeuo pipefail - docker build --target app \ + docker build \ + --target app \ --build-arg BASE_URL="$BASE_URL" \ --build-arg NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID="$NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID" \ - --build-arg NEXT_DEPLOYMENT_ID="$REVISION" \ - --build-arg VCS_REF="$REVISION" \ - --tag "$REGISTRY_IMAGE:$REVISION" . - docker build --target migration --build-arg VCS_REF="$REVISION" \ - --tag "$REGISTRY_IMAGE:migrate-$REVISION" . - docker save --output "$RUNNER_TEMP/buzz-app-image.tar" "$REGISTRY_IMAGE:$REVISION" - docker save --output "$RUNNER_TEMP/buzz-migration-image.tar" "$REGISTRY_IMAGE:migrate-$REVISION" - chmod 644 "$RUNNER_TEMP/buzz-app-image.tar" "$RUNNER_TEMP/buzz-migration-image.tar" - # One scanner container shares its private cache across both images. - docker run --rm --user 0:0 --cap-drop=ALL --security-opt=no-new-privileges \ - --volume "$RUNNER_TEMP/buzz-app-image.tar:/scan/buzz-app-image.tar:ro" \ - --volume "$RUNNER_TEMP/buzz-migration-image.tar:/scan/buzz-migration-image.tar:ro" \ - --entrypoint /bin/sh \ - aquasec/trivy@sha256:bcc376de8d77cfe086a917230e818dc9f8528e3c852f7b1aff648949b6258d1c \ - -ec 'trivy image --input /scan/buzz-app-image.tar --cache-dir /tmp/trivy-cache --scanners vuln --severity HIGH,CRITICAL --exit-code 1 && - trivy image --input /scan/buzz-migration-image.tar --cache-dir /tmp/trivy-cache --scanners vuln --severity HIGH,CRITICAL --exit-code 1' - rm "$RUNNER_TEMP/buzz-app-image.tar" "$RUNNER_TEMP/buzz-migration-image.tar" - docker push "$REGISTRY_IMAGE:$REVISION" | tee "$RUNNER_TEMP/buzz-app-push.log" - docker push "$REGISTRY_IMAGE:migrate-$REVISION" | tee "$RUNNER_TEMP/buzz-migration-push.log" + --build-arg NEXT_DEPLOYMENT_ID=${{ gitea.sha }} \ + --build-arg VCS_REF=${{ gitea.sha }} \ + --tag ${{ env.REGISTRY_IMAGE }}:${{ gitea.sha }} \ + . + docker push ${{ env.REGISTRY_IMAGE }}:${{ gitea.sha }} + + - name: Build and push migration image + run: | + docker build \ + --target migration \ + --build-arg VCS_REF=${{ gitea.sha }} \ + --tag ${{ env.REGISTRY_IMAGE }}:migrate-${{ gitea.sha }} \ + . + docker push ${{ env.REGISTRY_IMAGE }}:migrate-${{ gitea.sha }} + - name: Set up kubectl - uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4 - with: - version: v1.34.1 - - name: Migrate, then roll out verified digests + uses: azure/setup-kubectl@v4 + + - name: Configure kubectl + env: + KUBE_CONFIG_B64: ${{ secrets.KUBE_CONFIG_B64 }} + run: | + if [ -z "$KUBE_CONFIG_B64" ]; then + echo "Missing KUBE_CONFIG_B64 secret for the CI deploy identity" >&2 + exit 1 + fi + + 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" + cluster_name="$(kubectl config view --kubeconfig "$KUBECONFIG" --minify -o jsonpath='{.clusters[0].name}')" + kubectl config set-cluster "$cluster_name" \ + --kubeconfig "$KUBECONFIG" \ + --server "$KUBE_API_SERVER" \ + --insecure-skip-tls-verify=true >/dev/null + + env_file="${GITEA_ENV_FILE:-${GITHUB_ENV:-}}" + if [ -n "$env_file" ]; then + printf '%s\n' "KUBECONFIG=$KUBECONFIG" >> "$env_file" + fi + + - name: Migrate, then roll out the immutable revision env: REVISION: ${{ gitea.sha }} KUBE_CONFIG_B64: ${{ secrets.KUBE_CONFIG_B64 }} shell: bash run: | set -Eeuo pipefail + + if [ -z "$KUBE_CONFIG_B64" ]; then + echo "Missing KUBE_CONFIG_B64 secret for the CI deploy identity" >&2 + exit 1 + fi + kube_dir="$RUNNER_TEMP/buzz-sheet-kube" mkdir -p "$kube_dir" chmod 700 "$kube_dir" export KUBECONFIG="$kube_dir/config" - trap 'rm -f "$KUBECONFIG"' EXIT - printf '%s' "$KUBE_CONFIG_B64" | base64 --decode > "$KUBECONFIG" + if ! printf '%s' "$KUBE_CONFIG_B64" | base64 --decode >"$KUBECONFIG"; then + echo "KUBE_CONFIG_B64 is not valid base64" >&2 + exit 1 + fi chmod 600 "$KUBECONFIG" - test -s "$KUBECONFIG" - insecure="$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.insecure-skip-tls-verify}')" - if [ "$insecure" = true ]; then - echo 'The deployment kubeconfig must validate the Kubernetes certificate.' >&2 + if [ ! -s "$KUBECONFIG" ]; then + echo "KUBE_CONFIG_B64 decoded to an empty kubeconfig" >&2 exit 1 fi - # Preserve the CA and certificate-valid server supplied in the kubeconfig. - kubectl --namespace "$DEPLOY_NAMESPACE" get deployment buzz-sheet >/dev/null - app_digest="$(sed -nE 's/.*digest: (sha256:[a-f0-9]{64}).*/\1/p' "$RUNNER_TEMP/buzz-app-push.log" | tail -n 1)" - migration_digest="$(sed -nE 's/.*digest: (sha256:[a-f0-9]{64}).*/\1/p' "$RUNNER_TEMP/buzz-migration-push.log" | tail -n 1)" - app_image="$REGISTRY_IMAGE@$app_digest" - migration_image="$REGISTRY_IMAGE@$migration_digest" - [[ "$app_image" =~ @sha256:[a-f0-9]{64}$ ]] - [[ "$migration_image" =~ @sha256:[a-f0-9]{64}$ ]] - migration_manifest="$RUNNER_TEMP/buzz-sheet-migration.yaml" - kubectl kustomize k8s/migration > "$migration_manifest" - sed -i "s#image: $REGISTRY_IMAGE:.*#image: $migration_image#" "$migration_manifest" - grep -Fq "image: $migration_image" "$migration_manifest" - kubectl --namespace "$DEPLOY_NAMESPACE" delete job buzz-sheet-migrate --ignore-not-found - 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 + cluster_name="$(kubectl config view --kubeconfig "$KUBECONFIG" --minify -o jsonpath='{.clusters[0].name}')" + if [ -z "$cluster_name" ]; then + echo "Decoded kubeconfig has no active cluster" >&2 exit 1 fi - kubectl --namespace "$DEPLOY_NAMESPACE" patch configmap buzz-sheet-config --type=merge \ + kubectl config set-cluster "$cluster_name" \ + --kubeconfig "$KUBECONFIG" \ + --server "$KUBE_API_SERVER" \ + --insecure-skip-tls-verify=true >/dev/null + + 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#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" + + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" delete job buzz-sheet-migrate --ignore-not-found + migration_resource="$(kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" create --validate=false -f "$migration_manifest" -o name)" + if ! kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" wait \ + --for=condition=complete \ + --timeout=10m \ + "$migration_resource"; then + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" logs "$migration_resource" --all-containers=true || true + exit 1 + fi + + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" patch configmap buzz-sheet-config \ + --type=merge \ --patch "{\"data\":{\"NEXT_DEPLOYMENT_ID\":\"$REVISION\",\"BASE_URL\":\"$BASE_URL\"}}" - kubectl --namespace "$DEPLOY_NAMESPACE" set image deployment/buzz-sheet app="$app_image" - kubectl --namespace "$DEPLOY_NAMESPACE" set image deployment/buzz-sheet-worker worker="$app_image" - kubectl --namespace "$DEPLOY_NAMESPACE" set image deployment/buzz-sheet-discord-worker discord-worker="$app_image" - for deployment in buzz-sheet buzz-sheet-worker buzz-sheet-discord-worker; do - kubectl --namespace "$DEPLOY_NAMESPACE" rollout status "deployment/$deployment" --timeout=10m - done + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" set image \ + deployment/buzz-sheet \ + app="$REGISTRY_IMAGE:$REVISION" + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" set image \ + deployment/buzz-sheet-worker \ + worker="$REGISTRY_IMAGE:$REVISION" + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" set image \ + deployment/buzz-sheet-discord-worker \ + discord-worker="$REGISTRY_IMAGE:$REVISION" + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" rollout status \ + deployment/buzz-sheet \ + --timeout=10m + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" rollout status \ + deployment/buzz-sheet-worker \ + --timeout=10m + kubectl --kubeconfig "$KUBECONFIG" --namespace "$DEPLOY_NAMESPACE" rollout status \ + deployment/buzz-sheet-discord-worker \ + --timeout=10m