Skip to main content

Deployment Guide

This guide covers deployment procedures for HMP across different environments.

Environments​

EnvironmentPurposeURL
DevelopmentLocal developmentlocalhost:3000
StagingTesting & QAstaging.hmpcloud.com
ProductionLive systemapi.hmpcloud.com

Prerequisites​

Infrastructure Requirements​

  • Kubernetes cluster (1.25+)
  • PostgreSQL 14+
  • Redis 7+
  • S3-compatible storage
  • Container registry

Tools Required​

  • kubectl
  • Helm 3+
  • Docker
  • AWS CLI (or equivalent)

Build Process​

Building Docker Images​

# Build API image
docker build -t hmp/api:latest -f docker/Dockerfile.api .

# Build services
docker build -t hmp/reservation-service:latest -f docker/Dockerfile.service ./packages/services/reservation
docker build -t hmp/guest-service:latest -f docker/Dockerfile.service ./packages/services/guest
# ... other services

Tagging Images​

# Tag with version
docker tag hmp/api:latest hmp/api:v1.2.3

# Tag with commit SHA
docker tag hmp/api:latest hmp/api:$(git rev-parse --short HEAD)

Pushing to Registry​

# Login to registry
docker login registry.hmpcloud.com

# Push images
docker push hmp/api:v1.2.3
docker push hmp/reservation-service:v1.2.3

Kubernetes Deployment​

Namespace Setup​

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: hmp-production
labels:
environment: production

Configuration​

# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: hmp-config
namespace: hmp-production
data:
NODE_ENV: production
API_PORT: "3000"
LOG_LEVEL: info

Secrets​

# k8s/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: hmp-secrets
namespace: hmp-production
type: Opaque
data:
DATABASE_URL: <base64-encoded>
REDIS_URL: <base64-encoded>
JWT_SECRET: <base64-encoded>

Deployment​

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hmp-api
namespace: hmp-production
spec:
replicas: 3
selector:
matchLabels:
app: hmp-api
template:
metadata:
labels:
app: hmp-api
spec:
containers:
- name: api
image: hmp/api:v1.2.3
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: hmp-config
- secretRef:
name: hmp-secrets
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5

Service​

# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: hmp-api
namespace: hmp-production
spec:
selector:
app: hmp-api
ports:
- port: 80
targetPort: 3000
type: ClusterIP

Ingress​

# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hmp-api
namespace: hmp-production
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- api.hmpcloud.com
secretName: hmp-api-tls
rules:
- host: api.hmpcloud.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hmp-api
port:
number: 80

Helm Deployment​

Chart Structure​

helm/hmp/
├── Chart.yaml
├── values.yaml
├── values-staging.yaml
├── values-production.yaml
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
└── ...

Install/Upgrade​

# Install
helm install hmp ./helm/hmp \
--namespace hmp-production \
--values ./helm/hmp/values-production.yaml

# Upgrade
helm upgrade hmp ./helm/hmp \
--namespace hmp-production \
--values ./helm/hmp/values-production.yaml \
--set image.tag=v1.2.3

Database Migrations​

Pre-Deployment Migrations​

# Run migrations before deploying new version
kubectl run migrations \
--namespace hmp-production \
--image hmp/api:v1.2.3 \
--restart=Never \
--env-from=secret/hmp-secrets \
-- npm run db:migrate

# Verify migration completed
kubectl logs migrations -n hmp-production

Rollback Migrations​

# If deployment fails, rollback migrations
kubectl run migration-rollback \
--namespace hmp-production \
--image hmp/api:v1.2.3 \
--restart=Never \
--env-from=secret/hmp-secrets \
-- npm run db:migrate:rollback

CI/CD Pipeline​

GitHub Actions​

# .github/workflows/deploy.yml
name: Deploy

on:
push:
branches: [main]
release:
types: [published]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Build and push Docker images
run: |
docker build -t hmp/api:${{ github.sha }} .
docker push hmp/api:${{ github.sha }}

deploy-staging:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to staging
run: |
helm upgrade hmp ./helm/hmp \
--namespace hmp-staging \
--set image.tag=${{ github.sha }}

deploy-production:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'release'
steps:
- name: Deploy to production
run: |
helm upgrade hmp ./helm/hmp \
--namespace hmp-production \
--set image.tag=${{ github.event.release.tag_name }}

Rollback Procedures​

Kubernetes Rollback​

# View deployment history
kubectl rollout history deployment/hmp-api -n hmp-production

# Rollback to previous version
kubectl rollout undo deployment/hmp-api -n hmp-production

# Rollback to specific revision
kubectl rollout undo deployment/hmp-api -n hmp-production --to-revision=5

Helm Rollback​

# View release history
helm history hmp -n hmp-production

# Rollback to previous release
helm rollback hmp -n hmp-production

# Rollback to specific revision
helm rollback hmp 5 -n hmp-production

Monitoring​

Health Checks​

// src/health.ts
app.get('/health', (req, res) => {
res.json({ status: 'healthy', version: process.env.VERSION });
});

app.get('/ready', async (req, res) => {
const dbHealthy = await checkDatabaseConnection();
const redisHealthy = await checkRedisConnection();

if (dbHealthy && redisHealthy) {
res.json({ status: 'ready' });
} else {
res.status(503).json({ status: 'not ready' });
}
});

Metrics​

Prometheus metrics exposed at /metrics:

hmp_http_requests_total{method="GET", path="/reservations", status="200"} 1234
hmp_http_request_duration_seconds{method="GET", path="/reservations"} 0.045
hmp_database_connections_active 10
hmp_database_connections_idle 5

Logging​

Structured JSON logs:

{
"level": "info",
"message": "Request completed",
"timestamp": "2026-01-22T10:30:00Z",
"requestId": "req_abc123",
"method": "POST",
"path": "/api/v1/reservations",
"status": 201,
"duration": 150
}

Security Checklist​

Pre-deployment security verification:

  • All secrets in secret manager
  • No hardcoded credentials
  • TLS certificates valid
  • Network policies configured
  • RBAC properly configured
  • Container runs as non-root
  • Resource limits set
  • Security scanning passed