Skip to content

Commit ee825a7

Browse files
committed
passing nginx.conf vals as part of deploy, + pre-built backend/frontend containers
1 parent b25f493 commit ee825a7

File tree

9 files changed

+335
-47
lines changed

9 files changed

+335
-47
lines changed

.github/workflows/docker.yml

Lines changed: 165 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,182 @@
1-
name: Docker Build & Scan
1+
name: Docker Build, Scan & Publish
22

33
on:
44
push:
5-
branches: [ main, dev ]
5+
branches: [ main ]
6+
tags: [ 'v*' ]
67
pull_request:
7-
branches: [ main, dev ]
8+
branches: [ main ]
89
workflow_dispatch:
910

11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_PREFIX: ${{ github.repository_owner }}/integr8scode
14+
1015
jobs:
11-
docker:
12-
name: Docker Build & Scan
16+
build-and-scan:
17+
name: Build & Scan
1318
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write
22+
security-events: write
23+
24+
outputs:
25+
backend_tag: ${{ steps.meta-backend.outputs.tags }}
26+
frontend_tag: ${{ steps.meta-frontend.outputs.tags }}
27+
1428
steps:
1529
- uses: actions/checkout@v4
30+
31+
- name: Set up Docker Buildx
32+
uses: docker/setup-buildx-action@v3
33+
34+
- name: Log in to GitHub Container Registry
35+
if: github.event_name != 'pull_request'
36+
uses: docker/login-action@v3
37+
with:
38+
registry: ${{ env.REGISTRY }}
39+
username: ${{ github.actor }}
40+
password: ${{ secrets.GITHUB_TOKEN }}
41+
42+
# =========================================================================
43+
# BASE IMAGE
44+
# =========================================================================
45+
- name: Extract metadata for base image
46+
id: meta-base
47+
uses: docker/metadata-action@v5
48+
with:
49+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/base
50+
tags: |
51+
type=ref,event=branch
52+
type=ref,event=pr
53+
type=semver,pattern={{version}}
54+
type=semver,pattern={{major}}.{{minor}}
55+
type=sha,prefix=sha-
56+
type=raw,value=latest,enable={{is_default_branch}}
57+
1658
- name: Build base image
17-
run: |
18-
docker build -f ./backend/Dockerfile.base -t integr8scode-base:latest ./backend
59+
uses: docker/build-push-action@v5
60+
with:
61+
context: ./backend
62+
file: ./backend/Dockerfile.base
63+
push: ${{ github.event_name != 'pull_request' }}
64+
tags: ${{ steps.meta-base.outputs.tags }}
65+
labels: ${{ steps.meta-base.outputs.labels }}
66+
cache-from: type=gha
67+
cache-to: type=gha,mode=max
68+
# Also build locally for dependent images
69+
load: true
1970

