Skip to content
Closed
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
174 changes: 174 additions & 0 deletions .github/workflows/build-deploy-apim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: APIM Build & Deploy

permissions:
id-token: write
contents: read

on:
push:
branches:
- main
- 'task/DOSIS*'

jobs:
metadata:
name: "Get CI/CD metadata"
uses: ./.github/workflows/metadata.yaml

build-and-deploy:
name: "Build and Deploy API"
runs-on: ubuntu-latest
needs: metadata
env:
ENVIRONMENT: internal-dev
API_NAME: dos-search
FHIR_VERSION: FHIR_R4
WORKSPACE: ${{ needs.metadata.outputs.workspace }} # branch name or PR ref

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'

- name: Set up yq
run: |
sudo wget https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -O /usr/local/bin/yq
sudo chmod +x /usr/local/bin/yq

- name: Install proxygen CLI
run: |
pip install proxygen-cli
echo "$HOME/.local/bin" >> $GITHUB_PATH
echo "$HOME/.proxygen/bin" >> $GITHUB_PATH

- name: Verify workspace variable
run: |
echo "Workspace: ${{ env.WORKSPACE }}"
echo "Environment: ${{ env.ENVIRONMENT }}"
echo "API Name: ${{ env.API_NAME }}"
echo "FHIR Version: ${{ env.FHIR_VERSION }}"

- name: Backup original OAS file
run: |
cp docs/specification/dos-search.yaml docs/specification/dos-search.yaml.backup

- name: Preprocess OAS file
run: |
# Prefix title with workspace tag
yq eval '.info.title = "[" + "${{ env.WORKSPACE }}" + "] " + .info.title' \
docs/specification/dos-search.yaml.backup > docs/specification/dos-search.yaml

- name: Display modified OAS info
run: |
echo "Modified OAS title:"
yq eval '.info.title' docs/specification/dos-search.yaml

# - name: Validate OpenAPI spec
# run: |
# npx @redocly/cli lint docs/specification/dos-search.yaml --format=stylish

# - name: Security scan OpenAPI spec
# run: |
# # Optional: Add security scanning
# echo "Running security checks..."
# # npx @42crunch/api-security-audit docs/specification/dos-search.yaml || true

- name: Deploy to APIM
run: |
API_INSTANCE_NAME="${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}"
echo "Deploying API instance: ${API_INSTANCE_NAME}"

proxygen instance deploy \
"${{ env.ENVIRONMENT }}" \
"${API_INSTANCE_NAME}" \
"docs/specification/dos-search.yaml"

- name: Post-deployment verification
run: |
API_INSTANCE_NAME="${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}"
echo "Verifying deployment of: ${API_INSTANCE_NAME}"

# List instances and check if our API exists
if proxygen instance list "${{ env.ENVIRONMENT }}" | grep -q "${API_INSTANCE_NAME}"; then
echo "✅ API instance deployed successfully: ${API_INSTANCE_NAME}"
else
echo "❌ API instance not found: ${API_INSTANCE_NAME}"
echo "Available instances:"
proxygen instance list "${{ env.ENVIRONMENT }}"
exit 1
fi

- name: Generate deployment report
if: always()
run: |
cat > deployment-report.md << EOF
# Deployment Report

## Details
- **Environment**: ${{ env.ENVIRONMENT }}
- **API Name**: ${{ env.API_NAME }}
- **FHIR Version**: ${{ env.FHIR_VERSION }}
- **Workspace**: ${{ env.WORKSPACE }}
- **Instance Name**: ${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}
- **Commit**: ${{ github.sha }}
- **Branch**: ${{ github.ref_name }}
- **Actor**: ${{ github.actor }}
- **Timestamp**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")

## Status
- Validation: ${{ job.status == 'success' && '✅ Passed' || '❌ Failed' }}
- Deployment: ${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}

## Links
- [Workflow Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
- [Commit](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }})
EOF

- name: Upload deployment artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: deployment-artifacts-${{ env.WORKSPACE }}
path: |
docs/specification/dos-search.yaml
docs/specification/dos-search.yaml.backup
deployment-report.md
retention-days: 30

- name: Cleanup on failure
if: failure()
run: |
echo "Deployment failed, attempting cleanup..."
API_INSTANCE_NAME="${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}"

# Optional: Remove failed deployment
# proxygen instance delete "${{ env.ENVIRONMENT }}" "${API_INSTANCE_NAME}" || true

echo "Cleanup completed"

notify:
name: "Notify deployment status"
runs-on: ubuntu-latest
needs: [metadata, build-and-deploy]
if: always()

steps:
- name: Notify on success
if: needs.build-and-deploy.result == 'success'
run: |
echo "🎉 Deployment successful!"
echo "Environment: internal-dev"
echo "API Instance: ${{ needs.metadata.outputs.workspace }}-dos-search_FHIR_R4"
# Add notification logic here (Slack, Teams, email, etc.)

- name: Notify on failure
if: needs.build-and-deploy.result == 'failure'
run: |
echo "💥 Deployment failed!"
echo "Check the workflow logs for details"
# Add error notification logic here
7 changes: 7 additions & 0 deletions infrastructure/stacks/gp_search/s3.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ module "s3" {
force_destroy = true
s3_logging_bucket = local.s3_logging_bucket
}

module "proxygen-s3" {
source = "../../modules/s3"
bucket_name = "${local.resource_prefix}-${var.s3_bucket_name}-proxygen"
force_destroy = true
s3_logging_bucket = local.s3_logging_bucket
}
27 changes: 27 additions & 0 deletions infrastructure/stacks/gp_search/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
resource "aws_secretsmanager_secret" "proxygen_private_key" {
# checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
# checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
name = "/${var.project}/${var.environment}/proxygen-private-key"
description = "Private key for proxygen"
}

resource "aws_secretsmanager_secret" "proxygen_public_key" {
# checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
# checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
name = "/${var.project}/${var.environment}/proxygen-public-key"
description = "Public key for proxygen"
}

resource "aws_secretsmanager_secret" "proxygen_key_id" {
# checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
# checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
name = "/${var.project}/${var.environment}/proxygen-key-id"
description = "Key id for proxygen"
}

resource "aws_secretsmanager_secret" "proxygen_client_id" {
# checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
# checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405
name = "/${var.project}/${var.environment}/proxygen-client-id"
description = "Client id for proxygen"
}
Loading
Loading