@@ -18,18 +18,23 @@ jobs:
1818 run : |
1919 TAG=${GITHUB_REF#refs/tags/}
2020 # Extract service name and version from tag
21- # api-v1.2.3 -> service=api, version=1.2.3
21+ # api-v1.2.3 -> service=api, version=1.2.3 (builds all services)
22+ # commit-worker-v1.2.3 -> service=commit-worker, version=1.2.3
23+ # user-worker-v1.2.3 -> service=user-worker, version=1.2.3
2224 if [[ $TAG =~ ^api-v(.+)$ ]]; then
2325 echo "SERVICE=api" >> $GITHUB_OUTPUT
2426 echo "VERSION=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
27+ echo "BUILD_ALL=true" >> $GITHUB_OUTPUT
2528 echo "DOCKERFILE=backend/Dockerfile.prod" >> $GITHUB_OUTPUT
2629 elif [[ $TAG =~ ^commit-worker-v(.+)$ ]]; then
2730 echo "SERVICE=commit-worker" >> $GITHUB_OUTPUT
2831 echo "VERSION=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
32+ echo "BUILD_ALL=false" >> $GITHUB_OUTPUT
2933 echo "DOCKERFILE=backend/Dockerfile.cloudrun-commit-worker" >> $GITHUB_OUTPUT
3034 elif [[ $TAG =~ ^user-worker-v(.+)$ ]]; then
3135 echo "SERVICE=user-worker" >> $GITHUB_OUTPUT
3236 echo "VERSION=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
37+ echo "BUILD_ALL=false" >> $GITHUB_OUTPUT
3338 echo "DOCKERFILE=backend/Dockerfile.cloudrun-user-worker" >> $GITHUB_OUTPUT
3439 else
3540 echo "❌ Error: Invalid tag format"
@@ -58,85 +63,148 @@ jobs:
5863 fi
5964 echo "✅ package-lock.json found"
6065
61- - name : Build and push image
66+ - name : Build and push images
6267 id : build
6368 run : |
64- IMAGE_TAG=${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/github-scraper/${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.VERSION }}
65- LATEST_TAG=${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/github-scraper/${{ steps.extract.outputs.SERVICE }}:latest
66-
67- echo "🔨 Building image..."
68- docker buildx build \
69- --platform linux/amd64 \
70- -f ${{ steps.extract.outputs.DOCKERFILE }} \
71- --build-arg VERSION=${{ steps.extract.outputs.VERSION }} \
72- --cache-from type=registry,ref=${IMAGE_TAG} \
73- --cache-from type=registry,ref=${LATEST_TAG} \
74- -t ${IMAGE_TAG} \
75- -t ${LATEST_TAG} \
76- --push \
77- --provenance=false \
78- --sbom=false \
79- ./backend
80-
81- echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_OUTPUT
82- echo "LATEST_TAG=${LATEST_TAG}" >> $GITHUB_OUTPUT
83- echo "✅ Image built and pushed successfully"
84-
85- - name : Verify image in registry
86- run : |
87- IMAGE_TAG="${{ steps.build.outputs.IMAGE_TAG }}"
88- EXPECTED_VERSION="${{ steps.extract.outputs.VERSION }}"
89-
90- echo "🔍 Verifying image in registry..."
91-
92- # Pull and verify APP_VERSION
93- docker pull ${IMAGE_TAG}
94-
95- # Verify APP_VERSION is set
96- APP_VERSION=$(docker inspect ${IMAGE_TAG} --format='{{range .Config.Env}}{{println .}}{{end}}' | grep "^APP_VERSION=" | cut -d= -f2 || echo "")
97-
98- if [ "$APP_VERSION" != "$EXPECTED_VERSION" ]; then
99- echo "❌ ERROR: APP_VERSION mismatch!"
100- echo " Expected: ${EXPECTED_VERSION}"
101- echo " Found: ${APP_VERSION:-not set}"
102- exit 1
103- fi
104- echo "✅ APP_VERSION verified: ${APP_VERSION}"
105-
106- # Verify node_modules exists (quick check)
107- if ! docker run --rm --platform linux/amd64 --entrypoint /bin/sh ${IMAGE_TAG} -c "test -d /app/node_modules && test -f /app/node_modules/.bin/prisma && test -d /app/node_modules/fastify" 2>/dev/null; then
108- echo "❌ ERROR: Critical dependencies missing in image!"
109- echo " Checking what's in /app:"
110- docker run --rm --platform linux/amd64 --entrypoint /bin/sh ${IMAGE_TAG} -c "ls -la /app" || true
111- exit 1
69+ VERSION="${{ steps.extract.outputs.VERSION }}"
70+ BUILD_ALL="${{ steps.extract.outputs.BUILD_ALL }}"
71+ REGISTRY=${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/github-scraper
72+
73+ # Define all services to build
74+ if [ "$BUILD_ALL" = "true" ]; then
75+ # Build all services when API tag is pushed
76+ SERVICES=("api:backend/Dockerfile.prod" "commit-worker:backend/Dockerfile.cloudrun-commit-worker" "user-worker:backend/Dockerfile.cloudrun-user-worker")
77+ echo "🔨 Building all services (API, Commit Worker, User Worker) with version ${VERSION}..."
78+ else
79+ # Build only the specific service
80+ SERVICES=("${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.DOCKERFILE }}")
81+ echo "🔨 Building ${{ steps.extract.outputs.SERVICE }} with version ${VERSION}..."
11282 fi
113- echo "✅ Dependencies verified: node_modules, prisma, fastify all present"
11483
115- echo "✅ Image verification passed"
116- echo "✅ Image ready: ${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.VERSION }}"
117- echo " Version injected via build arg: ${{ steps.extract.outputs.VERSION }}"
84+ BUILT_SERVICES=()
85+
86+ # Build each service
87+ for SERVICE_CONFIG in "${SERVICES[@]}"; do
88+ SERVICE_NAME=$(echo $SERVICE_CONFIG | cut -d: -f1)
89+ DOCKERFILE=$(echo $SERVICE_CONFIG | cut -d: -f2)
90+ IMAGE_TAG=${REGISTRY}/${SERVICE_NAME}:${VERSION}
91+ LATEST_TAG=${REGISTRY}/${SERVICE_NAME}:latest
92+
93+ echo ""
94+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
95+ echo "📦 Building ${SERVICE_NAME}:${VERSION}"
96+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
97+
98+ docker buildx build \
99+ --platform linux/amd64 \
100+ -f ${DOCKERFILE} \
101+ --build-arg VERSION=${VERSION} \
102+ --cache-from type=registry,ref=${IMAGE_TAG} \
103+ --cache-from type=registry,ref=${LATEST_TAG} \
104+ -t ${IMAGE_TAG} \
105+ -t ${LATEST_TAG} \
106+ --push \
107+ --provenance=false \
108+ --sbom=false \
109+ ./backend
110+
111+ BUILT_SERVICES+=("${SERVICE_NAME}")
112+ echo "✅ ${SERVICE_NAME}:${VERSION} built and pushed"
113+ done
114+
115+ # Output built services as JSON array for later steps
116+ echo "BUILT_SERVICES=$(IFS=','; echo "${BUILT_SERVICES[*]}")" >> $GITHUB_OUTPUT
117+ echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
118+ echo ""
119+ echo "✅ All images built and pushed successfully"
120+
121+ - name : Verify images in registry
122+ run : |
123+ REGISTRY=${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/github-scraper
124+ EXPECTED_VERSION="${{ steps.build.outputs.VERSION }}"
125+ BUILT_SERVICES="${{ steps.build.outputs.BUILT_SERVICES }}"
126+
127+ echo "🔍 Verifying images in registry..."
128+ echo ""
129+
130+ # Convert comma-separated string to array
131+ IFS=',' read -ra SERVICES <<< "$BUILT_SERVICES"
132+
133+ for SERVICE_NAME in "${SERVICES[@]}"; do
134+ IMAGE_TAG=${REGISTRY}/${SERVICE_NAME}:${EXPECTED_VERSION}
135+
136+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
137+ echo "🔍 Verifying ${SERVICE_NAME}:${EXPECTED_VERSION}"
138+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
139+
140+ # Pull and verify APP_VERSION
141+ docker pull ${IMAGE_TAG}
142+
143+ # Verify APP_VERSION is set
144+ APP_VERSION=$(docker inspect ${IMAGE_TAG} --format='{{range .Config.Env}}{{println .}}{{end}}' | grep "^APP_VERSION=" | cut -d= -f2 || echo "")
145+
146+ if [ "$APP_VERSION" != "$EXPECTED_VERSION" ]; then
147+ echo "❌ ERROR: APP_VERSION mismatch for ${SERVICE_NAME}!"
148+ echo " Expected: ${EXPECTED_VERSION}"
149+ echo " Found: ${APP_VERSION:-not set}"
150+ exit 1
151+ fi
152+ echo "✅ APP_VERSION verified: ${APP_VERSION}"
153+
154+ # Verify node_modules exists (quick check)
155+ if ! docker run --rm --platform linux/amd64 --entrypoint /bin/sh ${IMAGE_TAG} -c "test -d /app/node_modules && test -f /app/node_modules/.bin/prisma" 2>/dev/null; then
156+ echo "❌ ERROR: Critical dependencies missing in ${SERVICE_NAME} image!"
157+ echo " Checking what's in /app:"
158+ docker run --rm --platform linux/amd64 --entrypoint /bin/sh ${IMAGE_TAG} -c "ls -la /app" || true
159+ exit 1
160+ fi
161+ echo "✅ Dependencies verified: node_modules, prisma present"
162+ echo ""
163+ done
164+
165+ echo "✅ All images verified successfully"
118166
119167 - name : Cleanup old images
120168 if : success() # Only run if build succeeded
121169 run : |
122- # Cleanup old images (keeps last 3 versions + latest + deployed version)
170+ # Cleanup old images for all built services
123171 export PROJECT_ID=${{ secrets.PROJECT_ID }}
124172 export REGION=${{ secrets.GCP_REGION }}
125173 export REPOSITORY=github-scraper
126- ./scripts/utils/cleanup-old-images.sh ${{ steps.extract.outputs.SERVICE }} --execute
174+ BUILT_SERVICES="${{ steps.build.outputs.BUILT_SERVICES }}"
175+
176+ # Convert comma-separated string to array
177+ IFS=',' read -ra SERVICES <<< "$BUILT_SERVICES"
178+
179+ for SERVICE_NAME in "${SERVICES[@]}"; do
180+ echo "🧹 Cleaning up old images for ${SERVICE_NAME}..."
181+ ./scripts/utils/cleanup-old-images.sh ${SERVICE_NAME} --execute || echo "⚠️ Cleanup failed for ${SERVICE_NAME}, continuing..."
182+ done
127183 continue-on-error : true # Don't fail workflow if cleanup fails
128184
129- - name : Trigger deployment in infra repo
185+ - name : Trigger deployments in infra repo
130186 run : |
131- # Automatically trigger deployment in infra repo (Option C)
132- curl -X POST https://api.github.com/repos/aalexmrt/github-scraper-infra/dispatches \
133- -H "Authorization: token ${{ secrets.DEPLOY_TOKEN }}" \
134- -H "Accept: application/vnd.github.v3+json" \
135- -d '{
136- "event_type":"deploy",
137- "client_payload":{
138- "service":"${{ steps.extract.outputs.SERVICE }}",
139- "version":"${{ steps.extract.outputs.VERSION }}"
140- }
141- }'
142- echo "✅ Deployment triggered for ${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.VERSION }}"
187+ # Automatically trigger deployment in infra repo for all built services
188+ BUILT_SERVICES="${{ steps.build.outputs.BUILT_SERVICES }}"
189+ VERSION="${{ steps.build.outputs.VERSION }}"
190+
191+ # Convert comma-separated string to array
192+ IFS=',' read -ra SERVICES <<< "$BUILT_SERVICES"
193+
194+ for SERVICE_NAME in "${SERVICES[@]}"; do
195+ echo "🚀 Triggering deployment for ${SERVICE_NAME}:${VERSION}..."
196+ curl -X POST https://api.github.com/repos/aalexmrt/github-scraper-infra/dispatches \
197+ -H "Authorization: token ${{ secrets.DEPLOY_TOKEN }}" \
198+ -H "Accept: application/vnd.github.v3+json" \
199+ -d "{
200+ \"event_type\":\"deploy\",
201+ \"client_payload\":{
202+ \"service\":\"${SERVICE_NAME}\",
203+ \"version\":\"${VERSION}\"
204+ }
205+ }"
206+ echo "✅ Deployment triggered for ${SERVICE_NAME}:${VERSION}"
207+ done
208+
209+ echo ""
210+ echo "✅ All deployments triggered successfully"
0 commit comments