Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/snyk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -e .
- name: Setup Snyk
if: ${{ env.SNYK_TOKEN != '' }}
uses: snyk/actions/setup@master

- name: Run Snyk (dependencies)
- name: Run Snyk (requirements.txt)
if: ${{ env.SNYK_TOKEN != '' }}
run: snyk test --severity-threshold=high
run: snyk test --file=requirements.txt --package-manager=pip --severity-threshold=high

- name: Run Snyk (pyproject.toml)
if: ${{ env.SNYK_TOKEN != '' }}
run: snyk test --file=pyproject.toml --package-manager=pip --severity-threshold=high
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ pyyaml>=6.0.3
ttkbootstrap>=1.20.3
pillow>=12.2.0
openai>=2.37.0
httpx<0.29
python-dotenv>=1.2.2
Jinja2>=3.1.6
jinja2>=3.1.6
tiktoken>=0.13.0
cachetools>=7.1.3
sqlalchemy>=2.0.49
Expand Down
68 changes: 68 additions & 0 deletions tests/test_snyk_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from pathlib import Path

try:
import tomllib
except ModuleNotFoundError: # pragma: no cover - Python <3.11 fallback
import tomli as tomllib

import yaml


def _repo_root() -> Path:
return Path(__file__).resolve().parents[1]


def _load_pyproject() -> dict:
pyproject_path = _repo_root() / "pyproject.toml"
return tomllib.loads(pyproject_path.read_text(encoding="utf-8"))


def _load_requirements() -> list[str]:
requirements_path = _repo_root() / "requirements.txt"
return [
line.strip()
for line in requirements_path.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.lstrip().startswith("#")
]


def _load_snyk_workflow() -> dict:
workflow_path = _repo_root() / ".github" / "workflows" / "snyk.yml"
return yaml.safe_load(workflow_path.read_text(encoding="utf-8"))


def test_runtime_manifests_match_exactly():
pyproject = _load_pyproject()
runtime_dependencies = sorted(pyproject["project"]["dependencies"])
requirements = sorted(_load_requirements())

assert runtime_dependencies == requirements


def test_snyk_workflow_scans_python_manifests_explicitly():
workflow = _load_snyk_workflow()
steps = workflow["jobs"]["snyk"]["steps"]

install_step = next(
(step for step in steps if step.get("name") == "Install dependencies"), None
)
assert install_step is not None, "Snyk install step is missing"
assert "pip install -e ." not in install_step.get("run", "")

requirements_scan = next(
(step for step in steps if step.get("name") == "Run Snyk (requirements.txt)"), None
)
assert requirements_scan is not None, "requirements.txt Snyk scan step is missing"
assert (
requirements_scan.get("run")
== "snyk test --file=requirements.txt --package-manager=pip --severity-threshold=high"
)

pyproject_scan = next(
(step for step in steps if step.get("name") == "Run Snyk (pyproject.toml)"), None
)
assert pyproject_scan is not None, "pyproject.toml Snyk scan step is missing"
assert (
pyproject_scan.get("run")
== "snyk test --file=pyproject.toml --package-manager=pip --severity-threshold=high"
)
Loading