ci: scope CI dependencies per job for faster, reliable installs #1506
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
| name: Security Scanning | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| paths: | |
| - 'src/**' | |
| - 'requirements*.txt' | |
| - 'pyproject.toml' | |
| - 'uv.lock' | |
| - '.github/workflows/security-code.yml' | |
| pull_request: | |
| branches: [ main, develop ] | |
| paths: | |
| - 'src/**' | |
| - 'requirements*.txt' | |
| - 'pyproject.toml' | |
| - 'uv.lock' | |
| - '.github/workflows/security-code.yml' | |
| schedule: | |
| - cron: '0 3 * * 0' | |
| # Per-ref concurrency: a rapid series of pushes to the same branch only runs | |
| # one security scan at a time; the newer push cancels the older. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Belt-and-suspenders: prevent any accidental implicit uv sync from firing | |
| # the SPA build hook (setup.py build_ui.sh) in this workflow. | |
| env: | |
| ORB_SKIP_UI_BUILD: "1" | |
| jobs: | |
| config: | |
| name: Configuration | |
| uses: ./.github/workflows/shared-config.yml | |
| setup-cache: | |
| name: Setup Cache | |
| needs: config | |
| uses: ./.github/workflows/cache-management.yml | |
| with: | |
| cache-type: dependencies | |
| cache-key-base: deps | |
| python-version: ${{ needs.config.outputs.default-python-version }} | |
| security-bandit: | |
| name: Bandit (Security Scan) | |
| needs: [config, setup-cache] | |
| permissions: | |
| contents: read | |
| actions: read | |
| security-events: write | |
| uses: ./.github/workflows/reusable-security.yml | |
| with: | |
| scan-type: bandit | |
| default-python-version: ${{ needs.config.outputs.default-python-version }} | |
| python-version: ${{ needs.config.outputs.default-python-version }} | |
| cache-key: ${{ needs.setup-cache.outputs.cache-key }} | |
| security-safety: | |
| name: Safety (Dependency Scan) | |
| needs: [config, setup-cache] | |
| permissions: | |
| contents: read | |
| actions: read | |
| security-events: write | |
| uses: ./.github/workflows/reusable-security.yml | |
| with: | |
| scan-type: safety | |
| default-python-version: ${{ needs.config.outputs.default-python-version }} | |
| python-version: ${{ needs.config.outputs.default-python-version }} | |
| cache-key: ${{ needs.setup-cache.outputs.cache-key }} | |
| security-semgrep: | |
| name: Semgrep (Static Analysis) | |
| needs: config | |
| permissions: | |
| contents: read | |
| actions: read | |
| security-events: write | |
| uses: ./.github/workflows/reusable-security.yml | |
| with: | |
| scan-type: semgrep | |
| default-python-version: ${{ needs.config.outputs.default-python-version }} | |
| security-trivy-fs: | |
| name: Trivy (Filesystem Scan) | |
| needs: config | |
| permissions: | |
| contents: read | |
| actions: read | |
| security-events: write | |
| uses: ./.github/workflows/reusable-security.yml | |
| with: | |
| scan-type: trivy-fs | |
| default-python-version: ${{ needs.config.outputs.default-python-version }} | |
| security-trufflehog: | |
| name: TruffleHog (Secrets Scan) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.event.before != '0000000000000000000000000000000000000000') | |
| permissions: | |
| security-events: write | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for secrets with TruffleHog | |
| uses: trufflesecurity/trufflehog@27b0417c16317ca9a472a9a8092acce143b49c55 # v3.95.9 | |
| with: | |
| path: ./ | |
| base: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }} | |
| head: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.event.after }} | |
| extra_args: --debug --only-verified | |
| dependency-review: | |
| name: Dependency Review | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v4 | |
| with: | |
| fail-on-severity: moderate | |
| allow-licenses: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense | |
| # The dependency-review action sometimes reports compound SPDX expressions | |
| # (e.g. 'MIT AND HPND-Markus-Kuhn') for packages that are actually plain MIT | |
| # in their PyPI METADATA. The compound string is treated as a single | |
| # non-allowlisted license. Each exemption below has been verified by reading | |
| # the package's METADATA license / License-Expression directly: | |
| # werkzeug BSD-3-Clause AND LicenseRef-scancode-unknown-license-reference -> BSD-3-Clause | |
| # lark MIT AND MPL-2.0 -> MIT (METADATA: License: MIT) | |
| # mcp MIT AND Python-2.0 -> MIT (METADATA: License: MIT) | |
| # rfc3987-syntax Apache-2.0 AND GPL-1.0-or-later AND MIT -> MIT (METADATA: License-Expression: MIT) | |
| # wcwidth MIT AND HPND-Markus-Kuhn -> MIT (METADATA: License-Expression: MIT) | |
| # lxml BSD-3-Clause AND GPL-1.0-or-later -> BSD-3-Clause (METADATA: License: BSD-3-Clause; GPL applies to a single legacy source file) | |
| # protobuf BSD-3-Clause AND LicenseRef-scancode-protobuf -> 3-Clause BSD (METADATA License text) | |
| # pywin32 PSF-2.0 -> PSF-2.0 (permissive, equivalent to BSD) | |
| # cyclonedx-python-lib no detected license -> Apache-2.0 (METADATA: License: Apache-2.0) | |
| # fastapi no detected license -> MIT (METADATA: License-Expression: MIT) | |
| # aiohappyeyeballs 0BSD AND BSD-3-Clause AND GPL-1.0-or-later AND PSF-2.0 AND Python-2.0 -> PSF-2.0 (METADATA: License-Expression: PSF-2.0; permissive) | |
| # aiohttp no detected license -> Apache-2.0 (METADATA: License-Expression: Apache-2.0 AND MIT; dual permissive) | |
| # docutils BSD-2-Clause AND BSD-3-Clause AND CC-PDDC AND GPL-1.0-or-later AND GPL-3.0-only AND GPL-3.0-or-later AND ... -> public-domain + BSD-2-Clause (METADATA: License: public domain, Python, 2-Clause BSD; GPL applies to a few isolated source files in the docutils source tree) | |
| # scramp no detected license -> MIT-0 (METADATA: License-Expression: MIT No Attribution; permissive) | |
| # bidict MPL-2.0 -> MPL-2.0 file-level copyleft; used unmodified as a runtime dependency, permitted under Apache-2.0 combined works (pulled in transitively via reflex[ui] extra) | |
| # semgrep LGPL-2.0-only AND LGPL-2.1 -> LGPL-2.1 (PyPI classifier: LGPLv2; CLI-only scanner, not imported or linked into orb-py; LGPL permits this use) | |
| allow-dependencies-licenses: 'pkg:pypi/werkzeug, pkg:githubactions/trufflesecurity/trufflehog, pkg:pypi/lark, pkg:pypi/mcp, pkg:pypi/rfc3987-syntax, pkg:pypi/wcwidth, pkg:pypi/lxml, pkg:pypi/protobuf, pkg:pypi/pywin32, pkg:pypi/cyclonedx-python-lib, pkg:pypi/fastapi, pkg:pypi/aiohappyeyeballs, pkg:pypi/aiohttp, pkg:pypi/docutils, pkg:pypi/scramp, pkg:pypi/bidict, pkg:pypi/semgrep' | |
| codeql-analysis: | |
| name: CodeQL Analysis | |
| needs: [config, setup-cache] | |
| if: github.event_name == 'pull_request' || github.event_name == 'schedule' || contains(github.event.head_commit.message, '[security]') | |
| permissions: | |
| contents: read | |
| actions: read | |
| security-events: write | |
| uses: ./.github/workflows/reusable-security.yml | |
| with: | |
| scan-type: codeql | |
| default-python-version: ${{ needs.config.outputs.default-python-version }} | |
| python-version: ${{ needs.config.outputs.default-python-version }} | |
| cache-key: ${{ needs.setup-cache.outputs.cache-key }} |