Skip to content

Enhance health platform #32

Enhance health platform

Enhance health platform #32

Workflow file for this run

name: Continuous Integration
on:
pull_request:
branches:
- main
- develop
push:
branches:
- main
tags:
- 'v*.*.*'
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
packages: write
jobs:
lint:
name: Lint & Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8.7.0
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpm build
- name: Run ESLint
run: pnpm lint
- name: Check formatting
run: pnpm format:check
- name: Type check
run: pnpm type-check
unit-tests:
name: Unit Tests (Node ${{ matrix.node }})
runs-on: ubuntu-latest
needs: lint
strategy:
fail-fast: false
matrix:
node:
- 18
- 20
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8.7.0
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run unit test suite
run: pnpm run test:unit
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: unit-tests
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8.7.0
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run integration suite
run: pnpm run test:integration
- name: Upload integration logs
if: always()
uses: actions/upload-artifact@v4
with:
name: integration-logs
path: tests/integration
if-no-files-found: warn
security-scan:
name: Dependency Audit
runs-on: ubuntu-latest
needs: integration-tests
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8.7.0
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: pnpm audit
run: pnpm audit --audit-level=moderate || true
- name: Upload audit report
if: always()
run: pnpm audit --json > audit-report.json || true
- name: Persist audit report
if: always()
uses: actions/upload-artifact@v4
with:
name: pnpm-audit-report
path: audit-report.json
if-no-files-found: ignore
hipaa-checks:
name: HIPAA Safeguards
runs-on: ubuntu-latest
needs: integration-tests
steps:
- uses: actions/checkout@v4
- name: Scan repository for PHI indicators
run: scripts/ci/check-phi-exposure.sh
build:
name: Build Workspace Artifacts
runs-on: ubuntu-latest
needs:
- security-scan
- hipaa-checks
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8.7.0
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages and services
run: pnpm build
- name: Upload dist artifacts
uses: actions/upload-artifact@v4
with:
name: service-builds
path: |
services/**/dist
packages/**/dist
if-no-files-found: warn
container-images:
name: Build Service Images (${{ matrix.service }})
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
service: [transcription, documentation, coding]
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Derive image metadata
id: image-meta
run: echo "repository=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image
uses: docker/build-push-action@v5
with:
context: .
file: services/${{ matrix.service }}/Dockerfile
push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
tags: |
ghcr.io/${{ steps.image-meta.outputs.repository }}/${{ matrix.service }}-service:${{ github.sha }}
ghcr.io/${{ steps.image-meta.outputs.repository }}/${{ matrix.service }}-service:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs:
- container-images
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
environment:
name: staging
url: https://staging.scribemed.local
steps:
- uses: actions/checkout@v4
- name: Configure kubectl
uses: azure/k8s-set-context@v3
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBE_CONFIG_STAGING }}
- name: Apply namespace manifests
run: kubectl apply -f infrastructure/kubernetes/staging
- name: Run staging smoke tests
run: scripts/ci/health-check-staging.sh
- name: Notify Slack
if: always()
continue-on-error: true
uses: slackapi/slack-github-action@v1.25.0
with:
payload: |
{
"text": "Staging deployment ${{ job.status }} for ${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs:
- container-images
if: startsWith(github.ref, 'refs/tags/v')
environment:
name: production
url: https://app.scribemed.local
steps:
- uses: actions/checkout@v4
- name: Configure kubectl
uses: azure/k8s-set-context@v3
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBE_CONFIG_PROD }}
- name: Apply namespace manifests
run: kubectl apply -f infrastructure/kubernetes/production
- name: Run production smoke tests
run: scripts/ci/health-check-production.sh
- name: Notify Slack
if: always()
continue-on-error: true
uses: slackapi/slack-github-action@v1.25.0
with:
payload: |
{
"text": "🚀 Production deployment ${{ job.status }} for ${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}