Skip to content

Commit c8f3c01

Browse files
committed
Enhance Dockerfile and Build Workflow
- Added verification for the existence of package-lock.json in both the build-and-push workflow and Dockerfile, ensuring reproducible builds. - Implemented retry logic for npm ci commands in the Dockerfile to improve reliability during dependency installation. - Added checks to verify critical dependencies are present in the built Docker image, enhancing the robustness of the build process.
1 parent f18497c commit c8f3c01

2 files changed

Lines changed: 105 additions & 7 deletions

File tree

.github/workflows/build-and-push.yml

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,72 @@ jobs:
4848
- name: Set up Docker Buildx
4949
uses: docker/setup-buildx-action@v2
5050

51+
- name: Verify package-lock.json exists
52+
run: |
53+
if [ ! -f backend/package-lock.json ]; then
54+
echo "❌ ERROR: package-lock.json is missing!"
55+
echo " This file is required for reproducible builds."
56+
echo " Please commit it: git add backend/package-lock.json && git commit -m 'Add package-lock.json'"
57+
exit 1
58+
fi
59+
echo "✅ package-lock.json found"
60+
5161
- name: Build and push image
62+
id: build
5263
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..."
5368
docker buildx build \
5469
--platform linux/amd64 \
5570
-f ${{ steps.extract.outputs.DOCKERFILE }} \
5671
--build-arg VERSION=${{ steps.extract.outputs.VERSION }} \
57-
-t ${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/github-scraper/${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.VERSION }} \
58-
-t ${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/github-scraper/${{ steps.extract.outputs.SERVICE }}:latest \
72+
--cache-from type=registry,ref=${IMAGE_TAG} \
73+
--cache-from type=registry,ref=${LATEST_TAG} \
74+
-t ${IMAGE_TAG} \
75+
-t ${LATEST_TAG} \
5976
--push \
77+
--provenance=false \
78+
--sbom=false \
6079
./backend
61-
echo "✅ Image built and pushed: ${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.VERSION }}"
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
112+
fi
113+
echo "✅ Dependencies verified: node_modules, prisma, fastify all present"
114+
115+
echo "✅ Image verification passed"
116+
echo "✅ Image ready: ${{ steps.extract.outputs.SERVICE }}:${{ steps.extract.outputs.VERSION }}"
62117
echo " Version injected via build arg: ${{ steps.extract.outputs.VERSION }}"
63118
64119
- name: Cleanup old images

backend/Dockerfile.prod

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,25 @@ COPY prisma ./prisma/
1515
COPY tsconfig.json ./
1616

1717
# Install all dependencies (including dev dependencies for building)
18-
# Retry npm ci up to 3 times on failure
19-
RUN for i in 1 2 3; do npm ci && break || sleep 10; done
18+
# Verify package-lock.json exists, then retry npm ci up to 3 times on failure
19+
RUN if [ ! -f package-lock.json ]; then \
20+
echo "❌ ERROR: package-lock.json is missing! It must be committed to git."; \
21+
echo " Run: git add backend/package-lock.json && git commit -m 'Add package-lock.json'"; \
22+
exit 1; \
23+
fi && \
24+
for i in 1 2 3; do \
25+
if npm ci; then \
26+
echo "✅ Dependencies installed successfully (attempt $i)"; \
27+
break; \
28+
else \
29+
echo "⚠️ npm ci failed (attempt $i/3), retrying..."; \
30+
if [ $i -eq 3 ]; then \
31+
echo "❌ ERROR: npm ci failed after 3 attempts"; \
32+
exit 1; \
33+
fi; \
34+
sleep 10; \
35+
fi; \
36+
done
2037

2138
# Copy application code
2239
COPY src ./src
@@ -48,8 +65,34 @@ COPY package*.json ./
4865
COPY prisma ./prisma/
4966

5067
# Install only production dependencies
51-
# Retry npm ci up to 3 times on failure
52-
RUN for i in 1 2 3; do npm ci --omit=dev && break || sleep 10; done
68+
# Verify package-lock.json exists, then retry npm ci up to 3 times on failure
69+
RUN if [ ! -f package-lock.json ]; then \
70+
echo "❌ ERROR: package-lock.json is missing! It must be committed to git."; \
71+
echo " Run: git add backend/package-lock.json && git commit -m 'Add package-lock.json'"; \
72+
exit 1; \
73+
fi && \
74+
for i in 1 2 3; do \
75+
if npm ci --omit=dev; then \
76+
echo "✅ Production dependencies installed successfully (attempt $i)"; \
77+
break; \
78+
else \
79+
echo "⚠️ npm ci failed (attempt $i/3), retrying..."; \
80+
if [ $i -eq 3 ]; then \
81+
echo "❌ ERROR: npm ci failed after 3 attempts"; \
82+
exit 1; \
83+
fi; \
84+
sleep 10; \
85+
fi; \
86+
done && \
87+
# Verify critical dependencies are installed
88+
if [ ! -d "node_modules" ] || [ ! -f "node_modules/.bin/prisma" ] || [ ! -d "node_modules/fastify" ]; then \
89+
echo "❌ ERROR: Critical dependencies missing after installation"; \
90+
echo " node_modules exists: $([ -d node_modules ] && echo yes || echo no)"; \
91+
echo " prisma binary exists: $([ -f node_modules/.bin/prisma ] && echo yes || echo no)"; \
92+
echo " fastify exists: $([ -d node_modules/fastify ] && echo yes || echo no)"; \
93+
exit 1; \
94+
fi && \
95+
echo "✅ Verified: node_modules, prisma, and fastify are present"
5396

5497
# Copy built files from builder
5598
COPY --from=builder /app/dist ./dist

0 commit comments

Comments
 (0)