Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/deploy-azure-aks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ jobs:
- tenant-service
- enrollment-import-service
- trading-partner-service
- premium-billing-service
- appeals-service
- rfai-service
include:
# Most .NET services need repo root as context to reach
# src/services/shared/CloudHealthOffice.Infrastructure/ and/or src/engines/.
Expand Down Expand Up @@ -125,6 +128,12 @@ jobs:
build_context: '.'
- service: reference-data-service
build_context: '.'
- service: premium-billing-service
build_context: '.'
- service: appeals-service
build_context: '.'
- service: rfai-service
build_context: '.'

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -363,6 +372,19 @@ jobs:
src/portal/CloudHealthOffice.Portal/k8s/portal-deployment.yaml \
| kubectl apply -f -

- name: Apply backend service manifests
run: |
ACR="${{ env.REGISTRY }}"
SHA="sha-${{ github.sha }}"
for manifest in src/services/*/k8s/*.yaml; do
Comment on lines +375 to +379
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manifests expect a secret named "cosmos-db-secret" with "endpoint"/"key" keys, but this workflow creates "cosmosdb-secret" with only a "connectionString" key (earlier in the job). With this new apply loop, deployments will fail due to missing secrets/keys unless the secret name/shape is aligned between the workflow and manifests.

Copilot uses AI. Check for mistakes.
echo "Applying ${manifest}..."
sed \
-e "s|choacrhy6h2vdulfru6.azurecr.io/cloudhealthoffice-|${ACR}/cloudhealthoffice-|g" \
-e "s|:latest|:${SHA}|g" \
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tag rewrite here replaces every ":latest" with the SHA tag, which will also mutate manifests that still reference ghcr.io images (encounter-service, fhir-service, risk-adjustment-service, smart-auth-service, etc.). Those sha-* tags won’t exist in GHCR (and several of those images aren’t built by this workflow), so deployments will fail to pull. Scope the substitution (and/or the apply loop) to only images built/pushed to ${ACR} by this workflow.

Suggested change
-e "s|:latest|:${SHA}|g" \
-e "s|\(${ACR}/cloudhealthoffice-[^:]*\):latest|\1:${SHA}|g" \

Copilot uses AI. Check for mistakes.
"$manifest" \
| kubectl apply -f -
done

- name: Apply portal ingress (portal.cloudhealthoffice.com)
run: kubectl apply -f infrastructure/k8s/portal-ingress.yaml

Expand Down
4 changes: 4 additions & 0 deletions scripts/deploy/deploy-core-services.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ SERVICES=(
eligibility-service
coverage-service
enrollment-import-service
premium-billing-service
appeals-service
rfai-service
claims-scrubbing-service
Comment on lines +55 to +58
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deploy-core-services.sh verifies service health by port-forwarding and calling /health/live for every service. claims-scrubbing-service (Node.js) exposes /livez and /readyz (not /health/live), so after adding it to SERVICES this script will report it as unhealthy even when it’s running. Update the verification logic to use /livez for claims-scrubbing-service (or make the endpoint path configurable per service).

Copilot uses AI. Check for mistakes.
)

info() { echo "▸ $*"; }
Expand Down
112 changes: 112 additions & 0 deletions src/services/appeals-service/k8s/appeals-service-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: appeals-service-config
namespace: cloudhealthoffice
data:
ASPNETCORE_ENVIRONMENT: "Production"
CosmosDb__DatabaseName: "CloudHealthOffice"
AzureStorage__ContainerName: "appeal-attachments"
ClaimsService__BaseUrl: "http://claims-service.cloudhealthoffice"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: appeals-service
namespace: cloudhealthoffice
labels:
app: appeals-service
tier: backend
spec:
replicas: 1
selector:
Comment on lines +20 to +22
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says appeals-service should run with 2 replicas, but this manifest sets replicas: 1. Either update the manifest to match the intended replica count, or adjust the PR description so it accurately reflects the deployment configuration.

Copilot uses AI. Check for mistakes.
matchLabels:
app: appeals-service
template:
metadata:
labels:
app: appeals-service
tier: backend
spec:
containers:
- name: appeals-service
image: choacrhy6h2vdulfru6.azurecr.io/cloudhealthoffice-appeals-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
protocol: TCP
env:
- name: ASPNETCORE_ENVIRONMENT
valueFrom:
configMapKeyRef:
name: appeals-service-config
key: ASPNETCORE_ENVIRONMENT
- name: CosmosDb__AccountEndpoint
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: endpoint
- name: CosmosDb__AccountKey
Comment on lines +45 to +50
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

appeals-service Program.cs reads Cosmos DB configuration from "CosmosDb:Endpoint" and "CosmosDb:Key" and throws if they are missing, but this manifest sets "CosmosDb__AccountEndpoint" (and "CosmosDb__AccountKey" below). This will result in Endpoint/Key being unset at runtime and the container crashing on startup. Use env var names that match what the service reads (CosmosDb__Endpoint / CosmosDb__Key) or update the service to read AccountEndpoint/AccountKey consistently.

Suggested change
- name: CosmosDb__AccountEndpoint
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: endpoint
- name: CosmosDb__AccountKey
- name: CosmosDb__Endpoint
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: endpoint
- name: CosmosDb__Key

Copilot uses AI. Check for mistakes.
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: key
Comment on lines +45 to +54
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Deployment references secret "cosmos-db-secret" (keys "endpoint"/"key"), but the AKS deploy workflow currently creates "cosmosdb-secret" with only a "connectionString" key. As-is, the referenced secret/keys will be missing and the pod will fail to start. Align the secret name/keys between the workflow and manifests.

Suggested change
- name: CosmosDb__AccountEndpoint
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: endpoint
- name: CosmosDb__AccountKey
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: key
- name: CosmosDb__ConnectionString
valueFrom:
secretKeyRef:
name: cosmosdb-secret
key: connectionString

Copilot uses AI. Check for mistakes.
- name: CosmosDb__DatabaseName
valueFrom:
configMapKeyRef:
name: appeals-service-config
key: CosmosDb__DatabaseName
- name: AzureStorage__ConnectionString
valueFrom:
secretKeyRef:
name: azure-storage-secret
key: connectionString
- name: AzureStorage__ContainerName
valueFrom:
configMapKeyRef:
name: appeals-service-config
key: AzureStorage__ContainerName
- name: ClaimsService__BaseUrl
valueFrom:
configMapKeyRef:
name: appeals-service-config
key: ClaimsService__BaseUrl
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
name: appeals-service
namespace: cloudhealthoffice
labels:
app: appeals-service
spec:
type: ClusterIP
selector:
app: appeals-service
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: claims-scrubbing-service-config
namespace: cloudhealthoffice
data:
NODE_ENV: "production"
KAFKA_BOOTSTRAP_SERVERS: "kafka.cloudhealthoffice:9092"
KAFKA_CLIENT_ID: "claims-scrubbing-service"
KAFKA_CONSUMER_GROUP: "claims-scrubbers"
INBOUND_CLAIMS_TOPIC: "claims.inbound"
CLEAN_CLAIMS_TOPIC: "claims.clean"
FLAGGED_CLAIMS_TOPIC: "claims.flagged"
REJECTED_CLAIMS_TOPIC: "claims.rejected"
COSMOS_DATABASE: "CloudHealthOffice"
COSMOS_RULES_CONTAINER: "ScrubRules"
COSMOS_AUDIT_CONTAINER: "ScrubAudit"
CLAIMS_CONTAINER: "claims-archive"
PARALLEL_RULES: "true"
MAX_RULE_CONCURRENCY: "10"
RULE_TIMEOUT_MS: "5000"
CACHE_RULES: "true"
RULE_CACHE_TTL: "300"
MAX_ERRORS_FOR_REJECTION: "3"
MAX_WARNINGS_FOR_FLAGGING: "5"
ENABLE_DUPLICATE_DETECTION: "true"
ENABLE_MEDICAL_NECESSITY: "true"
ENABLE_NCCI_EDITS: "true"
ENABLE_AUTO_CORRECTION: "false"
ENABLE_REALTIME_NPI: "false"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: claims-scrubbing-service
namespace: cloudhealthoffice
labels:
app: claims-scrubbing-service
tier: backend
spec:
replicas: 1
selector:
Comment on lines +40 to +42
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says claims-scrubbing-service should run with 2 replicas, but this manifest sets replicas: 1. Either update the manifest to match the intended replica count, or adjust the PR description so it accurately reflects the deployment configuration.

Copilot uses AI. Check for mistakes.
matchLabels:
app: claims-scrubbing-service
template:
metadata:
labels:
app: claims-scrubbing-service
tier: backend
spec:
containers:
- name: claims-scrubbing-service
image: choacrhy6h2vdulfru6.azurecr.io/cloudhealthoffice-claims-scrubbing-service:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
name: http
protocol: TCP
envFrom:
- configMapRef:
name: claims-scrubbing-service-config
env:
- name: KAFKA_SASL_USERNAME
valueFrom:
secretKeyRef:
name: kafka-secret
key: saslUsername
optional: true
- name: KAFKA_SASL_PASSWORD
valueFrom:
secretKeyRef:
name: kafka-secret
key: saslPassword
optional: true
- name: COSMOS_ENDPOINT
valueFrom:
secretKeyRef:
name: cosmos-db-secret
key: endpoint
Comment on lines +78 to +79
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Deployment expects Cosmos DB endpoint in secret "cosmos-db-secret" (key "endpoint"), but the AKS deploy workflow currently creates "cosmosdb-secret" and only provides a "connectionString" key. If this service is deployed via the workflow, it will fail due to the missing secret/keys. Align the secret name/keys between the workflow and manifests.

Suggested change
name: cosmos-db-secret
key: endpoint
name: cosmosdb-secret
key: connectionString

Copilot uses AI. Check for mistakes.
- name: STORAGE_CONNECTION_STRING
valueFrom:
secretKeyRef:
name: azure-storage-secret
key: connectionString
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /livez
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /readyz
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
name: claims-scrubbing-service
namespace: cloudhealthoffice
labels:
app: claims-scrubbing-service
spec:
type: ClusterIP
selector:
app: claims-scrubbing-service
ports:
- name: http
port: 80
targetPort: 3000
protocol: TCP
Loading
Loading