diff --git a/.github/workflows/ci-security.yaml b/.github/workflows/ci-security.yaml index 9d51bb72514f..6f3e9f0cc4ac 100644 --- a/.github/workflows/ci-security.yaml +++ b/.github/workflows/ci-security.yaml @@ -14,11 +14,9 @@ env: SEMGREP_IMAGE: semgrep/semgrep:1.167.0@sha256:06938c1f365d3f67b8cedd8bc117607ae64253f88a0e768e9da9408548927dd6 jobs: - # Job to decide if we should run language-specific semgrep scans. + # Job to decide which path-scoped semgrep scans need to run. # See .github/actions/paths-filter/README.md for filter semantics - # NOTE: With token auth, paths-filter uses pulls.listFiles which caps at - # 3000 changed files. PRs exceeding that will silently truncate, but the - # outputs default to 'true' so scans run unconditionally (safe fallback). + # Pushes and PRs above GitHub's 3000-file API limit run every scan. changes: runs-on: ubuntu-latest timeout-minutes: 5 @@ -28,18 +26,24 @@ jobs: contents: read pull-requests: read outputs: - python: ${{ steps.filter.outputs.python || 'true' }} - go: ${{ steps.filter.outputs.go || 'true' }} - rust: ${{ steps.filter.outputs.rust || 'true' }} - js: ${{ steps.filter.outputs.js || 'true' }} - products-frontend: ${{ steps.filter.outputs.products-frontend || 'true' }} + python: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.python || 'true' }} + go: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.go || 'true' }} + rust: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.rust || 'true' }} + js: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.js || 'true' }} + products-frontend: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.products-frontend || 'true' }} + devex: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.devex || 'true' }} + test-rules: ${{ steps.oversized.outputs.force_all || steps.filter.outputs.test-rules || 'true' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: clean: false + - name: Force all scans for oversized pull requests + id: oversized + if: github.event_name == 'pull_request' && github.event.pull_request.changed_files > 3000 + run: echo "force_all=true" >> "$GITHUB_OUTPUT" - uses: ./.github/actions/paths-filter id: filter - if: github.event_name != 'push' # Run all scans on master push + if: github.event_name != 'push' && steps.oversized.outputs.force_all != 'true' with: filters: | python: @@ -72,6 +76,21 @@ jobs: - 'products/**' - '.semgrep/rules/security/prefer-codegen-api.yaml' - '.github/workflows/ci-security.yaml' + # Keep these paths aligned with semgrep-devex's scan targets. + devex: + - 'bin/**' + - 'common/**' + - 'ee/**' + - 'frontend/**' + - 'packages/**' + - 'posthog/**' + - 'products/**' + - '.semgrep/rules/devex/**' + - '.github/workflows/ci-security.yaml' + # Rule tests only read fixtures under .semgrep/. + test-rules: + - '.semgrep/**' + - '.github/workflows/ci-security.yaml' semgrep-python: needs: changes @@ -331,6 +350,8 @@ jobs: # - ERROR-severity rules fail the job on any finding (regression guards). # See `.semgrep/rules/devex/README.md`. semgrep-devex: + needs: changes + if: needs.changes.outputs.devex == 'true' runs-on: ubuntu-latest timeout-minutes: 20 @@ -382,6 +403,8 @@ jobs: bin/ common/ ee/ frontend/ packages/ posthog/ products/ semgrep-test-rules: + needs: changes + if: needs.changes.outputs.test-rules == 'true' runs-on: ubuntu-latest timeout-minutes: 10