Deployment Overview (platform-wide)¶
How the Someli platform is built and deployed across dev → UAT → production, spanning all repos. The single most important thing to understand:
There are two deploy targets, split by environment.
dev_*branches deploy to Lightsail/EC2 (SSH + PM2).uat_*and production deploy to ECS (Docker image → ECR → ECS service). They are different platforms with different tooling.
The per-repo mechanics live in each repo's build-and-deploy.md (or someli-api/deployment.md for the largest service). This page is the cross-cutting map they all point back to.
1. AWS coordinates (shared by every repo)¶
| Value | |
|---|---|
| Account | 255061853867 |
| Region | us-west-2 |
| ECR registry | 255061853867.dkr.ecr.us-west-2.amazonaws.com |
ECR repositories — one per environment¶
| ECR repo | Environment | Notes |
|---|---|---|
dev_crons |
Development | Dev cron/worker images |
uat |
UAT / testing | Multi-purpose — holds the someli-platform frontend image (tags uapp-<sha>) and the someli-api image (tag uapi) |
live_crons |
Production | Production cron/worker fleet images |
designers |
(designer side) | designer-api service image (tag dapi) — separate from the crons repos |
designers-crons |
(designer side) | Designer cron/worker fleet images |
⚠️ Hyphen-vs-underscore footgun. The production ECR repo is
live_crons(underscore) but the production ECS cluster islive-crons(hyphen). They are different identifiers for related things — don't assume one spelling works for the other.
ECS clusters¶
| Cluster | Environment | Services |
|---|---|---|
UAT |
UAT | uapp (someli-platform frontend) — see Path B |
live-crons |
Production | 9 domain services (below) |
Production cluster live-crons — 9 services¶
The production worker/cron fleet is partitioned into 9 ECS services by functional domain:
AI_CONTENT, Billing-Payments, Carousel, Content_Media, Dynamic_Post, Post_Schedule, Rag, Social_Media_Connection, User_Specific_Content.
One image, many services — but far more jobs than services.
someli-apihas 100+job_*.jsscripts (seesomeli-api/jobs-inventory.md); they are grouped into these 9 services by domain, so each service runs many jobs — there is no 1:1 job↔service mapping. Each service pulls the same ECR image and overrides the containerCMD/args to select which scripts it runs. The exact job→service assignment lives in the ECS task definitions in AWS — not committed in any repo — and is too large to enumerate here. This mirrors the Dockerfile comment "Default command — override with specific job script using docker run args."
2. The two deploy paths¶
┌─────────────────────────────────────────────┐
dev_* branch │ Lightsail / EC2 + PM2 (SSH or SSM) │
───────────► │ someli-api/dev-api-deploy.yml (SSH+PM2) │
│ someli-platform/dev_app.yml (SSM) │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
uat_* branch │ ECS UAT (cluster: UAT) │
───────────► │ docker build → ECR `uat` → ECS service uapp │
│ someli-platform/uat_app_ecs.yml (GH Action)│
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
production │ ECS PROD (cluster: live-crons, 9 services) │
(manual) │ docker build → ECR `live_crons` → 9 services│
───────────► │ MANUAL — no committed workflow │
└─────────────────────────────────────────────┘
Path A — dev → Lightsail/EC2 (SSH/SSM + PM2)¶
Committed in:
- someli-api/.github/workflows/dev-api-deploy.yml — push to dev_api, SSH to the Lightsail host, git pull + pm2 reload. OIDC is not used here — relies on LIGHTSAIL_* SSH secrets. (Also a legacy Jenkinsfile targets the same branch — see someli-api/deployment.md §6.1.)
- someli-platform/.github/workflows/dev_app.yml — "Deploy to Lightsail", push to dev_app, deploy via SSM. OIDC role arn:aws:iam::255061853867:role/GitHubActionsLightsailRole.
Path B — UAT → ECS (automated, frontend)¶
someli-platform/.github/workflows/uat_app_ecs.yml — name: Deploy to ECS UAT, push to uat_app. This is the only fully-automated ECS pipeline committed anywhere:
- OIDC auth —
arn:aws:iam::255061853867:role/GitHubActionsECSRole aws-actions/amazon-ecr-login@v2docker build→docker push $ECR_REGISTRY/uat:uapp-<sha>aws-actions/amazon-ecs-render-task-definition@v1(containeruapp)aws-actions/amazon-ecs-deploy-task-definition@v2→ clusterUAT, serviceuapp, then waits for service stability- Teams/Slack deployment summary
Config (env block): AWS_REGION=us-west-2, ECR_REPOSITORY=uat, ECS_CLUSTER=UAT, ECS_SERVICE=uapp, ECS_TASK_DEFINITION=uapp, CONTAINER_NAME=uapp.
Path C — production → ECS (manual)¶
Production deploys to the live-crons cluster (9 services, ECR repo live_crons) are manual — there is no committed production workflow in any repo. The image-build helpers that exist:
someli-api/push.sh→python deploy_image.py --image-tag uapi --repository-uri …/uat …(currently points at theuatrepo; the prod equivalent targetslive_crons)designer-api/push.sh→python deploy_image.py --image-tag dapi --repository-uri …/designers …deploy_image.pyauthenticates to ECR via boto3, runsdocker build, tags, and pushes.
After the image is pushed, each of the 9 ECS services must be updated to the new image (in the AWS Console or via CLI). Verify with ops the exact prod release runbook — the repos only contain the image-build half.
UAT may also be triggered automatically via GitHub Actions (the committed
uat_app_ecs.ymlcovers the frontend); the cron/worker side of UAT and all of production are manual today.
3. Per-repo summary¶
| Repo | Dockerfile | Dev deploy | UAT/Prod deploy | Detail doc |
|---|---|---|---|---|
someli-api |
✅ (no install step — see caveat) | GH Actions → Lightsail (SSH+PM2) | push.sh → ECR uat/live_crons → ECS (manual) |
deployment.md |
someli-platform |
✅ (artifacts pre-built, node_modules from EFS) | GH Actions → Lightsail (SSM) | GH Actions → ECS UAT (uapp), prod manual |
(in deployment.md + this page) |
designer-api |
✅ (multi-stage; .env baked in ⚠️) |
none in repo | push.sh → ECR designers / designers-crons (manual) |
build-and-deploy.md |
Someli-Designer |
✅ (artifacts pre-built, node_modules from EFS) | none in repo | image build opaque (manual) | build-and-deploy.md |
Someli-admin-api |
❌ none | none in repo | not containerised | build-and-deploy.md |
admin_console_R |
❌ none | none in repo | not containerised | build-and-deploy.md |
someli-dashboard-be |
❌ none | none in repo | runs in-process inside someli-api in prod |
build-and-deploy.md |
The three repos with no Dockerfile (Someli-admin-api, admin_console_R, someli-dashboard-be) are not part of the ECR/ECS flow — they deploy by other means (or, for the dashboard, run inside someli-api).
4. Cross-cutting risks¶
- Production is manual, no committed runbook. The 9
live-cronsservices are updated by hand after a manualpush.sh. No automated rollback, no audit trail, no health-gating. This is the highest-priority deployment gap. - No image versioning on the manual path.
push.shtags:uapi/:dapi(overwritten each push). Only the automateduat_app_ecs.ymlpath uses a git-SHA tag (uapp-<sha>). Adopt SHA tags on the manual paths so prod rollback is well-defined. live_crons(repo) vslive-crons(cluster) naming mismatch invites copy-paste errors in scripts and IAM policies.someli-apiDockerfile has noyarn install— relies onnode_modulespresent in the build context, producing non-reproducible images.designer-api's multi-stage Dockerfile does it correctly; align them. Seesomeli-api/deployment.md§6.3.designer-api/Dockerfilebakes.envinto the image — anyone with ECR pull access todesignersreads all secrets. Seedesigner-api/build-and-deploy.mdD-1 and the repo'ssecurity.md.- Two CI systems on
someli-api's dev branch (Jenkins + GH Actions). Retire one.
5. Related¶
someli-api/deployment.md— the deepest per-repo treatment (branch strategy, PM2, ports, infra table)someli-api/jobs-inventory.md— the job catalog the 9 prod services partitionCODE-OVERLAP-MATRIX.md— shared Dockerfile/skeleton lineage across the three backends- Onboarding:
../onboard/00-workstation-setup.md§5 — local Docker + ECR push setup