CI/CD Pipeline

Automated pipeline using GitHub Actions + ArgoCD for the LuckyPlans monorepo.

Pipeline Overview

  PR / Push to main          Merge to main             After Docker push
  ┌──────────────┐      ┌───────────────────┐      ┌───────────────────┐
  │     CI       │──ok──│  Docker Build     │──ok──│  Update Tags      │
  │              │      │  & Push           │      │                   │
  │ lint         │      │ build 3 images    │      │ commit new tags   │
  │ type-check   │      │ push to ghcr.io   │      │ to values files   │
  │ test         │      │ tag: sha + latest │      │ [skip ci]         │
  │ build        │      │ Trivy image scan  │      │                   │
  │ Trivy scans  │      │                   │      │                   │
  │ Helm lint    │      │                   │      │                   │
  └──────────────┘      └───────────────────┘      └───────────────────┘


                                                   ArgoCD detects change
                                                   └── Prod: auto-sync

Workflows

1. CI (.github/workflows/ci.yml)

Triggers: Push to main (excluding values file changes), pull requests to main.

Runs lint, type-check, test, and build using Turborepo. On PRs, only affected packages are checked via --filter=...[origin/main].

Concurrency groups cancel superseded PR runs automatically.

Security scanning is integrated into CI via Trivy :

  • Dependency scan (fs mode): Scans pnpm-lock.yaml and other dependency manifests for known CRITICAL/HIGH vulnerabilities. Fails the build if found.
  • IaC/Dockerfile config scan (config mode): Checks Dockerfiles, Helm templates, and Kubernetes manifests for misconfigurations. Fails on CRITICAL/HIGH.
  • SARIF upload: A vulnerability report is uploaded to GitHub Security tab for persistent tracking.

Additionally validates Helm chart templates by piping helm template output through kubeconform for all environment variants.

2. Docker Build & Push (.github/workflows/docker-build.yml)

Triggers: After CI passes on main, or manual dispatch.

Builds Docker images for all three services in parallel via a matrix strategy:

ServiceDockerfileImage
webapps/web/Dockerfileghcr.io/<owner>/web
api-gatewayapps/api-gateway/Dockerfileghcr.io/<owner>/api-gateway
service-coreapps/service-core/Dockerfileghcr.io/<owner>/service-core

Images are tagged with:

  • sha-<7-char-commit-sha> — immutable, used for deployments
  • latest — convenience pointer to the most recent build

Images are pushed with SBOM and provenance attestations enabled, providing supply chain transparency.

3. Update Image Tags (.github/workflows/update-tags.yml)

Triggers: After Docker build completes on main, or manual dispatch with a specific image tag.

The workflow:

  1. Computes the image tag (sha-<7char> from the triggering commit)
  2. Uses yq to update all 3 service image tags in values.prod.yaml
  3. Commits with [skip ci] to prevent re-triggering CI
  4. Pushes to main

ArgoCD then detects the change and auto-syncs the new image tags.

4. ArgoCD Sync & Post-Sync Hooks

After ArgoCD syncs the Helm chart, post-sync hooks run as Kubernetes Jobs:

  • Smoke tests verify API Gateway health, web frontend, and GraphQL endpoint
  • Job results are visible in the ArgoCD UI (sync status: Healthy or Degraded)
  • Failed smoke tests mark the sync as Degraded but do not auto-rollback

See ArgoCD for full operational documentation.

5. AI PR Review (.github/workflows/pr-review.yml)

Triggers: Manual only (workflow_dispatch) — run from the Actions tab by entering a PR number.

Runs an AI-powered code review using Claude against the project’s architecture, security, and convention rules (.claude/rules/). Posts inline review comments on changed files.

This workflow is opt-in to control API costs. To review a PR:

  1. Go to Actions → “AI PR Review” → Run workflow
  2. Enter the PR number and click “Run workflow”

This workflow is informational only — it posts comments, does not block merging.

Cost controls:

  • Opt-in only — never runs automatically
  • Skips PRs with more than 2000 changed lines
  • Excludes generated files (src/generated/, lock files)
  • Uses Claude Sonnet (not Opus) for cost efficiency
  • 10-minute timeout per review

Required GitHub Configuration

Secrets

SecretScopeDescription
GITHUB_TOKENAutomaticProvided by GitHub Actions. Used for ghcr.io auth.
CD_PUSH_TOKENRepositoryRequired with branch protection. Fine-grained PAT with Contents: read+write scope. Used by update-tags.yml to push tag commits to main.
ANTHROPIC_API_KEYRepositoryAPI key for Claude AI PR review. Configure spending limits in the Anthropic console.

Configure on the main branch:

  • Require a pull request before merging
  • Require at least 1 approval
  • Require status checks to pass (select the ci job)

Important: With branch protection enabled, GITHUB_TOKEN cannot push tag update commits to main. You must create a CD_PUSH_TOKEN secret.

Turborepo Caching

The CI workflow caches Turborepo artifacts in .turbo/ using actions/cache. On PRs, the --filter=...[origin/main] flag limits execution to packages affected by the changes, significantly reducing CI time.

Troubleshooting

CI fails on lint/type-check

pnpm turbo run lint --filter=<package-name>
pnpm turbo run type-check --filter=<package-name>

Docker build fails

docker build -f apps/<service>/Dockerfile .

ArgoCD sync fails or shows Degraded

kubectl -n luckyplans get pods
kubectl -n luckyplans describe pod <pod-name>
kubectl -n argocd get application luckyplans-prod -o yaml