fix(ci): prevent secret exposure to fork PRs in neon-integration-pg-m… #2
Workflow file for this run
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
| # NixOS Runner — Local Test Workflow | ||
|
Check failure on line 1 in .github/workflows/nixos-local-test.yml
|
||
| # | ||
| # Runs all four test suites (health checks, managed DB validation, migration | ||
| # validation, PR audit) on the self-hosted NixOS runner against the PG | ||
| # instances your secrets point at (Neon / DigitalOcean / etc.). | ||
| # | ||
| # Triggers: | ||
| # - pull_request [opened, synchronize] — runs the full matrix on PG15-18 | ||
| # in parallel against the secrets for each version. Fork PRs do NOT | ||
| # receive secrets (by design — secrets stay out of untrusted PR code). | ||
| # - workflow_dispatch — pick a single PG version + cloud_provider label | ||
| # for an ad-hoc run. | ||
| # | ||
| # The NixOS runner already has psql, uv, and network access to the test PG | ||
| # instances. No Docker or local PG install needed. | ||
| # | ||
| # The cloud auth steps (AWS/GCP/Azure CLI) in managed-db-validate.yml are | ||
| # NOT replicated here — they require real cloud credentials and live cloud | ||
| # DBs, and remain manual-dispatch only in CI. | ||
| name: NixOS Local Test Workflow | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| postgres_version: | ||
| description: 'PostgreSQL major version to test against' | ||
| required: true | ||
| type: choice | ||
| options: | ||
| - '15' | ||
| - '16' | ||
| - '17' | ||
| - '18' | ||
| default: '16' | ||
| cloud_provider: | ||
| description: 'Cloud provider label (for managed DB test output)' | ||
| required: false | ||
| type: choice | ||
| options: | ||
| - direct | ||
| - aws | ||
| - gcp | ||
| - azure | ||
| default: 'direct' | ||
| pull_request: | ||
| types: [opened, synchronize] | ||
| paths: | ||
| - pgFirstAid.sql | ||
| - view_pgFirstAid.sql | ||
| - view_pgFirstAid_managed.sql | ||
| - .github/workflows/** | ||
| - testing/local-workflows/** | ||
| - .github/workflows/nixos-local-test.yml | ||
| concurrency: | ||
| group: nixos-local-test-${{ github.ref }}-${{ matrix.postgres_version }} | ||
| cancel-in-progress: true | ||
| jobs: | ||
| local-test: | ||
| runs-on: [self-hosted, nix, nixos, x86_64-linux] | ||
| permissions: | ||
| contents: read | ||
| strategy: | ||
| fail-fast: false | ||
| # ponytail: explicit per-version secret mapping — any future PG major | ||
| # added to the matrix without a corresponding leg here will fail closed | ||
| # (missing secret) instead of silently falling through to PG18. | ||
| matrix: | ||
| include: | ||
| - postgres_version: "15" | ||
| pg_host_secret: PG15_HOST | ||
| pg_port_secret: PG15_PORT | ||
| pg_user_secret: PG15_USER | ||
| pg_password_secret: PG15_PASSWORD | ||
| pg_database_secret: PG15_DATABASE | ||
| pg_database_url_secret: PG15_DATABASE_URL | ||
| - postgres_version: "16" | ||
| pg_host_secret: PG16_HOST | ||
| pg_port_secret: PG16_PORT | ||
| pg_user_secret: PG16_USER | ||
| pg_password_secret: PG16_PASSWORD | ||
| pg_database_secret: PG16_DATABASE | ||
| pg_database_url_secret: PG16_DATABASE_URL | ||
| - postgres_version: "17" | ||
| pg_host_secret: PG17_HOST | ||
| pg_port_secret: PG17_PORT | ||
| pg_user_secret: PG17_USER | ||
| pg_password_secret: PG17_PASSWORD | ||
| pg_database_secret: PG17_DATABASE | ||
| pg_database_url_secret: PG17_DATABASE_URL | ||
| - postgres_version: "18" | ||
| pg_host_secret: PG18_HOST | ||
| pg_port_secret: PG18_PORT | ||
| pg_user_secret: PG18_USER | ||
| pg_password_secret: PG18_PASSWORD | ||
| pg_database_secret: PG18_DATABASE | ||
| pg_database_url_secret: PG18_DATABASE_URL | ||
| defaults: | ||
| run: | ||
| shell: bash -l {0} | ||
| env: | ||
| PG_VERSION: ${{ matrix.postgres_version }} | ||
| PGHOST: ${{ secrets[matrix.pg_host_secret] }} | ||
| PGPORT: ${{ secrets[matrix.pg_port_secret] }} | ||
| PGUSER: ${{ secrets[matrix.pg_user_secret] }} | ||
| PGPASSWORD: ${{ secrets[matrix.pg_password_secret] }} | ||
| PGDATABASE: ${{ secrets[matrix.pg_database_secret] }} | ||
| PGSSLMODE: require | ||
| DATABASE_URL: ${{ secrets[matrix.pg_database_url_secret] }} | ||
| # cloud_provider input is undefined on pull_request — default to 'direct' | ||
| CLOUD_PROVIDER: ${{ inputs.cloud_provider || 'direct' }} | ||
| PGFIRSTAID_FAIL_SEVERITY: HIGH | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 1 | ||
| ref: ${{ github.event.pull_request.head.sha || github.ref }} | ||
| - name: Add Nix profile paths | ||
| run: | | ||
| echo "/run/current-system/sw/bin" >> "$GITHUB_PATH" | ||
| echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH" | ||
| echo "$HOME/.nix-profile/bin" >> "$GITHUB_PATH" | ||
| echo "/etc/profiles/per-user/$USER/bin" >> "$GITHUB_PATH" | ||
| - name: Validate PG connection vars | ||
| run: | | ||
| missing=0 | ||
| for var in PGHOST PGPORT PGUSER PGPASSWORD PGDATABASE; do | ||
| if [ -z "${!var}" ]; then | ||
| echo "::error::Missing required secret/env: ${var} for PG${{ matrix.postgres_version }}" | ||
| missing=1 | ||
| fi | ||
| done | ||
| if [ "$missing" -ne 0 ]; then exit 1; fi | ||
| echo "Target: PG${{ matrix.postgres_version }} @ $PGHOST:$PGPORT" | ||
| - name: Verify psql + uv | ||
| run: | | ||
| command -v psql >/dev/null 2>&1 || { echo "::error::psql not found"; exit 1; } | ||
| psql --version | ||
| command -v uv >/dev/null 2>&1 || { echo "::error::uv not found"; exit 1; } | ||
| uv --version | ||
| - name: Test — Health Check Suite | ||
| working-directory: testing/local-workflows | ||
| run: | | ||
| mkdir -p reports | ||
| ./test_db_health_checks.sh | ||
| - name: Test — Managed DB Validation | ||
| working-directory: testing/local-workflows | ||
| run: | | ||
| ./test_managed_db_validate.sh | ||
| - name: Test — Pre/Post Migration Validation | ||
| working-directory: testing/local-workflows | ||
| run: | | ||
| ./test_pre_post_migration.sh | ||
| continue-on-error: true | ||
| - name: Test — PR Audit Script | ||
| working-directory: testing/local-workflows | ||
| run: | | ||
| uv pip install --quiet psycopg2-binary 2>/dev/null || uv pip install psycopg2-binary | ||
| ./test_pr_audit.sh | ||
| continue-on-error: true | ||
| - name: Upload reports | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: test-reports-pg${{ matrix.postgres_version }} | ||
| path: testing/local-workflows/reports/ | ||
| retention-days: 14 | ||
| - name: Post summary | ||
| if: always() | ||
| run: | | ||
| { | ||
| echo "## NixOS Local Test Results — PG${{ matrix.postgres_version }}" | ||
| echo "" | ||
| echo "| Suite | Status |" | ||
| echo "|-------|--------|" | ||
| echo "| Health Check | ${{ job.status == 'success' && '✅' || '❌' }} |" | ||
| echo "| Managed DB Validate | ${{ job.status == 'success' && '✅' || '❌' }} |" | ||
| echo "| Migration Validate | ${{ job.status == 'success' && '✅' || '❌' }} |" | ||
| echo "| PR Audit | ${{ job.status == 'success' && '✅' || '❌' }} |" | ||
| echo "" | ||
| echo "Cloud provider label: ${{ inputs.cloud_provider || 'direct' }}" | ||
| } >> "$GITHUB_STEP_SUMMARY" | ||