Skip to main content

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​

#CheckVerify
1All ticket merges on masterSee master tips table below
2@hmp/service-clients@1.12.1 published to Azure Artifactsnpm view @hmp/service-clients version
3Local Docker daemon runningdocker info
4SSH key ~/.ssh/hmp-pilot worksssh -i ~/.ssh/hmp-pilot ubuntu@43.204.247.178 'echo ok'
5envs/.env.qa-aws has INTERNAL_SERVICE_TOKEN and other secretsgrep INTERNAL_SERVICE_TOKEN envs/.env.qa-aws

Master tips at start of deploy (final, all backlog cleared)​

RepoMaster tipLast shipped
hmp-shared-packagese3bae68@hmp/service-clients@1.12.1 published
hmp-property-service12c617bautoFlippedToManual propagation + SINGLE_PAX_ADJUSTMENT AriCellField + writeSinglePaxAdjustment handler (migration 20260630_ari_cell_field_single_pax)
hmp-channel-service072bafbT15 backend (xml-builder diverged BaseByGuestAmt)
hmp-reservation-service12272abT14 backend (preview() promotion integration)
hmp-api-gateway3bde050T14 /promotions routing
hmp-web-dashboardb796ae1T15 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 → :qa for all 19 images
  • Save tarballs, scp to EC2, docker load
  • docker compose down && docker compose up -d on EC2 with --env-file .env.qa-aws
  • Wait for health checks
  • prisma db push on each schema-bearing service (15 services) — picks up the new tables:
    • ari_automation_rules (T12) — property-service
    • channel_allocation_policies (T13) — channel-service
    • promotions + promotion_rate_plan_links + promotion_channel_links (T14) — property-service
    • RatePlanRate.mode + singlePaxAdjustment columns (T15) — property-service
  • Seed scripts (seed-master.sh)
  • Re-mint INTERNAL_SERVICE_TOKEN on 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:

  1. Notify Manish that QA is live with all bundle features.
  2. Ask him to push the cert checklist test bookings (per v2 email section 6).
  3. Drive the outbound checklist (rate push, restriction push, MinStay/MaxStay, single-pax divergence, allocation caps).
  4. 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 || true continues past these.
  • @hmp/service-clients token in .npmrc rotates — refresh via Azure DevOps PAT before publishing if npm view ... version returns 401.
  • First-time deploy of new tables: prisma db push --accept-data-loss may be needed if a stale dev DB has conflicting columns. New tables ship with IF NOT EXISTS so existing rows are preserved.
  • AP-T11-014 discount persistence — Reservation.totalDiscount + appliedPromotions columns are NOT yet added (analytics deferred to v2). Today the promo amount carries through Reservation.discountValue field at create time.