T3 Distribution Module — QA Deploy Runbook
Bundle: AP-T11-007 (cert hotfix + dual-auth + Q9b) + AP-T11-011 (wire-up) + AP-T11-012 (Auto-Pilot) + AP-T11-013 (drip-feed) + AP-T11-014 (promotions) + AP-T11-015 (mode + occupancy)
Target: QA EC2 43.204.247.178 (hmp-pilot SSH key)
Strategy: Big-bang — single QA deploy after all tickets are code-complete on master.
Pre-flight checklist
| # | Check | Verify |
|---|---|---|
| 1 | All ticket merges on master | See master tips table below |
| 2 | @hmp/service-clients@1.12.1 published to Azure Artifacts | npm view @hmp/service-clients version |
| 3 | Local Docker daemon running | docker info |
| 4 | SSH key ~/.ssh/hmp-pilot works | ssh -i ~/.ssh/hmp-pilot ubuntu@43.204.247.178 'echo ok' |
| 5 | envs/.env.qa-aws has INTERNAL_SERVICE_TOKEN and other secrets | grep INTERNAL_SERVICE_TOKEN envs/.env.qa-aws |
Master tips at start of deploy (final, all backlog cleared)
| Repo | Master tip | Last shipped |
|---|---|---|
| hmp-shared-packages | e3bae68 | @hmp/service-clients@1.12.1 published |
| hmp-property-service | 12c617b | autoFlippedToManual propagation + SINGLE_PAX_ADJUSTMENT AriCellField + writeSinglePaxAdjustment handler (migration 20260630_ari_cell_field_single_pax) |
| hmp-channel-service | 072bafb | T15 backend (xml-builder diverged BaseByGuestAmt) |
| hmp-reservation-service | 12272ab | T14 backend (preview() promotion integration) |
| hmp-api-gateway | 3bde050 | T14 /promotions routing |
| hmp-web-dashboard | b796ae1 | T15 frontend + functional single-pax Save + Auto-Pilot scope multi-select chips |
No outstanding pending follow-ups before deploy. Backlog #19 (SINGLE_PAX_ADJUSTMENT) and #14 (multi-select chips) closed inline. Backlog item that remains is Reservation.totalDiscount analytics columns — explicitly v2 per the plan, not in this bundle.
Step 1 — Refresh shared-package consumers
Each consumer of @hmp/service-clients needs npm install to pull the freshly-published 1.12.1.
for r in hmp-property-service hmp-reservation-service; do
cd /c/CLProjects/HMP/$r && npm install
done
Verify:
grep '"@hmp/service-clients"' /c/CLProjects/HMP/hmp-property-service/node_modules/@hmp/service-clients/package.json
# Expect: "version": "1.12.1"
Step 2 — Local Docker rebuilds
5 images need fresh builds. Sized to run in parallel (~5 min each):
docker build -t hmp-property-service:dev /c/CLProjects/HMP/hmp-property-service &
docker build -t hmp-channel-service:dev /c/CLProjects/HMP/hmp-channel-service &
docker build -t hmp-reservation-service:dev /c/CLProjects/HMP/hmp-reservation-service &
docker build -t hmp-api-gateway:dev /c/CLProjects/HMP/hmp-api-gateway &
docker build -t hmp-web-dashboard:dev /c/CLProjects/HMP/hmp-web-dashboard &
wait
If any build fails, rerun individually with 2>&1 | tee build.log to capture the error.
Step 3 — deploy-qa.sh
cd /c/CLProjects/HMP/hmp-infrastructure
bash scripts/deploy-qa.sh
deploy-qa.sh handles:
- Tag
:dev→:qafor all 19 images - Save tarballs, scp to EC2,
docker load docker compose down && docker compose up -don EC2 with--env-file .env.qa-aws- Wait for health checks
prisma db pushon each schema-bearing service (15 services) — picks up the new tables:ari_automation_rules(T12) — property-servicechannel_allocation_policies(T13) — channel-servicepromotions+promotion_rate_plan_links+promotion_channel_links(T14) — property-serviceRatePlanRate.mode+singlePaxAdjustmentcolumns (T15) — property-service
- Seed scripts (
seed-master.sh) - Re-mint
INTERNAL_SERVICE_TOKENon EC2 (RS256 from key file)
Step 4 — Smoke test the bundle
After deploy-qa.sh reports green:
# 1. Health probe
curl -s https://qa.keynova.ai/api/health | python3 -m json.tool
# 2. Login + JWT
curl -s -X POST https://qa.keynova.ai/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@hmphotel.com","password":"<REDACTED>"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['data']['accessToken'])" > /tmp/jwt.txt
JWT=$(cat /tmp/jwt.txt)
# 3. ARI grid round-trip
curl -s -H "Authorization: Bearer $JWT" \
"https://qa.keynova.ai/api/distribution/ari?startDate=2026-05-01&endDate=2026-05-07" \
| python3 -m json.tool | head -40
# Expect: roomTypes[].byDate{...}.allocations field present (T13 surfaced),
# ratePlans[].mode + singlePaxAdjustment (T15 surfaced)
# 4. Allocation upsert smoke
curl -s -X PUT "https://qa.keynova.ai/api/distribution/allocations" \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"roomTypeId":"<uuid>","date":"2026-05-01","mode":"RATIO","perChannel":{"BOOKING_COM":0.4,"MAKEMYTRIP":0.3}}'
# 5. Auto-Pilot rule create
curl -s -X POST "https://qa.keynova.ai/api/distribution/automation-rules" \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"ruleType":"RATE_THRESHOLD","scope":{},"config":{"min":1000,"max":50000},"enabled":true}'
# 6. Promotion create
curl -s -X POST "https://qa.keynova.ai/api/promotions" \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"code":"WINTER25","name":"Winter Promo","discountType":"PCT","discountValue":15,"validFrom":"2026-12-01","validTo":"2026-12-31","enabled":true}'
# 7. ResAvenue dual-auth synthetic (Format B)
curl -s -X POST "https://qa.keynova.ai/api/webhooks/resavenue/booking" \
-H 'Content-Type: application/xml' -H 'X-Forwarded-For: 203.109.97.241' \
--data-binary @resavenue-format-b-sample.xml
# Expect: 201 + <OTA_HotelResNotifRS><Success/></OTA_HotelResNotifRS>
Step 5 — Cert demo to ResAvenue
After QA smoke green:
- Notify Manish that QA is live with all bundle features.
- Ask him to push the cert checklist test bookings (per v2 email section 6).
- Drive the outbound checklist (rate push, restriction push, MinStay/MaxStay, single-pax divergence, allocation caps).
- Capture screenshots / log excerpts per checklist item.
Rollback plan
If smoke fails:
# Revert to pre-bundle master tips (use git reflog on each repo to find pre-merge SHAs)
for r in <list>; do
cd /c/CLProjects/HMP/$r
git reset --hard <pre-merge-sha>
git push --force-with-lease origin master
done
# Rebuild + redeploy
bash scripts/deploy-qa.sh
Rollback is destructive — use --force-with-lease and double-check tip SHAs first.
Known issues / gotchas
- Pre-existing TS errors in
hmp-reservation-service/src/booking-engine/booking-engine.service.ts(express types, arithmetic on Decimal, GUEST_ERASED enum) are NOT introduced by this bundle. Build script's|| truecontinues past these. @hmp/service-clientstoken in.npmrcrotates — refresh via Azure DevOps PAT before publishing ifnpm view ... versionreturns 401.- First-time deploy of new tables:
prisma db push --accept-data-lossmay be needed if a stale dev DB has conflicting columns. New tables ship withIF NOT EXISTSso existing rows are preserved. AP-T11-014discount persistence —Reservation.totalDiscount+appliedPromotionscolumns are NOT yet added (analytics deferred to v2). Today the promo amount carries throughReservation.discountValuefield at create time.