> ## Documentation Index
> Fetch the complete documentation index at: https://kubestarterkit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CI/CD Pipelines

> Automated container builds and staging deployments on every merge to main

## Overview

The CI/CD pipeline automates container builds and deployments via GitHub Actions:

* **Change detection:** Only builds applications that have changed, keeping CI fast in a monorepo
* **Consistent builds:** All containers are built in CI with the same environment and tooling
* **Rendered manifests:** Kubernetes manifests are rendered and committed to Git, so what's in the repository is exactly what ArgoCD deploys
* **Automatic staging deployment:** Merges to main trigger builds and deploy to staging automatically

## What's Included

### Workflow Structure

```
.github/workflows/
├── ci-build-push-containers.yml # Build and push container images
├── ci-test.yml                  # Run tests (placeholder)
├── gitops-update-manifests.yml  # Render and commit K8s manifests
└── terramate-*.yml              # Terraform orchestration
```

Terraform CI/CD workflows (preview, deploy, drift detection) are covered in [Terraform Orchestration](/features/02-terramate#github-actions-workflows).

### Change Detection

The workflow uses [dorny/paths-filter](https://github.com/dorny/paths-filter) with a separate filter configuration file:

```yaml theme={null}
# .github/utils/file-filters.yaml
services/go-backend:
  - "services/go-backend/**"
  - "kubernetes/src/services/go-backend/**"

services/another-service:
  - "services/another-service/**"
  - "kubernetes/src/services/another-service/**"
```

The workflow matrix builds only the services that match changed paths. Changes to shared dependencies (like the workflow itself) trigger rebuilds of all dependent services.

### Build and Deploy Process

<Steps>
  <Step title="Detect changes [ci-build-push]">
    Determines which services have modifications based on path filters.
  </Step>

  <Step title="Build containers [ci-build-push]">
    Builds and pushes a container image to ECR for each changed service.
  </Step>

  <Step title="Trigger deploy [ci-build-push]">
    Triggers `gitops-update-manifests` for each built service.
  </Step>

  <Step title="Render manifests [gitops-update-manifests]">
    Generates Kubernetes manifests with the new image tags.
  </Step>

  <Step title="Commit manifests [gitops-update-manifests]">
    Pushes the updated manifests to the repository.
  </Step>

  <Step title="ArgoCD syncs">
    Detects the manifest changes via webhook or polling and deploys automatically.
  </Step>
</Steps>

### Container Registry

Images are pushed to Amazon ECR with version tags derived from `git describe`:

```
<account>.dkr.ecr.<region>.amazonaws.com/go-backend:1.2.3-0001-g4b5d2e7
```

The tag format `<version>-<commits>-g<hash>` shows the base version from the last release tag, how many commits since that release, and the commit hash. This provides traceability, immutability (tags are never overwritten), and easy rollback.

### Manifest Rendering

The pipeline renders Helm charts or Kustomize overlays into plain Kubernetes manifests:

```
kubernetes/
├── src/
│   └── services/
│       └── go-backend/
│           ├── Chart.yaml
│           └── values.yaml
└── rendered/
    └── staging/
        └── services/
            └── go-backend/
                └── manifests.yaml  # Generated by CI
```

Rendered manifests ensure what's in Git is exactly what deploys, PRs show actual Kubernetes changes (not just Helm values), and Git history provides a full audit trail.

## Key Design Decisions

| Decision                               | Rationale                                |
| -------------------------------------- | ---------------------------------------- |
| **Change detection with path filters** | Fast CI, minimal rebuilds in a monorepo  |
| **Versioned image tags**               | Immutable, traceable, rollback-friendly  |
| **Rendered manifests in Git**          | ArgoCD deploys exactly what's committed  |
| **Staging auto-deploy on merge**       | Merged code is always running in staging |