20-
- name: Build Docker image
21-
run: |
22-
DOCKER_BUILDKIT=1 docker build \
23-
--build-context base=docker-image://integr8scode-base:latest \
24-
-t integr8scode:test \
25-
./backend
26-
- name: Run Trivy vulnerability scanner
71+
# =========================================================================
72+
# BACKEND IMAGE
73+
# =========================================================================
74+
- name: Extract metadata for backend image
75+
id: meta-backend
76+
uses: docker/metadata-action@v5
77+
with:
78+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend
79+
tags: |
80+
type=ref,event=branch
81+
type=ref,event=pr
82+
type=semver,pattern={{version}}
83+
type=semver,pattern={{major}}.{{minor}}
84+
type=sha,prefix=sha-
85+
type=raw,value=latest,enable={{is_default_branch}}
86+
87+
- name: Build backend image
88+
uses: docker/build-push-action@v5
89+
with:
90+
context: ./backend
91+
file: ./backend/Dockerfile
92+
push: ${{ github.event_name != 'pull_request' }}
93+
tags: ${{ steps.meta-backend.outputs.tags }}
94+
labels: ${{ steps.meta-backend.outputs.labels }}
95+
cache-from: type=gha
96+
cache-to: type=gha,mode=max
97+
build-contexts: |
98+
base=docker-image://${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/base:${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || 'latest' }}
99+
load: true
100+
101+
- name: Run Trivy vulnerability scanner on backend
27102
uses: aquasecurity/trivy-action@master
28103
with:
29-
image-ref: 'integr8scode:test'
30-
format: 'table'
31-
exit-code: '1'
104+
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend:${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || 'latest' }}
105+
format: 'sarif'
106+
output: 'trivy-backend-results.sarif'
32107
ignore-unfixed: true
33108
severity: 'CRITICAL,HIGH'
34109
timeout: '5m0s'
35-
trivyignores: 'backend/.trivyignore'
110+
trivyignores: 'backend/.trivyignore'
111+
112+
- name: Upload Trivy scan results to GitHub Security
113+
if: always()
114+
uses: github/codeql-action/upload-sarif@v3
115+
with:
116+
sarif_file: 'trivy-backend-results.sarif'
117+
category: 'trivy-backend'
118+
119+
# =========================================================================
120+
# FRONTEND IMAGE
121+
# =========================================================================
122+
- name: Extract metadata for frontend image
123+
id: meta-frontend
124+
uses: docker/metadata-action@v5
125+
with:
126+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/frontend
127+
tags: |
128+
type=ref,event=branch
129+
type=ref,event=pr
130+
type=semver,pattern={{version}}
131+
type=semver,pattern={{major}}.{{minor}}
132+
type=sha,prefix=sha-
133+
type=raw,value=latest,enable={{is_default_branch}}
134+
135+
- name: Build frontend image
136+
uses: docker/build-push-action@v5
137+
with:
138+
context: ./frontend
139+
file: ./frontend/Dockerfile.prod
140+
push: ${{ github.event_name != 'pull_request' }}
141+
tags: ${{ steps.meta-frontend.outputs.tags }}
142+
labels: ${{ steps.meta-frontend.outputs.labels }}
143+
cache-from: type=gha
144+
cache-to: type=gha,mode=max
145+
load: true
146+
147+
- name: Run Trivy vulnerability scanner on frontend
148+
uses: aquasecurity/trivy-action@master
149+
with:
150+
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/frontend:${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || 'latest' }}
151+
format: 'sarif'
152+
output: 'trivy-frontend-results.sarif'
153+
ignore-unfixed: true
154+
severity: 'CRITICAL,HIGH'
155+
timeout: '5m0s'
156+
157+
- name: Upload Trivy frontend scan results
158+
if: always()
159+
uses: github/codeql-action/upload-sarif@v3
160+
with:
161+
sarif_file: 'trivy-frontend-results.sarif'
162+
category: 'trivy-frontend'
163+
164+
# =========================================================================
165+
# SUMMARY
166+
# =========================================================================
167+
- name: Summary
168+
if: github.event_name != 'pull_request'
169+
run: |
170+
echo "## Docker Images Published" >> $GITHUB_STEP_SUMMARY
171+
echo "" >> $GITHUB_STEP_SUMMARY
172+
echo "| Image | Tags |" >> $GITHUB_STEP_SUMMARY
173+
echo "|-------|------|" >> $GITHUB_STEP_SUMMARY
174+
echo "| Base | \`${{ steps.meta-base.outputs.tags }}\` |" >> $GITHUB_STEP_SUMMARY
175+
echo "| Backend | \`${{ steps.meta-backend.outputs.tags }}\` |" >> $GITHUB_STEP_SUMMARY
176+
echo "| Frontend | \`${{ steps.meta-frontend.outputs.tags }}\` |" >> $GITHUB_STEP_SUMMARY
177+
echo "" >> $GITHUB_STEP_SUMMARY
178+
echo "### Usage" >> $GITHUB_STEP_SUMMARY
179+
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
180+
echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend:latest" >> $GITHUB_STEP_SUMMARY
181+
echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/frontend:latest" >> $GITHUB_STEP_SUMMARY
182+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

