Source control, CI-CD & SDLC — N1 IT Landscape
N1 IT Landscape — The Blueprint · CF-Access internal
Source control, CI-CD & SDLC
Section titled “Source control, CI-CD & SDLC”N1 IT Landscape · Owner: Arun Venkataraman · source of truth: markdown SSOT
N1 IT Landscape — Source control, CI/CD & SDLC
Section titled “N1 IT Landscape — Source control, CI/CD & SDLC”CURRENT-STATE as of 2026-06-09 · part of the N1 IT Landscape (start at Overview). Owner: Arun Venkataraman (Principal Engineer).
Where the code lives (GitHub) and how a change travels from a laptop to production — the build pipeline, governance, and the full software delivery lifecycle.
7. SOURCE CONTROL & CI/CD
Section titled “7. SOURCE CONTROL & CI/CD”GitHub is the only source-control system. Org n1healthcare: 98 repos total — 48 active, 50 archived as of this snapshot (2026-06-09). The active/archived split moves continuously as repos are archived during ongoing cleanup, so treat the count as a point-in-time figure. The dependency manifest in the companion file was captured earlier the same day when 66 were active, so it covers 65 cloned repos (18 of which are now archived). 2 public repos (OcrRouter, synthetic-medical-reports), both archived; everything else is private. The repo count far exceeds the number of services in production — many are experiments, POCs, or archived workflows. 🔒 2FA is enforced org-wide; default repo permission is read.
Note: the full repo catalogue (with language, default branch, and the exact
developHEAD commit for each) is in §18; the full per-repo catalogue with HEAD SHAs is in the companion DEPENDENCIES file.
7.1 The build-and-ship pipeline (the canonical pattern)
Section titled “7.1 The build-and-ship pipeline (the canonical pattern)”Almost every service repo carries a thin deploy_aws.yaml that delegates all real work to reusable workflows in thebastion repo (n1healthcare/bastion/.github/workflows/...@main):
push to develop → deploy-staging → bastion/deploy.yml (env n1-staging) → ECR n1-staging/<svc>push to main → deploy-prod → bastion/deploy.yml (env n1-prod) → ECR n1-prod/<svc>PR opened/sync → precheck → bastion/supply_chain_precheck.yml (safe-chain dependency shims)PR merged → release-notes → bastion/release_notes.yml → Slack (via release-scribe)🔒 bastion/deploy.yml is hardened :
- Checkout via SHA-pinned wrapper actions.
- Resolve env → ECR prefix + IAM role + region (
us-east-2for staging/prod;us-east-1for the retired twin-staging). - Assume an AWS role via GitHub OIDC (
id-token: write) — no long-lived AWS keys in CI. - Login to ECR (
191421493115.dkr.ecr.us-east-2.amazonaws.com). - Build with Docker Buildx; derive the image tag from the repo’s
VERSIONfile (staging:<VERSION>_<sha7>, prod: clean<VERSION>). - Grype CVE scan → SARIF upload (prod).
- Push
:latest+:<tag>to ECR.
The canonical bastion pipeline builds ARM64 only (on ubuntu-24.04-arm runners), matching the all-Graviton/Bottlerocket-ARM fleet (§8/§9). Multi-arch (amd64+arm64 via QEMU) is used only by react-frontend (see §7.4).
7.2 Shared CI machinery
Section titled “7.2 Shared CI machinery”bastion— the reusable-workflow hub:deploy.yml,supply_chain_precheck.yml(enforcessafe-chain v1.5.0, SHA-pinned, foruv/npminstalls),release_notes.yml,mirror_dhi_images.yaml(mirrors third-party images into ECR). All third-party actions are wrapped in composite actions that SHA-pin every external dependency.release-scribe(@v1) — on PR merge, sends the PR diff + commits to the internal LiteLLM proxy (Gemini 2.5 Flash), gets structured JSON back (summary / change type / breaking changes / test recommendations), posts a Slack Block Kit message, and optionally creates a ClickUp ticket. This is the “what changed / what to test / will it break” note posted on every develop and main merge.github-action-deployment-approval— a Slack Approve/Reject gate that resolves approvers fromCODEOWNERS. 🔒 The approval step in the sharedbastion/deploy.ymlis commented out , so most service prod deploys run without a human gate in CI. The exception is admin-dashboard , which wires thedeployment-approval@mainaction directly into its own pipeline.
Pinned third-party action versions (from bastion): aws-actions/configure-aws-credentials v6.1.0, actions/checkout v6.0.2, docker/setup-buildx-action v4.0.0, docker/build-push-action v7.1.0, docker/setup-qemu-action v4.0.0, actions/upload-artifact v7.0.1 (all SHA-pinned).
7.3 Deployment (GitOps) and who can deploy
Section titled “7.3 Deployment (GitOps) and who can deploy”- ArgoCD runs in-cluster in both clusters and continuously syncs from
git@github.com:n1healthcare/n1-helm-charts.git(branchdevelop). ArgoCD Image Updater (v1.0.2) watches ECR and advances image tags — which is why several apps showOutOfSyncbutHealthy(the live image is ahead of the git manifest). - Staging deploys: any developer — via
argocd-staging.n1-research.com(Access-gated, Google sign-in required). - Production deploys: Arun, Darpan, Jasper only.
7.4 Branch protection & governance (GitHub rulesets)
Section titled “7.4 Branch protection & governance (GitHub rulesets)”Branch protection is implemented with GitHub rulesets (the classic branch-protection API is unused and returns 404). Three organization-level rulesets apply to all repos:
| Ruleset | Target | Enforces |
|---|---|---|
| Organization Branch Protection Policy | main + develop, all repos |
≥1 PR approval, dismiss-stale-reviews, require-thread-resolution, require-last-push-approval, block force-push, block deletion, no direct commits (PR required), signed commits |
| Protect all default branches | default branch, all repos | block force-push, block deletion |
| Require signed commits (org-wide) | all branches, all repos | every commit cryptographically signed |
Bypass actors: org admins, plus one team (via PR) on the main policy. Some repos add their own — e.g. forge-runner requires linear history + Copilot code review on main.
7.5 GitHub security & Actions configuration
Section titled “7.5 GitHub security & Actions configuration”- The enforced “N1 Default “ code-security config has secret-scanning, push-protection, and code-scanning disabled — these are GitHub Advanced Security features that are not available on the Team plan N1 is on. Dependabot alerts and security updates are enabled. An unenforced “GitHub recommended” config (which would enable the scanning features on a plan that offers them) also exists.
- The org Actions policy is
all(any public or private action may run); members can create repos. react-frontendbuilds multi-arch (amd64+arm64 via QEMU), has no Grype scan, uses date-sequentialV<YYYYMMDD>_<n>tags, and its EKS rollout steps are commented out (image reaches ECR, not auto-rolled).admin-dashboarduses the same date-tag scheme with rollout steps commented out, and does run Grype + the deployment-approval gate.api-backendhas a webhook tosearch.clickup-eu.com(ClickUp EU).
7A. SOFTWARE DELIVERY LIFECYCLE (SDLC) — what runs where, and what ships to staging vs prod
Section titled “7A. SOFTWARE DELIVERY LIFECYCLE (SDLC) — what runs where, and what ships to staging vs prod”This ties §7, §8, §9 and §10 into one description of how a change travels from a laptop to production.
7A.1 The three places work happens
Section titled “7A.1 The three places work happens”| Environment | Where | What runs there | Who deploys |
|---|---|---|---|
| Local / dev | Engineer’s laptop | Code is written mostly with Claude Code (only Eyad/Arun hand-write occasionally). Local stacks via local-development-env; CHR work via the chr-dev-kit with synthetic patients. |
— |
| Staging | n1-staging-cluster, namespace staging + staging.n1.care |
All services plus the evals suite (parser/router/grouper-evals), automated-testing, helix-parser, rosetta-genetics-grouper, n1-api-slack-bot, and data-validation-service. Developers get read-only staging DB/Redis over WARP. |
Any developer |
| Production | n1-production-cluster, namespace prod + app.n1.care |
Core services + the 3 production CHR types , plus the prod-only api-proxy/auth-proxy/billing-proxy and pdf-converter. |
Arun, Darpan, Jasper |
7A.2 Branch model = environment model (build once per branch)
Section titled “7A.2 Branch model = environment model (build once per branch)”feature branch ──PR──▶ develop ──(CI builds ARM64 image)──▶ ECR n1-staging/<svc>:V<date>_<sha7> │ └─▶ ArgoCD Image Updater ▶ STAGING └──PR (develop→main)──▶ main ──(CI)──▶ ECR n1-prod/<svc>:V<date> └─▶ ArgoCD ▶ PRODUCTIONdevelop maps to staging , main maps to production. A merge is the deploy trigger; promotion to production is the develop → main pull request. The staging image tag carries the git sha; the production tag is the clean VERSION. Both branches are gated by rulesets (≥1 approval, signed commits, no force-push — §7.4).
7A.3 What happens on each event
Section titled “7A.3 What happens on each event”| Trigger | Pipeline (bastion) |
Result |
|---|---|---|
| PR opened/updated | supply_chain_precheck.yml |
safe-chain-shimmed uv/npm install |
Merge →develop |
deploy.yml (env n1-staging) |
OIDC role → build ARM64 → (Grype on prod path) → push n1-staging/<svc> → ArgoCD Image Updater rolls it into staging |
Merge →main |
deploy.yml (env n1-prod) |
same, pushes n1-prod/<svc> → ArgoCD rolls into prod |
| PR merged (either) | release_notes.yml → release-scribe |
AI-generated release note posted to Slack |
| Pod starts | migration sidecar | DB schema migrated on startup (Alembic / raw SQL / Ory automigration / LiteLLM) |
7A.4 Delivery paths outside the standard ECR→ArgoCD flow
Section titled “7A.4 Delivery paths outside the standard ECR→ArgoCD flow”- Web app & marketing —
react-frontendandn1care-websiteare built and deployed on Cloudflare (Workers forn1.care/app.n1.care/staging.n1.care). - N1 libraries —
n1r-cortex,n1r-rosetta,n1r-phoenix,n1r-chr,n1-api-client,medical-unit-conversion,n1r-document-managerpublish wheels to the public R2 bucket (artifacts.n1-research.com) via their own publish workflows. forge-runnerships as an image but runs as on-demand Kubernetes Jobs (one per CHR), launched byforge-sentinel.
7A.5 Testing
Section titled “7A.5 Testing”PR-time: supply_chain_precheck plus each repo’s test/quick-check/lint workflows. In staging : automated-testing, e2e-tests, the parser/router/grouper-evals services, and data-validation-service (evaluates parser + CHR output). Production builds add a Grype CVE scan.
7A.6 Deploy state & rollback
Section titled “7A.6 Deploy state & rollback”ArgoCD Image Updater advances image tags as new images land in ECR, which is why several ArgoCD apps read OutOfSync but Healthy (live image ahead of the git manifest). Rollback is re-pointing the image tag or reverting the PR and letting CI rebuild. Staging and production run different tags at any given time (visible in §9.4).
