From f9c1213bfd6637198b03cd9b9b4d660fd329472e Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Thu, 9 Apr 2026 13:14:07 -0700 Subject: [PATCH] feat: consolidate PR gates and harden security scans (zero-harm version) --- .github/workflows/.unit-tests.yml | 104 ++++++++++++++++++++++++++++ .github/workflows/analysis.yml | 111 +++--------------------------- .github/workflows/pr-open.yml | 14 +++- 3 files changed, 125 insertions(+), 104 deletions(-) create mode 100644 .github/workflows/.unit-tests.yml diff --git a/.github/workflows/.unit-tests.yml b/.github/workflows/.unit-tests.yml new file mode 100644 index 000000000..6a326338f --- /dev/null +++ b/.github/workflows/.unit-tests.yml @@ -0,0 +1,104 @@ +name: .Unit Tests + +on: + workflow_call: + secrets: + SONAR_TOKEN_BACKEND: + required: true + SONAR_TOKEN_FRONTEND: + required: true + +jobs: + backend-tests: + name: Backend + runs-on: ubuntu-24.04 + timeout-minutes: 5 + services: + postgres: + image: postgres + env: + POSTGRES_PASSWORD: default + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v6 + - uses: bcgov/action-test-and-analyse@v2 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_BACKEND }} + with: + commands: | + npm ci + npm run lint + npm run test:cov + dir: backend + node_version: "22" + sonar_args: > + -Dsonar.exclusions=**/coverage/**,**/node_modules/**,**/*spec.ts + -Dsonar.organization=bcgov-sonarcloud + -Dsonar.projectKey=quickstart-openshift_backend + -Dsonar.sources=src + -Dsonar.test.inclusions=**/*spec.ts + -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + sonar_token: ${{ env.SONAR_TOKEN }} + dep_scan: warning + supply_scan: true + triggers: ('backend/') + + frontend-tests: + name: Frontend + runs-on: ubuntu-24.04 + timeout-minutes: 5 + steps: + - uses: actions/checkout@v6 + - uses: bcgov/action-test-and-analyse@v2 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_FRONTEND }} + with: + commands: | + npm ci + npm run lint + npm run test:cov + dir: frontend + node_version: "22" + sonar_args: >- + -Dsonar.exclusions=**/coverage/**,**/node_modules/**,**/*spec.ts + -Dsonar.organization=bcgov-sonarcloud + -Dsonar.projectKey=quickstart-openshift_frontend + -Dsonar.sources=src + -Dsonar.test.inclusions=**/*spec.ts + -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + sonar_token: ${{ env.SONAR_TOKEN }} + dep_scan: warning + supply_scan: true + triggers: ('frontend/') + + trivy: + name: Security + permissions: + security-events: write + runs-on: ubuntu-slim + timeout-minutes: 1 + steps: + - uses: actions/checkout@v6 + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@v0.35.0 + with: + format: "sarif" + output: "trivy-results.sarif" + ignore-unfixed: true + scan-type: "fs" + scanners: "vuln,secret,misconfig" + severity: "CRITICAL,HIGH" + exit-code: "1" + trivy-config: ".github/trivy.yaml" + trivyignores: ".trivyignore" + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: "trivy-results.sarif" diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 820794e0f..63b2d25fc 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -3,8 +3,6 @@ name: Analysis on: push: branches: [main] - pull_request: - types: [opened, reopened, synchronize, ready_for_review, converted_to_draft] schedule: - cron: "0 11 * * 0" # 3 AM PST = 12 PM UDT, runs sundays workflow_dispatch: @@ -16,108 +14,19 @@ concurrency: permissions: {} jobs: - backend-tests: - name: Backend Tests - if: (! github.event.pull_request.draft) - runs-on: ubuntu-24.04 - timeout-minutes: 5 - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: default - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - steps: - - uses: bcgov/action-test-and-analyse@8f699e3fd3fadd9a6adf6f4b1f2638ef7ecfefb9 # v2.0.0 - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_BACKEND }} - with: - commands: | - npm ci - npm run lint - npm run test:cov - dir: backend - node_version: "22" - sonar_args: > - -Dsonar.exclusions=**/coverage/**,**/node_modules/**,**/*spec.ts - -Dsonar.organization=bcgov-sonarcloud - -Dsonar.projectKey=quickstart-openshift_backend - -Dsonar.sources=src - -Dsonar.test.inclusions=**/*spec.ts - -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info - sonar_token: ${{ env.SONAR_TOKEN }} - dep_scan: warning - supply_scan: true - triggers: ('backend/') - - frontend-tests: - name: Frontend Tests - if: (! github.event.pull_request.draft) - runs-on: ubuntu-24.04 - timeout-minutes: 5 - steps: - - uses: bcgov/action-test-and-analyse@8f699e3fd3fadd9a6adf6f4b1f2638ef7ecfefb9 # v2.0.0 - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_FRONTEND }} - with: - commands: | - npm ci - npm run lint - npm run test:cov - dir: frontend - node_version: "22" - sonar_args: > - -Dsonar.exclusions=**/coverage/**,**/node_modules/**,**/*spec.ts - -Dsonar.organization=bcgov-sonarcloud - -Dsonar.projectKey=quickstart-openshift_frontend - -Dsonar.sources=src - -Dsonar.test.inclusions=**/*spec.ts - -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info - sonar_token: ${{ env.SONAR_TOKEN }} - dep_scan: warning - supply_scan: true - triggers: ('frontend/') - - # https://github.com/marketplace/actions/aqua-security-trivy - trivy: - name: Trivy Security Scan - if: (! github.event.pull_request.draft) - continue-on-error: true - permissions: - security-events: write - runs-on: ubuntu-slim - timeout-minutes: 1 - steps: - - uses: actions/checkout@v6 - - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 - with: - format: "sarif" - output: "trivy-results.sarif" - ignore-unfixed: true - scan-type: "fs" - scanners: "vuln,secret,misconfig" - severity: "CRITICAL,HIGH" - trivy-config: ".github/trivy.yaml" - trivyignores: ".trivyignore" - - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v4 - with: - sarif_file: "trivy-results.sarif" + unit-tests: + name: Unit Tests + uses: ./.github/workflows/.unit-tests.yml + secrets: + SONAR_TOKEN_BACKEND: ${{ secrets.SONAR_TOKEN_BACKEND }} + SONAR_TOKEN_FRONTEND: ${{ secrets.SONAR_TOKEN_FRONTEND }} results: name: Analysis Results - needs: [backend-tests, frontend-tests] - if: (! github.event.pull_request.draft) + needs: [unit-tests] + if: always() runs-on: ubuntu-slim steps: - - if: contains(needs.*.result, 'failure')||contains(needs.*.result, 'canceled') - run: echo "At least one job has failed." && exit 1 + - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'canceled') + run: exit 1 - run: echo "Success!" diff --git a/.github/workflows/pr-open.yml b/.github/workflows/pr-open.yml index a94efa620..cc8c4ea9f 100644 --- a/.github/workflows/pr-open.yml +++ b/.github/workflows/pr-open.yml @@ -50,12 +50,20 @@ jobs: needs: [deploys] uses: ./.github/workflows/.tests.yml + unit-tests: + name: Unit Tests + if: (! github.event.pull_request.draft) + uses: ./.github/workflows/.unit-tests.yml + secrets: + SONAR_TOKEN_BACKEND: ${{ secrets.SONAR_TOKEN_BACKEND }} + SONAR_TOKEN_FRONTEND: ${{ secrets.SONAR_TOKEN_FRONTEND }} + results: name: PR Results - needs: [builds, deploys, tests] + needs: [builds, deploys, tests, unit-tests] if: always() runs-on: ubuntu-slim steps: - - if: contains(needs.*.result, 'failure')||contains(needs.*.result, 'canceled') - run: echo "At least one job has failed." && exit 1 + - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'canceled') + run: exit 1 - run: echo "Success!"