deploy.sh

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
# ./deploy.sh dev # Start local development (docker-compose)
88
# ./deploy.sh dev --build # Rebuild and start local development
99
# ./deploy.sh down # Stop local development
10-
# ./deploy.sh prod # Deploy to K8s with Helm (production values)
10+
# ./deploy.sh prod # Deploy to K8s (builds images locally)
11+
# ./deploy.sh prod --prod # Deploy with production values (uses registry)
1112
# ./deploy.sh prod --dry-run # Test Helm deployment without applying
12-
# ./deploy.sh staging # Deploy to K8s with Helm (default values)
1313
# ./deploy.sh check # Run local quality checks (lint, type, security)
1414
# ./deploy.sh test # Run full test suite locally
1515
# ./deploy.sh logs [service] # View logs (dev mode)
@@ -55,18 +55,27 @@ show_help() {
5555
echo "Commands:"
5656
echo " dev [--build] Start local development environment (docker-compose)"
5757
echo " down Stop local development environment"
58-
echo " prod [--dry-run] Deploy to Kubernetes with Helm"
58+
echo " prod [options] Deploy to Kubernetes with Helm"
5959
echo " check Run quality checks (ruff, mypy, bandit)"
6060
echo " test Run full test suite with docker-compose"
6161
echo " logs [service] View logs (defaults to all services)"
6262
echo " status Show status of running services"
6363
echo " help Show this help message"
6464
echo ""
65+
echo "Prod options:"
66+
echo " --dry-run Validate templates without applying"
67+
echo " --prod Use production values (ghcr.io images, no local build)"
68+
echo " --local Force local build even with --prod values"
69+
echo " --set key=value Override Helm values"
70+
echo ""
6571
echo "Examples:"
66-
echo " ./deploy.sh dev # Start dev environment (auto-seeds users)"
67-
echo " ./deploy.sh dev --build # Rebuild and start"
68-
echo " ./deploy.sh prod # Deploy to K8s (requires password args)"
69-
echo " ./deploy.sh logs backend # View backend logs"
72+
echo " ./deploy.sh dev # Start dev environment"
73+
echo " ./deploy.sh dev --build # Rebuild and start"
74+
echo " ./deploy.sh prod # Deploy with local images"
75+
echo " ./deploy.sh prod --prod # Deploy with registry images (no build)"
76+
echo " ./deploy.sh prod --prod --local # Deploy prod values but build locally"
77+
echo " ./deploy.sh prod --set mongodb.auth.rootPassword=secret"
78+
echo " ./deploy.sh logs backend # View backend logs"
7079
}
7180

