ci: build and push nxtgauge-db-migrate image on every push
All checks were successful
build-and-release / build (developers) (push) Successful in 3m6s
build-and-release / build (jobs) (push) Successful in 1m54s
build-and-release / build-db-migrate (push) Successful in 2m42s
build-and-release / build (companies) (push) Successful in 1m50s
build-and-release / build (photographers) (push) Successful in 2m59s
build-and-release / build (makeup-artists) (push) Successful in 1m34s
build-and-release / build (gateway) (push) Successful in 1m34s
build-and-release / build (ugc-content-creators) (push) Successful in 3m13s
build-and-release / build (job-seekers) (push) Successful in 3m0s
build-and-release / build (tutors) (push) Successful in 2m48s
build-and-release / build (users) (push) Successful in 4m55s
build-and-release / build (customers) (push) Successful in 1m50s
build-and-release / build (graphic-designers) (push) Successful in 1m53s
build-and-release / build (social-media-managers) (push) Successful in 1m51s
build-and-release / build (video-editors) (push) Successful in 2m52s
build-and-release / build (catering-services) (push) Successful in 2m28s
build-and-release / build (fitness-trainers) (push) Successful in 2m49s
build-and-release / build (payments) (push) Successful in 2m44s
build-and-release / build (cron) (push) Successful in 1m6s
build-and-release / build (employees) (push) Successful in 2m28s
backend-integration-tests / ai-credits (push) Successful in 52s
All checks were successful
build-and-release / build (developers) (push) Successful in 3m6s
build-and-release / build (jobs) (push) Successful in 1m54s
build-and-release / build-db-migrate (push) Successful in 2m42s
build-and-release / build (companies) (push) Successful in 1m50s
build-and-release / build (photographers) (push) Successful in 2m59s
build-and-release / build (makeup-artists) (push) Successful in 1m34s
build-and-release / build (gateway) (push) Successful in 1m34s
build-and-release / build (ugc-content-creators) (push) Successful in 3m13s
build-and-release / build (job-seekers) (push) Successful in 3m0s
build-and-release / build (tutors) (push) Successful in 2m48s
build-and-release / build (users) (push) Successful in 4m55s
build-and-release / build (customers) (push) Successful in 1m50s
build-and-release / build (graphic-designers) (push) Successful in 1m53s
build-and-release / build (social-media-managers) (push) Successful in 1m51s
build-and-release / build (video-editors) (push) Successful in 2m52s
build-and-release / build (catering-services) (push) Successful in 2m28s
build-and-release / build (fitness-trainers) (push) Successful in 2m49s
build-and-release / build (payments) (push) Successful in 2m44s
build-and-release / build (cron) (push) Successful in 1m6s
build-and-release / build (employees) (push) Successful in 2m28s
backend-integration-tests / ai-credits (push) Successful in 52s
The migrate image (Dockerfile.migrate) was never part of the CI build matrix - it's a separate crate, not an apps/* service, and the running K8s Job pulls a static <branch>-latest tag rather than a pinned digest. Without this, a stale image silently no-ops new migrations: the Job reports success but applies nothing, which is exactly what happened with the ai_guard_violations migration on 2026-08-15.
This commit is contained in:
parent
605f3bdaaa
commit
f9718f85d0
3 changed files with 60 additions and 17 deletions
|
|
@ -227,3 +227,63 @@ jobs:
|
||||||
echo "Failed to push gitops update for $service after all retries" >&2
|
echo "Failed to push gitops update for $service after all retries" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
build-db-migrate:
|
||||||
|
runs-on: docker-ready
|
||||||
|
# Separate from the service matrix above: db-migrate isn't an apps/*
|
||||||
|
# service (it's crates/db-migrate, built from Dockerfile.migrate), isn't
|
||||||
|
# tracked via the gitops per-SHA release state, and the running Job
|
||||||
|
# always pulls the static `<branch>-latest` tag (see
|
||||||
|
# k8s-migration-job.yaml) rather than a pinned digest. Build on every
|
||||||
|
# push rather than change-detecting crates/db/migrations/** - the whole
|
||||||
|
# point is that a stale image here silently no-ops new migrations
|
||||||
|
# (a job that "succeeds" without applying anything), so keeping this
|
||||||
|
# unconditional trades a little redundant CI time for not repeating that.
|
||||||
|
env:
|
||||||
|
DOCKER_BUILDKIT: "1"
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Point DOCKER_HOST at this container's own gateway
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
GATEWAY="$(awk '$2 == "00000000" {print $3}' /proc/net/route | head -1 | \
|
||||||
|
sed -E 's/(..)(..)(..)(..)/0x\4 0x\3 0x\2 0x\1/' | \
|
||||||
|
{ read -r a b c d; printf '%d.%d.%d.%d' "$a" "$b" "$c" "$d"; })"
|
||||||
|
echo "Detected docker host gateway: $GATEWAY"
|
||||||
|
echo "DOCKER_HOST=tcp://$GATEWAY:2375" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
docker version
|
||||||
|
docker buildx create --use --name nxtgauge-builder || docker buildx use nxtgauge-builder
|
||||||
|
docker buildx inspect --bootstrap
|
||||||
|
|
||||||
|
- name: Login to registry
|
||||||
|
env:
|
||||||
|
REGISTRY_HOST: ${{ secrets.REGISTRY_HOST || 'ci.nxtgauge.com' }}
|
||||||
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
printf '%s' "$REGISTRY_PASSWORD" | docker login "$REGISTRY_HOST" -u "$REGISTRY_USERNAME" --password-stdin
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
env:
|
||||||
|
REGISTRY_HOST: ${{ secrets.REGISTRY_HOST || 'ci.nxtgauge.com' }}
|
||||||
|
REGISTRY_NAMESPACE: ${{ secrets.REGISTRY_NAMESPACE || 'ashwin' }}
|
||||||
|
SHA: ${{ github.sha }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
branch="${GITHUB_REF#refs/heads/}"
|
||||||
|
base="$REGISTRY_HOST/$REGISTRY_NAMESPACE/nxtgauge-db-migrate"
|
||||||
|
|
||||||
|
docker buildx build --push \
|
||||||
|
-f Dockerfile.migrate \
|
||||||
|
-t "${base}:${branch}-latest" \
|
||||||
|
-t "${base}:${SHA}" \
|
||||||
|
.
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
DROP TABLE IF EXISTS ai_guard_violations;
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
-- AI Guard Violations — records every message blocked by the content guard.
|
|
||||||
-- Migration: 20260815000001
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS ai_guard_violations (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
||||||
message_excerpt TEXT NOT NULL, -- first 200 chars, never the full text
|
|
||||||
guard_type VARCHAR(40) NOT NULL, -- 'keyword' | 'length' | 'flood' | 'moderation_api'
|
|
||||||
reason TEXT NOT NULL, -- human-readable rejection reason
|
|
||||||
categories JSONB, -- OpenAI moderation categories (moderation_api only)
|
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_ai_guard_violations_user_id ON ai_guard_violations(user_id);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_ai_guard_violations_created_at ON ai_guard_violations(created_at DESC);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_ai_guard_violations_guard_type ON ai_guard_violations(guard_type);
|
|
||||||
Loading…
Add table
Reference in a new issue