Test: test env | Prod: production env
BuildPipeline is an AWS-backed, fully scripted build → test → deploy pipeline with separate test and production environments. The frontend (React + TypeScript + Webpack) is served from S3 behind CloudFront, with project subdomains managed in Cloudflare. Infrastructure and deployment flow are defined as code in Terraform plus a small set of Bash scripts. CodeBuild and CodePipeline orchestrate builds, tests, artifact packaging, and promoted releases. Logs go to CloudWatch. Only actual deployment/runtime secrets remain in SSM Parameter Store.
- Push to master → test env pipeline: build, test, apply infra, upload and deploy assets
- Promote: merge master → production branch
- Manual approval gate in CodePipeline
- Production deploy: infra apply (no rebuild/tests) and asset promotion
- Frontend: React, TypeScript, Webpack 5, Rebass v4 (@emotion theme), Redux + Sagas
- Quality: ESLint 9 flat config, TypeScript strict-ish, Prettier (via ESLint)
- Infra: Terraform modules (
/infrastructure+ nested modules), Bash helpers - CI/CD: AWS CodeBuild, CodePipeline, S3, CloudFront, Cloudflare DNS, CloudWatch Logs
- Secrets: SSM Parameter Store (SecureString) for deployment/runtime secrets only
- Build Images: ECR-hosted
docker-node-terraform-aws:22.xfor test anddind-terraform-aws:v1.13.3for prod
Production CodeBuild in this repo runs on the standard LINUX_CONTAINER environment, so the configured runtime image must include linux/amd64. An arm64-only image will fail during the CodeBuild PROVISIONING phase before buildspec-prod.yml starts.
Before changing the prod build image tag, verify the target image manifest:
./infrastructure/check-codebuild-image-platform.bash \
352311918919.dkr.ecr.ap-southeast-2.amazonaws.com/dind-terraform-aws:v1.13.3For a private ECR image, authenticate Docker first:
aws ecr get-login-password --region ap-southeast-2 | docker login --username AWS --password-stdin 352311918919.dkr.ecr.ap-southeast-2.amazonaws.comLocated under infrastructure/modules/ (e.g. build-pipeline, web-app). Modules encapsulate repeatable infra (pipelines, IAM, hosting). State + buildspec files are per-environment to allow environment‑specific steps.
Naming convention:
- Repo scoped:
/buildpipeline/SECRET_NAME - Environment specific:
/buildpipeline/SECRET_NAME-testor/buildpipeline/SECRET_NAME-prod
Current secrets used by this repo:
/buildpipeline/cloudflare-api-token/buildpipeline/app-secret-test/buildpipeline/app-secret-prod
Basic CLI examples:
aws ssm put-parameter --region <REGION> --name "/buildpipeline/cloudflare-api-token" --value "VALUE" --type SecureString --key-id <KMS_KEY_ID>
aws ssm get-parameters --region <REGION> --name "/buildpipeline/cloudflare-api-token" --with-decryption --query 'Parameters[0].Value' --output text- master branch → test automatically
- production branch → prod after manual approval (reduces accidental releases / coordinates timing)
- Separate buildspec + state per environment
- Production skips build & tests: only infra apply + artifact deploy
- First deploy in a new account/environment is run locally via
./infrastructure/bootstrap-deploy.bash <test|prod>, after which CodeBuild takes over - Current demo URLs:
buildpipeline--test.603.nzandbuildpipeline--prod.603.nz
AWS CodePipeline uses AWS CodeConnections for GitHub source access. When creating a new GitHub connection in AWS, install the GitHub app from the CodeConnections flow and grant it access to the jch254/buildpipeline repository. Repository access is repo-scoped, not branch-scoped, so a valid installation covers both master and production. After creating a replacement connection, update TF_VAR_github_connection_arn in both buildspecs and run one manual test pipeline execution so Terraform can roll the new connection ARN into the deployed pipelines.
If building Docker images, enable privileged mode (CodeBuild project or module variable) and start the daemon early in the buildspec:
nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 --storage-driver=overlay &
timeout -t 15 sh -c "until docker info; do echo .; sleep 1; done"Provide cache_bucket Terraform variable → CodeBuild layer caches (see buildspec-test.yml).
pnpm install
pnpm dev # http://localhost:3001 (hot reload)pnpm install
pnpm build # outputs to /distpnpm install
pnpm prod # serves built assets- Migrated to ESLint 9 flat config; removed legacy TSLint remnants
- Aligned React Router to v6 (was mixed with v7 bits)
- Rebass v4 migration + unified @emotion ThemeProvider
- Added safe runtime env fallbacks (DEPLOY_ENV, APP_VERSION)
- Simplified Home page layout; consistent spacing & typography
- Cross-account production deployment pattern
- Extended build notifications (Lambda → Slack/webhook)
- Additional reusable infra modules
See ./infrastructure for Terraform root modules, helper scripts and environment state layout.
MIT License