7281
# =============================================================================
@@ -237,6 +246,8 @@ cmd_prod() {
237246
local DRY_RUN=""
238247
local VALUES_FILE="values.yaml"
239248
local EXTRA_ARGS=""
249+
local USE_REGISTRY=false
250+
local FORCE_LOCAL=false
240251

241252
# Parse arguments
242253
while [[ $# -gt 0 ]]; do
@@ -247,7 +258,12 @@ cmd_prod() {
247258
;;
248259
--prod)
249260
VALUES_FILE="values-prod.yaml"
250-
print_info "Using production values"
261+
USE_REGISTRY=true
262+
print_info "Using production values (ghcr.io images)"
263+
;;
264+
--local)
265+
FORCE_LOCAL=true
266+
print_info "Forcing local image build"
251267
;;
252268
--set)
253269
shift
@@ -261,17 +277,25 @@ cmd_prod() {
261277
shift
262278
done
263279

264-
deploy_helm "$VALUES_FILE" "$DRY_RUN" "$EXTRA_ARGS"
280+
deploy_helm "$VALUES_FILE" "$DRY_RUN" "$EXTRA_ARGS" "$USE_REGISTRY" "$FORCE_LOCAL"
265281
}
266282

267283
deploy_helm() {
268284
local VALUES_FILE="$1"
269285
local DRY_RUN="$2"
270286
local EXTRA_ARGS="$3"
287+
local USE_REGISTRY="$4"
288+
local FORCE_LOCAL="$5"
271289

272-
# Build images (skip for dry-run)
290+
# Build images if:
291+
# - Not dry-run AND
292+
# - Not using registry OR force local build
273293
if [[ -z "$DRY_RUN" ]]; then
274-
build_and_import_images
294+
if [[ "$USE_REGISTRY" != "true" ]] || [[ "$FORCE_LOCAL" == "true" ]]; then
295+
build_and_import_images
296+
else
297+
print_info "Using pre-built images from ghcr.io (skipping local build)"
298+
fi
275299
fi
276300

277301
print_info "Updating Helm dependencies..."
@@ -301,7 +325,11 @@ deploy_helm() {
301325
echo "Services:"
302326
kubectl get services -n "$NAMESPACE"
303327
echo ""
304-
echo "Default credentials: user/user123, admin/admin123"
328+
if [[ "$VALUES_FILE" == "values-prod.yaml" ]]; then
329+
echo "Note: Passwords must be set via --set flags for production"
330+
else
331+
echo "Default credentials: user/user123, admin/admin123"
332+
fi
305333
echo ""
306334
echo "Commands:"
307335
echo " kubectl logs -n $NAMESPACE -l app.kubernetes.io/component=backend"

docs/operations/deployment.md

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ variables like `KAFKA_PORT=tcp://...` override the expected numeric values. The
264264
### Image pull failures
265265

266266
If pods stay in ImagePullBackOff, the images aren't available to the cluster. For K3s, the deploy script imports images
267-
automatically. For other distributions, push images to your registry and update `values.yaml` with the correct
268-
repository and tag.
267+
automatically. For other distributions, use the pre-built images from GitHub Container Registry (see below) or push to
268+
your own registry and update `values.yaml` with the correct repository and tag.
269269

270270
```yaml
271271
images:
@@ -301,3 +301,57 @@ workers:
301301
```
302302

303303
Monitor resource usage with kubectl top or your cluster's metrics solution to right-size the limits.
304+
305+
## Pre-built images
306+
307+
For production deployments, you can skip the local build step entirely by using pre-built images from GitHub Container
308+
Registry. The CI pipeline automatically builds and pushes images on every merge to main.
309+
310+
### Using registry images
311+
312+
The `--prod` flag configures the deployment to pull images from `ghcr.io/hardmax71/integr8scode/`:
313+
314+
```bash
315+
./deploy.sh prod --prod \
316+
--set userSeed.defaultUserPassword=secure-pass \
317+
--set userSeed.adminUserPassword=secure-admin
318+
```
319+
320+
This skips the local Docker build and tells Kubernetes to pull images from the registry. The `values-prod.yaml` file
321+
sets `imagePullPolicy: IfNotPresent`, so images are cached locally after the first pull.
322+
323+
### Available tags
324+
325+
Each push to main produces multiple tags:
326+
327+
| Tag | Description |
328+
|---------------|------------------------------------|
329+
| `latest` | Most recent build from main branch |
330+
| `sha-abc1234` | Specific commit SHA |
331+
| `v1.0.0` | Release version (from git tags) |
332+
333+
For production, pin to a specific SHA or version rather than `latest`:
334+
335+
```yaml
336+
images:
337+
backend:
338+
repository: ghcr.io/hardmax71/integr8scode/backend
339+
tag: sha-abc1234
340+
```
341+
342+
### Hybrid approach
343+
344+
If you need production resource limits but want to build locally (for testing changes before pushing):
345+
346+
```bash
347+
./deploy.sh prod --prod --local
348+
```
349+
350+
The `--local` flag forces a local build even when using `values-prod.yaml`.
351+
352+
### CI/CD integration
353+
354+
The GitHub Actions workflow in `.github/workflows/docker.yml` handles image building and publishing. On every push to
355+
main, it builds the base, backend, and frontend images, scans them with Trivy for vulnerabilities, and pushes to
356+
ghcr.io.
357+
Pull requests build and scan but don't push, ensuring only tested code reaches the registry.

0 commit comments

Comments
 (0)