Put resource counts on the aucore CapabilityStatement #123
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Validate Configuration | |
| on: | |
| pull_request: | |
| paths: | |
| - 'module-config/**' | |
| - 'terraform/**' | |
| - 'scripts/test_consent_default_readonly.js' | |
| - '.github/workflows/validate-config.yml' | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'module-config/**' | |
| - 'terraform/**' | |
| - 'scripts/test_consent_default_readonly.js' | |
| - '.github/workflows/validate-config.yml' | |
| # These jobs use NO secrets, so they are safe to run on PRs from forks (community | |
| # contributions). Runner selection enforces one invariant: untrusted fork code | |
| # must never execute on the self-hosted arc-runner-set. So a fork PR always runs | |
| # on a GitHub-hosted runner (free for public repos), while same-repo PRs and | |
| # pushes use vars.CI_RUNNER (the self-hosted runner) if set. Anything needing | |
| # secrets or live-server/AWS access is gated elsewhere behind maintainer-triggered | |
| # workflows, never on fork PR events. | |
| jobs: | |
| validate-yaml: | |
| name: Validate YAML Configuration | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.CI_RUNNER || 'ubuntu-latest' }} | |
| container: | |
| image: python:3.12-slim | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install dependencies | |
| run: pip install -r scripts/requirements.txt | |
| - name: Validate YAML files | |
| run: | | |
| yamllint -d "{extends: default, rules: {line-length: {max: 200}, indentation: {spaces: 2}}}" module-config/*.yaml || true | |
| echo "✅ YAML syntax validation complete" | |
| - name: Check for common issues | |
| run: | | |
| echo "Checking for common configuration issues..." | |
| # Every module-config file referenced by terraform/main.tf must exist. | |
| # Covers the package specs and the scripts mapped into config_seeding | |
| # (smart-post-authorize.js, consent-default-readonly.js): a module that | |
| # points at a missing script file fails at module startup, not at apply. | |
| # | |
| # Not a `while read` over a pipe: that runs the loop in a subshell, so | |
| # its exit only leaves the subshell and the step still passes. | |
| echo "📦 Verifying module-config file references..." | |
| missing=0 | |
| for filepath in $(grep -oE '\.\./module-config/[A-Za-z0-9._/-]+' terraform/main.tf | sed 's|\.\./||' | sort -u); do | |
| if [ -f "$filepath" ]; then | |
| echo " ✅ Found: $filepath" | |
| else | |
| echo " ❌ Missing: $filepath" | |
| missing=1 | |
| fi | |
| done | |
| # Every script referenced by a consent_service.script.file or | |
| # post_authorize_script.file classpath must also be mapped in by | |
| # terraform, or the node boots pointing at a file that is not there. | |
| echo "📜 Verifying config_seeding script references..." | |
| for script in $(grep -hoE 'classpath:/?config_seeding/[A-Za-z0-9._-]+\.js([^a-z]|$)' module-config/*.yaml | sed -e 's|.*/||' -e 's|\.js.*|.js|' | sort -u); do | |
| if grep -q "module-config/$script" terraform/main.tf; then | |
| echo " ✅ Mapped by terraform: $script" | |
| else | |
| echo " ❌ Referenced in module config but not mapped in terraform/main.tf: $script" | |
| missing=1 | |
| fi | |
| done | |
| exit $missing | |
| validate-consent-script: | |
| name: Test Consent Service Script | |
| # The consent service runs in front of every REST request on the node, so | |
| # its decision matrix is unit tested before it can be deployed. Node 24 is | |
| # the current LTS; the test has no dependencies. | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.CI_RUNNER || 'ubuntu-latest' }} | |
| container: | |
| image: node:24-slim | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run consent service tests | |
| run: node scripts/test_consent_default_readonly.js | |
| validate-terraform: | |
| name: Validate Terraform | |
| # Fork-safe: no backend, no credentials, no PR comment (fork tokens are | |
| # read-only). Contributors see the result via the check status. | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.CI_RUNNER || 'ubuntu-latest' }} | |
| # Run in a Debian container that we install Terraform into, rather than the | |
| # setup-terraform action: this works identically on GitHub-hosted runners and | |
| # on the self-hosted arc-runner-set (whose base image has no Terraform binary). | |
| container: | |
| image: debian:bookworm-slim | |
| defaults: | |
| run: | |
| working-directory: terraform | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Terraform | |
| run: | | |
| apt-get update | |
| # git is required by terraform to fetch the git:: sourced module | |
| apt-get install -y --no-install-recommends curl unzip ca-certificates git | |
| curl -fsSL "https://releases.hashicorp.com/terraform/1.15.6/terraform_1.15.6_linux_amd64.zip" -o /tmp/terraform.zip | |
| unzip -o /tmp/terraform.zip -d /usr/local/bin | |
| terraform version | |
| - name: Terraform Format Check | |
| run: terraform fmt -check -recursive | |
| continue-on-error: true | |
| - name: Terraform Init (no backend) | |
| run: terraform init -backend=false | |
| - name: Terraform Validate | |
| run: terraform validate | |
| validate-packages: | |
| name: Validate FHIR Packages | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.CI_RUNNER || 'ubuntu-latest' }} | |
| container: | |
| image: python:3.12-slim | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install dependencies | |
| run: | | |
| apt-get update | |
| apt-get install -y jq | |
| - name: Validate JSON syntax | |
| run: | | |
| echo "Validating package JSON files..." | |
| find module-config/packages -name "*.json" -type f | while read file; do | |
| echo "Checking $file..." | |
| if jq empty "$file" 2>/dev/null; then | |
| echo " ✅ Valid JSON: $file" | |
| else | |
| echo " ❌ Invalid JSON: $file" | |
| exit 1 | |
| fi | |
| done | |
| - name: Check package structure | |
| run: | | |
| echo "Checking package file structure..." | |
| find module-config/packages -name "package-*.json" -type f | while read file; do | |
| # Check for required fields | |
| if jq -e '.name and .version' "$file" >/dev/null 2>&1; then | |
| name=$(jq -r '.name' "$file") | |
| version=$(jq -r '.version' "$file") | |
| echo " ✅ $file: $name@$version" | |
| else | |
| echo " ⚠️ $file: Missing name or version field" | |
| fi | |
| done | |
| security-scan: | |
| name: Security Scan | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.CI_RUNNER || 'ubuntu-latest' }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy security scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'config' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| continue-on-error: true | |
| - name: Check for sensitive data | |
| run: | | |
| echo "Scanning for potential secrets..." | |
| # Check for common patterns that might be secrets | |
| if grep -r "password.*=.*['\"].*['\"]" --include="*.tf" --include="*.yaml" --exclude-dir=".git" .; then | |
| echo "⚠️ Warning: Found potential hardcoded passwords" | |
| fi | |
| if grep -r "secret.*=.*['\"].*['\"]" --include="*.tf" --include="*.yaml" --exclude-dir=".git" .; then | |
| echo "⚠️ Warning: Found potential hardcoded secrets" | |
| fi | |
| echo "✅ Security scan complete" |