GitLab CI migration — handover notes¶
Date: 2026-05-13
Migration status: Complete for all currently-built modules. Agents own their CI pipeline from here.
What changed from GitHub Actions¶
Every module that was on GitHub Actions now has equivalent GitLab CI jobs generated under
.gitlab/ci/mod-NNN.gitlab-ci.yml in its repo. Each module file includes a shared template
from totara-bank/bank-platform and defines two jobs:
mod-NNN-mr— MR validation (typecheck, lint, unit tests, policy tests). Fires on merge request events only. No deploy, no artefact upload, no wiki handoff.mod-NNN-deploy— Full deploy pipeline. Fires on push tomain(or manual web trigger). Runs: install → typecheck → lint → tests → build → deploy (Pulumi/Serverless/Cloudflare) → integration tests → writesBuilthandoff → smoke test → writesDeployedhandoff.
Templates live in bank-platform/.gitlab/ci/templates/:
| Template | Used by |
|---|---|
lambda.gitlab-ci.yml |
bank-core, bank-kyc, bank-aml, bank-payments, bank-credit, bank-app (Lambda modules), bank-platform |
frontend.gitlab-ci.yml |
bank-app (frontend/Cloudflare modules) |
iac.gitlab-ci.yml |
bank-platform (infrastructure modules) |
risk-platform.gitlab-ci.yml |
bank-risk-platform (all SD06 modules) |
Known issue: missing changes: path guards¶
Every repo except bank-risk-platform still has unconditional deploy rules on every module job.
This means every push to main in your repo runs every module's deploy job, regardless of what
changed. This burned GitLab compute minutes during the migration.
Do not make a bulk fix commit. Add the guard naturally when you next push a real code change to a module. The pattern is:
# In .gitlab/ci/mod-NNN.gitlab-ci.yml — replace the existing push rule:
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- MOD-NNN-your-module-name/**/* # only run when this module's source changes
- if: '$CI_PIPELINE_SOURCE == "web"'
when: manual
variables:
STAGE: ${DEPLOY_STAGE:-dev}
The manual web trigger (CI_PIPELINE_SOURCE == "web") remains unconditional so you can always
re-deploy a specific module from the GitLab UI without touching code.
bank-risk-platform already has changes: guards applied to all 11 modules (ca3d624).
Handoff mechanism — how CI advances build_status in bank-wiki¶
When a deploy job completes successfully it writes a .handoff.md file into docs/handoffs/
in your repo and pushes it back to main. The bank-wiki agent polls for these files and runs:
python3 scripts/update-wiki.py --module MOD-NNN --status Built|Deployed \
--commit SHA --repo your-repo-name
This advances build_status in source/entities/modules/MOD-NNN.yaml and recompiles the wiki.
You do not need to edit wiki YAML manually for build status — CI owns that field.
Per-SD status and outstanding items¶
SD01 — Core Banking (bank-core)¶
| Metric | Value |
|---|---|
| CI jobs | 18 (lambda template) |
| Deployed | 19/20 |
changes: guards |
None — add when next committing to any module |
Outstanding: MOD-118 has no source directory — not yet built.
SD02 — KYC Platform (bank-kyc)¶
| Metric | Value |
|---|---|
| CI jobs | 8 (lambda template) |
| Deployed | 8/9 |
changes: guards |
None — add when next committing to any module |
Outstanding: MOD-096 has no source directory — not yet built.
SD03 — AML Monitoring (bank-aml)¶
| Metric | Value |
|---|---|
| CI jobs | 3 (lambda template) |
| Deployed | 3/4 |
changes: guards |
None — add when next committing to any module |
Outstanding: MOD-019 has no source directory — not yet built.
SD04 — Payments (bank-payments)¶
| Metric | Value |
|---|---|
| CI jobs | 10 (lambda template) |
| Deployed | 10/26 |
changes: guards |
None — add when next committing to any module |
Outstanding: 16 modules (MOD-026/061/067/081/084/114/122/123/124/135/136/137/144/145/149/154) have no source directory — not yet built. CI jobs exist only for the 10 Deployed modules.
SD05 — Credit (bank-credit)¶
| Metric | Value |
|---|---|
| CI jobs | 12 (lambda template) |
| Deployed | 12/17 |
changes: guards |
None — add when next committing to any module |
Outstanding: 5 modules (MOD-121/132/162/163/167) have no source directory — not yet built.
SD06 — Risk Platform (bank-risk-platform)¶
| Metric | Value |
|---|---|
| CI jobs | 11 (risk-platform template) |
| Deployed | 8/32 |
changes: guards |
All 11 applied (ca3d624) |
Three modules incomplete — these are your immediate CI responsibility:
| Module | Status | Issue | Action needed |
|---|---|---|---|
| MOD-041 | Not started | SCP resolved in code (4b9855e) — bucket moved to MOD-104. Blocked on MOD-104 shipping bank-merchant-assets-{env} |
SD07 has the handoff (MOD-041-needs-MOD-104-merchant-assets-bucket.handoff.md). Re-trigger after MOD-104 deploys bucket. |
| MOD-056 | Not started | No S3 in Pulumi stack — re-clears on retrigger | Re-trigger directly; no infrastructure prerequisite |
| MOD-080 | Built | Bucket already provisioned (6a21dae) — re-trigger to advance to Deployed |
Re-trigger directly |
DCM ownership context: SF_ROLE (the CI service account) cannot self-grant ownership of DCM
projects pre-created as BANK_NONPROD_RISK_ROLE. The workaround sets HAS_DCM=false and
HAS_DBT_PROJECT=false, routing these modules through the legacy dbt build path instead of
snow dcm plan/deploy and snow dbt deploy/execute. See .gitlab/ci/mod-041.gitlab-ci.yml
comments for full explanation.
Long-term resolution (DCM): grant SF_USER the BANK_NONPROD_RISK_ROLE role in Snowflake,
then flip HAS_DCM and HAS_DBT_PROJECT back to true for these three modules.
SCP blocker — resolved for MOD-041, MOD-056, MOD-080
SD06 agent resolved via commit 4b9855e (2026-05-13 09:14 +1200): S3 bucket creation removed
from MOD-041's Pulumi stack and delegated to MOD-104 (bank-platform), which runs under a
principal exempt from the SCP. The same pattern was applied earlier for MOD-080 in 6a21dae.
MOD-056 has no S3 resources — it clears on retrigger without any prerequisite.
Current blocking state per module:
| Module | Status | Remaining blocker |
|---|---|---|
| MOD-041 | Waiting on MOD-104 | MOD-104 must provision bank-merchant-assets-{env} first. Handoff delivered to SD07 (MOD-041-needs-MOD-104-merchant-assets-bucket.handoff.md in bank-platform/docs/handoffs/). Re-trigger mod-041-deploy after MOD-104 ships. |
| MOD-056 | Ready to retrigger | No S3 dependency. Re-trigger directly from GitLab UI (web trigger). |
| MOD-080 | Ready to retrigger | Bucket already provisioned. Re-trigger to advance from Built → Deployed. |
23 further Not-started modules (MOD-033/034/036/037/055/057/058/060/088/089/092/094/095/
101/105/106/107/147/150/152/165) have no source directory — not yet built. They have no CI jobs.
Add them to .gitlab-ci.yml when code is ready.
SD07 — Data Platform (bank-platform)¶
| Metric | Value |
|---|---|
| CI jobs | 23 (lambda + iac templates) |
| Deployed | 23/26 |
changes: guards |
None — add when next committing to any module |
Outstanding: MOD-087, MOD-093, MOD-168 have no source directory — not yet built.
SD08 — App (bank-app)¶
| Metric | Value |
|---|---|
| CI jobs | 6 (lambda + frontend templates) |
| Deployed | 6/34 |
changes: guards |
None — add when next committing to any module |
Outstanding: 28 modules have no source directory — not yet built. The 6 Deployed modules cover the current app shell and back-office (MOD-049/050/052/068/069 + one more).
Pipeline from e16ffcf — outcome¶
Commit e16ffcf (2026-05-13 07:18 +1200) added changes: guards to the 8 already-Deployed
modules but left MOD-041/056/080 with unconditional push rules. That commit triggered a 3-job
pipeline for those three modules. Six minutes later, ca3d624 added guards to MOD-041/056/080
too — but the pipeline was already in flight. ca3d624 fires zero jobs (only CI config files
changed).
The pipeline failed. MOD-041-deploy failed at Pulumi up (~45 min in) with an AWS SCP deny
on s3:CreateBucket for bank-dev-merchant-assets (see SCP blocker above). MOD-056 and MOD-080
were likely cancelled or similarly blocked. No ci(handoff) commits were written. Build
statuses for MOD-041/056/080 are unchanged from before the pipeline ran.
CI template change log (migration period)¶
Key fixes made to bank-platform/.gitlab/ci/templates/risk-platform.gitlab-ci.yml:
| Commit | Change | Reason |
|---|---|---|
6fa4aa4 |
Smoke test made conditional on file existence | Modules without verify-deployment.mjs were failing |
e5044b7 |
apply-ddl guarded by jq script-existence check |
HAS_DCM=false modules without the script were failing |
200217f |
DCM Phase 2 ENV_ROLE grant made non-fatal |
GRANT OWNERSHIP exits non-zero even on self-grants; Phase 2 was killing all HAS_DCM=true jobs |
These fixes are in the shared template. All SD06 modules benefit automatically.