Multi-env CI/CD: ECR build-push + ECS deploy - #144
Open
arvsa wants to merge 3 commits into
Open
Conversation
deploy-staging.yml and deploy-production.yml now build all three service images on a GitHub-hosted arm64 runner, push them to AWS ECR (OIDC role, no static AWS keys), then SSH into that environment's plain EC2 box and docker compose pull && up -d. Only the image tag/registry flow through CI on each deploy; app secrets stay in a persistent .env bootstrapped once per box. Removes the ecs/ directory (untracked, superseded ECS-cluster approach) and rewrites deployment.md's CD section into a provisioning runbook for the new flow, with an updated secrets/variables table. No self-hosted runner install is needed anywhere anymore. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the SSH-into-EC2 docker-compose deploy with ECS (EC2 launch
type, reusing the existing argus-staging cluster): CI still builds and
pushes images to ECR, but the deploy step now renders the new image tag
into a checked-in task definition and calls register-task-definition +
update-service via aws-actions/amazon-ecs-deploy-task-definition -- no
SSH, no self-hosted runner, nothing to reach into on a routine deploy.
Both environments run as a single ECS task with all 7 services as
sidecar containers (same topology compose.yml runs locally), using
classic Docker links for inter-container DNS and Traefik's file
provider (ecs/traefik-dynamic.*.yml) instead of the docker-label
provider, since routing shouldn't depend on giving a container access
to the host's docker.sock. App secrets move from a persistent .env
file to SSM Parameter Store (SecureString), referenced directly by the
task definition's `secrets` blocks -- non-sensitive config (domain,
environment name, CORS origins) is baked into the checked-in
per-environment task-def JSON instead. This shrinks the GitHub Actions
secrets surface for deploy down to just two: AWS_DEPLOY_ROLE_ARN and
the AWS_REGION variable.
Adds ecs/README.md (provisioning runbook), ecs/{staging,production}-
taskdef.json, and ecs/traefik-dynamic.{staging,production}.yml.
Rewrites deployment.md's Continuous Deployment section to match.
Not yet exercised against real AWS infra -- workflow YAML and task
definition JSON validated for syntax only, per the existing caveat
that this needs a real provisioning pass to fully verify.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the 3x docker/build-push-action calls (one ECR repo per service) with a single `docker compose build` invocation -- reusing compose.yml's own Dockerfile/context/target definitions rather than duplicating them in the workflow -- followed by tagging/pushing into two repos as separate tags: argus-client (backend-<sha>, frontend-<sha>, pingsvc-<sha> -- a full zone) and argus-server (backend-<sha>, frontend-<sha> only, since the central dashboard never runs pingsvc). backend/frontend are role-agnostic at runtime (ROLE/ S3_BUCKET pick client vs server, see CLAUDE.md), so the same build lands in both repos; only argus-client's tags are actually consumed by these two workflows' ECS deploy step, since staging and production are both client-role zones -- argus-server's tags are pushed for future use by a server deployment, not deployed by anything yet. Updates ecs/README.md's ECR/IAM sections and both task definitions' placeholder image strings to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POSTGRES_*naming, so it should merge after/into that one.ubuntu-24.04-armrunner runsdocker compose build backend frontend pingsvc(reusing compose.yml's own Dockerfile/context/target definitions rather than duplicating them in the workflow), then tags/pushes the results into two ECR repos as separate tags instead of one repo per service:argus-clientholdsbackend-<sha>/frontend-<sha>/pingsvc-<sha>(a full zone needs all three),argus-serverholdsbackend-<sha>/frontend-<sha>only (the central dashboard never runs pingsvc — see CLAUDE.md). backend/frontend are role-agnostic at runtime (ROLE/S3_BUCKETpick client vs server), so the same build lands in both repos — onlyargus-client's tags are actually consumed by these two workflows' deploy step since staging/production are both client-role zones;argus-server's tags are pushed for a future server deployment, not deployed by anything yet. Auth to ECR is via OIDC (AWS_DEPLOY_ROLE_ARN, no static AWS keys as secrets).argus-stagingcluster). The deploy step renders the new image tag into a checked-in task definition (aws-actions/amazon-ecs-render-task-definition) and callsregister-task-definition+update-service(aws-actions/amazon-ecs-deploy-task-definition) — no SSH, no self-hosted runner, nothing to reach into on a routine deploy.compose.ymlruns locally): classic Dockerlinksgive inter-container DNS the way compose's default network does, and Traefik uses its file provider (ecs/traefik-dynamic.{staging,production}.yml) instead of the docker-label provider, since routing shouldn't require giving a container access to the host's docker.sock.secretsblocks. Non-sensitive config (domain, environment name, CORS origins, admin email) is baked into the checked-in per-environment task-def JSON. This shrinks the GitHub Actions secrets surface for deploy down to just two:AWS_DEPLOY_ROLE_ARNand theAWS_REGIONvariable.ecs/README.md(full provisioning runbook),ecs/{staging,production}-taskdef.json,ecs/traefik-dynamic.{staging,production}.yml.deployment.md's Continuous Deployment section to match.Test plan
yaml.safe_load/json.load)prestart,backend,frontend,pingsvc)ecs/README.md(staging first, reusing the existingargus-stagingcluster, creating theargus-client/argus-serverECR repos), then confirming a push tomainflows all the way through: images land in both ECR repos → task definition registers → service updates and stabilizes →https://api.staging.<domain>/api/v1/utils/health-check/responds. Production only gets provisioned/deployed after staging is confirmed working.🤖 Generated with Claude Code