name: build-and-release on: push: branches: - main - high-performance concurrency: group: ai-assistant-build-${{ github.ref }} cancel-in-progress: true jobs: build: runs-on: docker-ready 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 # 127.0.0.1 doesn't work: the job container is nested one level # inside the runner pod's dind sidecar, so its own loopback isn't # the sidecar's. Read the container's actual default-route gateway # from /proc/net/route instead (the dind engine that spawned it). 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 for attempt in $(seq 1 30); do if docker version >/dev/null 2>&1; then break fi sleep 2 done docker version docker buildx create --use --name nxtgauge-builder || docker buildx use nxtgauge-builder docker buildx inspect --bootstrap - name: Login to Forgejo registry env: 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 image env: REGISTRY_HOST: ci.nxtgauge.com SHA: ${{ github.sha }} run: | set -euo pipefail image_ref="$REGISTRY_HOST/ashwin/nxtgauge-ai-assistant:$SHA" metadata_file="/tmp/ai-assistant-metadata.json" docker buildx build --push \ --metadata-file "$metadata_file" \ -t "$image_ref" \ -t "$REGISTRY_HOST/ashwin/nxtgauge-ai-assistant:latest" \ -f Dockerfile \ . digest="$(grep -o '"containerimage\.digest"[[:space:]]*:[[:space:]]*"sha256:[^"]*"' "$metadata_file" | grep -o 'sha256:[^"]*')" test -n "$digest" echo "IMAGE_DIGEST=$digest" >> "$GITHUB_ENV" - name: Update GitOps env: GITOPS_REPO: https://ci.nxtgauge.com/ashwin/nxtgauge-gitops.git GITOPS_TOKEN: ${{ secrets.GITOPS_TOKEN }} SHA: ${{ github.sha }} DIGEST: ${{ env.IMAGE_DIGEST }} run: | set -euo pipefail apk add --no-cache git git config --global credential.helper '!f() { printf "%s\\n" "username=forgejo-actions"; printf "%s\\n" "password=$GITOPS_TOKEN"; }; f' GITOPS_DIR=$(mktemp -d) # -b main: this repo's server-side HEAD symref is broken (returns # "remote HEAD refers to nonexistent ref" on a plain clone even # though refs/heads/main exists) - an explicit branch bypasses # HEAD resolution entirely instead of relying on it. git clone -b main "$GITOPS_REPO" "$GITOPS_DIR" cd "$GITOPS_DIR" # release-patch.yaml pins by digest (@sha256:...), not by mutable # tag - Flux's ImageUpdateAutomation previously raced this file via # a $imagepolicy marker comment and always won because its # alphabetical tag ordering sorted "latest" above any hex SHA, # clobbering this step's commits every ~2 minutes. The marker was # removed from the file so this CI step is now the sole writer. sed -i -E "s#image: ci\.nxtgauge\.com/ashwin/nxtgauge-ai-assistant(:[a-f0-9]+|@sha256:[a-f0-9]+)#image: ci.nxtgauge.com/ashwin/nxtgauge-ai-assistant@${DIGEST}#" apps/nxtgauge-ai-assistant/overlays/prod/release-patch.yaml git config user.name "forgejo-actions[bot]" git config user.email "forgejo-actions@ci.nxtgauge.com" git add apps/nxtgauge-ai-assistant/overlays/prod/release-patch.yaml git diff --quiet || (git commit -m "chore(gitops): deploy ai-assistant@${SHA} (${DIGEST})" && git push)