ci(security): add Gitleaks secret scanning #215
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| docs: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - name: Build strict documentation site and check documentation contracts | |
| run: | | |
| uv sync --locked --extra docs --extra test | |
| uv run mkdocs build --strict --site-dir /tmp/airlock-docs | |
| uv run pytest tests/test_documentation_contract.py -q | |
| test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 35 | |
| strategy: | |
| matrix: | |
| python-version: ["3.12"] | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - name: Install dependencies | |
| run: | | |
| uv sync --locked --all-extras | |
| - name: Download spaCy model | |
| run: make ensure-spacy | |
| - name: Verify presidio + spaCy available | |
| run: | | |
| uv run python -c "from presidio_analyzer import AnalyzerEngine; print('presidio OK')" | |
| uv run python -c "import spacy; spacy.load('en_core_web_lg'); print('spacy model OK')" | |
| - name: Run tests with coverage | |
| run: | | |
| mkdir -p test-results | |
| uv run pytest -m "not live and not docker" --cov=airlock --cov-report=xml --cov-report=term-missing --junitxml=test-results/junit.xml -o junit_logging=no | |
| - name: Check failure JUnit report is safe to retain | |
| id: junit | |
| if: failure() | |
| run: | | |
| if test -f test-results/junit.xml && test "$(wc -c < test-results/junit.xml)" -le 5242880; then | |
| echo "upload=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "upload=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Upload bounded failure JUnit report | |
| if: failure() && steps.junit.outputs.upload == 'true' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: test-failure-junit | |
| path: test-results/junit.xml | |
| retention-days: 1 | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: coverage-report | |
| path: coverage.xml | |
| lint: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - name: Install dependencies and linters | |
| run: | | |
| uv sync --locked --all-extras | |
| # Pin linter versions so CI is reproducible and a new ruff/mypy | |
| # release can't silently turn the build red on an unrelated PR. | |
| . scripts/tool-versions.sh | |
| uv pip install "ruff==$AIRLOCK_RUFF_VERSION" "mypy==$AIRLOCK_MYPY_VERSION" | |
| - name: Ruff check | |
| run: uv run ruff check airlock/ tests/ | |
| - name: Ruff format check | |
| run: uv run ruff format --check airlock/ tests/ | |
| - name: Mypy (fast subsystem) | |
| run: uv run mypy airlock/fast/ --ignore-missing-imports | |
| docker: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - name: Install locked test dependencies | |
| run: uv sync --locked --extra test | |
| - name: Verify disposable Docker topology | |
| run: make test-docker | |
| security: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - name: Install and audit | |
| # Suppressions are documented, scoped, and reviewable in | |
| # dev/notes/security-pip-audit-exceptions.md. Each records why it cannot | |
| # be fixed, why it is unreachable in Airlock's usage, and the condition | |
| # for removal. Do not add one without that assessment. | |
| # | |
| # cryptography 48.0.1: litellm[proxy] and presidio-anonymizer both pin | |
| # <49, blocking the 49/50 fixes. All three findings need PKCS#7 | |
| # decryption or X.509 path validation; Airlock does neither and imports | |
| # cryptography nowhere directly. | |
| run: | | |
| uv sync --locked --all-extras | |
| . scripts/tool-versions.sh | |
| uv pip install "pip-audit==$AIRLOCK_PIP_AUDIT_VERSION" | |
| uv run pip-audit \ | |
| --ignore-vuln PYSEC-2026-3552 \ | |
| --ignore-vuln PYSEC-2026-3553 \ | |
| --ignore-vuln PYSEC-2026-3554 |