Dual-Track CI/CD Delivery Pipeline
A GitHub Actions pipeline that runs quality gates on every push and deploys via two independent paths: a static Next.js export to AWS S3 + CloudFront, and a containerised build to Kubernetes. IAM OIDC provides keyless AWS authentication — no long-lived credentials stored anywhere.
Manual deployments are slow, error-prone, and don't scale. Storing AWS credentials as long-lived secrets is a security risk. Running no quality gates means bugs and type errors reach production.
Every push triggers a full CI run. On success, two independent deploy jobs run in parallel — one for the static path, one for Kubernetes. IAM OIDC means no AWS credentials are stored anywhere in GitHub.
ESLint checks code quality and catches common errors before the build.
TypeScript compiler validates all types — no any leaks, no runtime surprises.
Unit and integration tests run against the application code.
next build runs the production build and catches build-time errors.
npm audit checks for known vulnerabilities in the dependency tree.
Static path and Kubernetes path run simultaneously — independent failures, faster delivery.
Static AWS access keys stored in GitHub Secrets are a major security risk — they never expire, can be leaked in logs, and require manual rotation. IAM OIDC lets GitHub Actions assume an AWS role dynamically for each workflow run using short-lived tokens. No keys to rotate, no secrets to leak.
The static S3 deploy and the Kubernetes deploy are independent concerns. Separating them means a Kubernetes cluster issue won't block the static deployment, and each path can be enabled or disabled without modifying shared logic. Each job also has its own IAM permissions — least-privilege by design.
Shifting security left means catching issues before they reach production. Running a dependency audit and static analysis in every PR build ensures no new vulnerabilities are introduced silently. It also creates a clear audit trail in the GitHub Actions log.
Without cache invalidation, CloudFront may serve stale files for up to 24 hours after a deployment. Running aws cloudfront create-invalidation at the end of every deploy ensures users always get the latest version immediately.
IAM OIDC trust policies must include the exact GitHub repo and branch in the condition — too permissive and any repo can assume your role, too strict and your own workflow breaks.
CloudFront cache invalidation is not instant — it takes 30–60 seconds. Build your deploy job to trigger it and not wait for confirmation to avoid slowing down the pipeline.
Separating CI from CD in different jobs makes it easy to re-run just the deploy without re-running tests — useful when a deploy fails due to an infrastructure issue, not a code issue.
Caching node_modules in GitHub Actions using actions/cache can cut CI time by 60–80% on subsequent runs by avoiding a full npm install each time.