feat : 6 astra improve it
This commit is contained in:
+84
-117
@@ -2,40 +2,56 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '17 3 * * 1'
|
||||
|
||||
concurrency:
|
||||
group: buzz-sheet-${{ gitea.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
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
|
||||
name: Verify and audit
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out repository and history
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
||||
with:
|
||||
bun-version: 1.3.14
|
||||
- name: Set up kubectl
|
||||
uses: azure/setup-kubectl@v4
|
||||
uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4
|
||||
with:
|
||||
version: v1.34.1
|
||||
- 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 immutable images and deploy
|
||||
name: Build, scan and deploy immutable images
|
||||
needs: verify
|
||||
if: >-
|
||||
gitea.event_name == 'push' &&
|
||||
@@ -45,130 +61,81 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build and push application image
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Build and scan application and migration images
|
||||
env:
|
||||
REVISION: ${{ gitea.sha }}
|
||||
run: |
|
||||
docker build \
|
||||
--target app \
|
||||
set -Eeuo pipefail
|
||||
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=${{ 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 }}
|
||||
|
||||
--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" .
|
||||
mkdir -p "$RUNNER_TEMP/buzz-trivy-cache"
|
||||
for tag in "$REVISION" "migrate-$REVISION"; do
|
||||
docker save --output "$RUNNER_TEMP/buzz-image.tar" "$REGISTRY_IMAGE:$tag"
|
||||
docker run --rm --user "$(id -u):$(id -g)" --cap-drop=ALL --security-opt=no-new-privileges \
|
||||
--volume "$RUNNER_TEMP:/scan:ro" \
|
||||
--volume "$RUNNER_TEMP/buzz-trivy-cache:/cache" \
|
||||
aquasec/trivy@sha256:bcc376de8d77cfe086a917230e818dc9f8528e3c852f7b1aff648949b6258d1c \
|
||||
image --input /scan/buzz-image.tar --cache-dir /cache --scanners vuln --severity HIGH,CRITICAL --exit-code 1
|
||||
rm "$RUNNER_TEMP/buzz-image.tar"
|
||||
done
|
||||
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"
|
||||
- name: Set up kubectl
|
||||
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
|
||||
uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4
|
||||
with:
|
||||
version: v1.34.1
|
||||
- name: Migrate, then roll out verified digests
|
||||
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"
|
||||
if ! printf '%s' "$KUBE_CONFIG_B64" | base64 --decode >"$KUBECONFIG"; then
|
||||
echo "KUBE_CONFIG_B64 is not valid base64" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -f "$KUBECONFIG"' EXIT
|
||||
printf '%s' "$KUBE_CONFIG_B64" | base64 --decode > "$KUBECONFIG"
|
||||
chmod 600 "$KUBECONFIG"
|
||||
if [ ! -s "$KUBECONFIG" ]; then
|
||||
echo "KUBE_CONFIG_B64 decoded to an empty kubeconfig" >&2
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
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
|
||||
# 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
|
||||
exit 1
|
||||
fi
|
||||
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 \
|
||||
kubectl --namespace "$DEPLOY_NAMESPACE" patch configmap buzz-sheet-config --type=merge \
|
||||
--patch "{\"data\":{\"NEXT_DEPLOYMENT_ID\":\"$REVISION\",\"BASE_URL\":\"$BASE_URL\"}}"
|
||||
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
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user