fix(ci): deploy frontend via immutable gitops release
Some checks failed
build-and-release / build (push) Failing after 5s

This commit is contained in:
Ashwin Kumar Sivakumar 2026-06-14 05:52:50 +05:30
parent 494384e6c6
commit 18759f9670
3 changed files with 60 additions and 192 deletions

View file

@ -1,13 +0,0 @@
#!/busybox/sh
set -eu
mkdir -p /kaniko/.docker
cat > /kaniko/.docker/config.json <<JSON
{"auths":{"${REGISTRY_HOSTPORT}":{"username":"${REGISTRY_USERNAME}","password":"${REGISTRY_PASSWORD}"}}}
JSON
/kaniko/executor \
--context "${GITHUB_WORKSPACE}" \
--dockerfile "${GITHUB_WORKSPACE}/Dockerfile" \
--destination "${REGISTRY_HOSTPORT}/${IMAGE_NAME}:${COMMIT_SHA}" \
--destination "${REGISTRY_HOSTPORT}/${IMAGE_NAME}:${LATEST_TAG}"

View file

@ -1,149 +0,0 @@
#!/usr/bin/env python3
"""
Update GitOps kustomization.yaml with new image SHA tags.
Usage:
python3 update-gitops.py \
--repo /path/to/nxtgauge-gitops \
--service gateway \
--sha abc123def456...
This script:
1. Updates the newTag for the specified service to the SHA
2. Commits and pushes to the gitops repo
3. Flux detects the change and deploys
"""
import argparse
import os
import re
import subprocess
import sys
def run(cmd: list[str], cwd: str = None) -> tuple[int, str, str]:
"""Run a command and return (returncode, stdout, stderr)."""
result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True)
return result.returncode, result.stdout, result.stderr
def update_kustomization(kustomization_path: str, service: str, sha: str) -> bool:
"""Update the newTag for a service in kustomization.yaml."""
with open(kustomization_path, "r") as f:
content = f.read()
# Pattern to find image entry for the service
# Matches: - name: registry.nxtgauge.com/nxtgauge-rust-{service}
# newTag: something
pattern = rf'(\s+-\s+name:\s+registry\.nxtgauge\.com/nxtgauge-rust-{re.escape(service)}\n\s+newTag:\s+)[^\n]+'
replacement = rf'\g<1>{sha}'
new_content, count = re.subn(pattern, replacement, content)
if count == 0:
# Try without the nxtgauge-rust- prefix (for frontend, admin, etc)
pattern = rf'(\s+-\s+name:\s+registry\.nxtgauge\.com/nxtgauge-{re.escape(service)}\n\s+newTag:\s+)[^\n]+'
new_content, count = re.subn(pattern, replacement, content)
if count == 0:
print(f"[ERROR] Could not find image entry for service: {service}")
return False
with open(kustomization_path, "w") as f:
f.write(new_content)
print(f"[OK] Updated {service} to SHA {sha}")
return True
def main():
parser = argparse.ArgumentParser(description="Update GitOps with new image SHA")
parser.add_argument("--repo", required=True, help="Path to gitops repo")
parser.add_argument("--service", required=True, help="Service name (e.g., gateway, users, frontend-solid)")
parser.add_argument("--sha", required=True, help="Git SHA to deploy")
parser.add_argument("--message", default=None, help="Commit message")
args = parser.parse_args()
service_image_map = {
"gateway": "nxtgauge-rust-gateway",
"users": "nxtgauge-rust-users",
"companies": "nxtgauge-rust-companies",
"jobs": "nxtgauge-rust-jobs",
"leads": "nxtgauge-rust-leads",
"job-seekers": "nxtgauge-rust-job-seekers",
"customers": "nxtgauge-rust-customers",
"payments": "nxtgauge-rust-payments",
"employees": "nxtgauge-rust-employees",
"photographers": "nxtgauge-rust-photographers",
"makeup-artists": "nxtgauge-rust-makeup-artists",
"tutors": "nxtgauge-rust-tutors",
"developers": "nxtgauge-rust-developers",
"video-editors": "nxtgauge-rust-video-editors",
"graphic-designers": "nxtgauge-rust-graphic-designers",
"social-media-managers": "nxtgauge-rust-social-media-managers",
"fitness-trainers": "nxtgauge-rust-fitness-trainers",
"catering-services": "nxtgauge-rust-catering-services",
"ugc-content-creators": "nxtgauge-rust-ugc-content-creators",
"cron": "nxtgauge-rust-cron",
"frontend-solid": "nxtgauge-frontend-solid",
"admin-solid": "nxtgauge-admin-solid",
"ai-assistant": "nxtgauge-ai-assistant",
}
# Determine which kustomization file to update
if service_image_map.get(args.service):
image_name = service_image_map[args.service]
else:
image_name = f"nxtgauge-{args.service}"
# Find the right kustomization file based on service
if "frontend" in args.service:
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-frontend-solid/overlays/prod/kustomization.yaml")
if not os.path.exists(kustomization_path):
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-frontend-solid/base/kustomization.yaml")
elif "admin" in args.service:
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-admin-solid/overlays/prod/kustomization.yaml")
if not os.path.exists(kustomization_path):
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-admin-solid/base/kustomization.yaml")
elif "ai-assistant" in args.service:
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-ai-assistant/overlays/prod/kustomization.yaml")
if not os.path.exists(kustomization_path):
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-ai-assistant/base/kustomization.yaml")
else:
kustomization_path = os.path.join(args.repo, "apps/nxtgauge-backend-rust/overlays/prod/kustomization.yaml")
if not os.path.exists(kustomization_path):
print(f"[ERROR] Kustomization file not found: {kustomization_path}")
sys.exit(0) # Exit 0 per workflow requirement
print(f"Updating {kustomization_path} for service {args.service}")
if not update_kustomization(kustomization_path, args.service, args.sha):
sys.exit(0) # Exit 0 per workflow requirement
# Git add, commit, push
commit_msg = args.message or f"chore: deploy {args.service}@{args.sha}"
run(["git", "add", "-A"], cwd=args.repo)
code, stdout, stderr = run(["git", "diff", "--cached", "--stat"], cwd=args.repo)
if not stdout.strip():
print("[INFO] No changes to commit")
sys.exit(0)
print(f"Changes to commit:\n{stdout}")
run(["git", "commit", "-m", commit_msg], cwd=args.repo)
code, stdout, stderr = run(["git", "push"], cwd=args.repo)
if code != 0:
print(f"[ERROR] Push failed: {stderr}")
else:
print(f"[OK] Pushed update to gitops repo")
sys.exit(0) # Always exit 0 per workflow requirement
if __name__ == "__main__":
main()

