diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 06b3ef5..55b60d5 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -121,6 +121,17 @@ jobs:
mv fleetdm-stack-*.tgz .tmp/
ls -la .tmp/
+ - name: Build and push container image
+ run: |
+ TAG="${{ steps.version.outputs.new_tag }}"
+ IMAGE="git.produktor.io/${{ gitea.repository }}/fleetdm-stack"
+
+ echo "${{ gitea.token }}" | docker login git.produktor.io -u "${{ gitea.actor }}" --password-stdin
+ docker build -t "${IMAGE}:${TAG}" -t "${IMAGE}:latest" .
+ docker push "${IMAGE}:${TAG}"
+ docker push "${IMAGE}:latest"
+ echo "Pushed ${IMAGE}:${TAG}"
+
- name: Create tag
run: |
git config user.name "Gitea Actions"
diff --git a/.gitignore b/.gitignore
index 57ee6b1..e39bbed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ fleetdm-stack/charts/*.tgz
.helm/
*.log
/*-flamingo
+.idea
diff --git a/docs/architecture-design-company-inc.md b/docs/architecture-design-company-inc.md
index e742976..ad448cf 100644
--- a/docs/architecture-design-company-inc.md
+++ b/docs/architecture-design-company-inc.md
@@ -125,13 +125,55 @@ flowchart LR
**Cost impact:** Near-zero — both slots share the same node pool; the idle slot consumes minimal resources until traffic is switched. Argo Rollouts automates the full lifecycle within ArgoCD.
-### 4.5 Containerisation and CI/CD
+### 4.5 Containerisation Strategy
+
+#### Image Building Process
+
+Each service (Flask backend, React frontend) has its own **multi-stage Dockerfile**:
+
+1. **Build stage** — installs dependencies and compiles artefacts in a full SDK image (e.g. `python:3.12`, `node:20`).
+2. **Runtime stage** — copies only the built artefacts into a minimal base image (e.g. `python:3.12-slim`, `nginx:alpine`). This cuts image size by 60–80% and removes build tools from the attack surface.
+3. **Non-root user** — the runtime stage runs as a dedicated unprivileged user (`appuser`), never as root.
+4. **Reproducible builds** — dependency lock files (`requirements.txt` / `package-lock.json`) are copied and installed before application code to maximise Docker layer caching.
+
+**Tagging convention:** images are tagged with the **git SHA** for traceability and a `latest` alias for convenience. Semantic version tags (e.g. `v1.3.0`) are added on release.
+
+#### Container Registry Management
+
+All container images are stored in **GCP Artifact Registry** in the `company-inc-shared` project:
+
+- **Single source of truth** — one registry serves both staging and production via cross-project IAM pull permissions.
+- **Vulnerability scanning** — Artifact Registry's built-in scanning is enabled; CI fails if critical CVEs are detected.
+- **Image retention policy** — keep the latest 10 tagged images per service; automatically garbage-collect untagged manifests older than 30 days.
+- **Access control** — CI service account has `roles/artifactregistry.writer`; GKE node service accounts have `roles/artifactregistry.reader`. No human push access.
+
+*For self-hosted Git platforms (e.g. Gitea), the built-in OCI container registry can serve the same role at zero additional cost, with Trivy added as a CI step for vulnerability scanning.*
+
+#### Deployment Pipelines (CI/CD Integration)
+
+The pipeline follows a **GitOps** model with clear separation between CI and CD:
+
+| Phase | Tool | What happens |
+|-------|------|-------------|
+| **Lint & Test** | Gitea / GitHub Actions | Unit tests, linting, Helm lint on every push |
+| **Build & Push** | Gitea / GitHub Actions | `docker build` → tag with git SHA → push to registry |
+| **Security Scan** | Trivy (in CI) | Scan image for OS and library CVEs; block on critical findings |
+| **Manifest Update** | CI job | Update image tag in the GitOps manifests repo (or Helm values) |
+| **Sync & Deploy** | ArgoCD | Detects manifest drift → triggers blue-green rollout via Argo Rollouts |
+| **Promotion** | Argo Rollouts | Automated analysis (metrics, health checks) → promote or rollback |
+
+**Key properties:**
+- **CI never touches the cluster directly** — it only builds images and updates manifests. ArgoCD is the sole deployer.
+- **Rollback is instant** — revert the manifest repo to the previous commit; ArgoCD syncs automatically.
+- **Audit trail** — every deployment maps to a git commit in the manifests repo.
+
+### 4.6 CI/CD Summary
| Aspect | Approach |
|-------|----------|
-| **Image build** | Dockerfile per service; multi-stage builds; non-root user |
-| **Registry** | Artifact Registry in `company-inc-shared` |
-| **CI** | GitHub/Gitea Actions — build, test, security scan |
+| **Image build** | Multi-stage Dockerfile; layer caching; non-root; git-SHA tags |
+| **Registry** | Artifact Registry in `company-inc-shared` (or Gitea built-in OCI registry) |
+| **CI** | Gitea / GitHub Actions — lint, test, build, scan, push |
| **CD** | ArgoCD + Argo Rollouts — GitOps with blue-green strategy |
| **Secrets** | External Secrets Operator + GCP Secret Manager |
diff --git a/docs/architecture-hld.md b/docs/architecture-hld.md
index 0ddba03..f1066a5 100644
--- a/docs/architecture-hld.md
+++ b/docs/architecture-hld.md
@@ -94,10 +94,12 @@ flowchart LR
flowchart LR
Dev[Developer] -->|push| Repo[Git Repo]
Repo -->|webhook| CI[CI Pipeline
lint · test · build]
- CI -->|push image| Registry[Artifact Registry]
+ CI -->|docker build + push| Registry[Container Registry
Artifact Registry / Gitea OCI]
+ CI -->|scan image| Trivy[Trivy
CVE scan]
CI -->|update manifests| GitOps[GitOps Repo]
GitOps -->|sync| Argo[ArgoCD]
Argo -->|blue-green deploy| GKE[GKE Cluster]
+ GKE -->|pull image| Registry
```
## Network Security Layers