View file

@ -1,4 +1,4 @@
name: build-and-push
name: build-and-release
on:
push:
@ -6,27 +6,56 @@ on:
- main
- high-performance
concurrency:
group: frontend-solid-build-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build and push
uses: docker://gcr.io/kaniko-project/executor:v1.23.2-debug
- 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_HOSTPORT: ${{ secrets.REGISTRY_HOSTPORT }}
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
IMAGE_NAME: nxtgauge-frontend-solid
LATEST_TAG: high-performance-latest
COMMIT_SHA: ${{ github.sha }}
with:
entrypoint: /busybox/sh
args: ${{ github.workspace }}/.forgejo/scripts/kaniko-build.sh
run: |
set -euo pipefail
test -n "$REGISTRY_HOSTPORT"
printf '%s' "$REGISTRY_PASSWORD" | docker login "$REGISTRY_HOSTPORT" -u "$REGISTRY_USERNAME" --password-stdin
- name: Prune old image tags (keep latest 1 SHA)
- name: Build and push image
env:
REGISTRY_HOSTPORT: ${{ secrets.REGISTRY_HOSTPORT }}
SHA: ${{ github.sha }}
run: |
set -euo pipefail
metadata_file="/tmp/frontend-solid-metadata.json"
image_ref="$REGISTRY_HOSTPORT/nxtgauge-frontend-solid:$SHA"
docker buildx build --push \
--metadata-file "$metadata_file" \
-f Dockerfile \
-t "$image_ref" \
.
digest="$(grep -o '"containerimage.digest":"sha256:[^"]*"' "$metadata_file" | cut -d'"' -f4)"
test -n "$digest"
printf '%s@%s\n' "$REGISTRY_HOSTPORT/nxtgauge-frontend-solid" "$digest" > /tmp/frontend-solid-image-ref.txt
- name: Prune old SHA tags
if: success()
continue-on-error: true
env:
@ -40,36 +69,37 @@ jobs:
--repo "nxtgauge-frontend-solid" \
--username "$REGISTRY_USERNAME" \
--password "$REGISTRY_PASSWORD" \
--keep 1
--keep 2
- name: Update GitOps and trigger deployment
if: success()
continue-on-error: true
- name: Update GitOps release
env:
GITEOPS_REPO: ${{ secrets.GITEOPS_REPO }}
GITEOPS_SSH_KEY: ${{ secrets.GITEOPS_SSH_KEY }}
SHA: ${{ github.sha }}
run: |
set -euo pipefail
SHA="$(git rev-parse HEAD)"
test -n "$GITEOPS_REPO"
test -n "$GITEOPS_SSH_KEY"
if [ -z "$GITEOPS_REPO" ]; then
echo "GITEOPS_REPO secret not set, skipping GitOps update"
exit 0
fi
mkdir -p ~/.ssh
printf '%s\n' "$GITEOPS_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
GITEOPS_DIR=$(mktemp -d)
git clone "$GITEOPS_REPO" "$GITEOPS_DIR"
cd "$GITEOPS_DIR"
mkdir -p ~/.ssh
echo "$GITEOPS_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
image_ref="$(cat /tmp/frontend-solid-image-ref.txt)"
./scripts/set-app-release.sh frontend-solid "$image_ref"
python3 .forgejo/scripts/update-gitops.py \
--repo "$GITEOPS_DIR" \
--service "frontend-solid" \
--sha "${SHA}" \
--message "chore: deploy frontend-solid@${SHA}"
if git diff --quiet; then
echo "GitOps repo already up to date."
exit 0
fi
rm -rf "$GITEOPS_DIR"
git config user.name "forgejo-actions[bot]"
git config user.email "forgejo-actions@ci.nxtgauge.com"
git add apps scripts/set-app-release.sh
git commit -m "chore(gitops): deploy frontend-solid@${SHA}"
git push