From f160eb5e71ff6dd0e4ea6b828b67307bc2296ba5 Mon Sep 17 00:00:00 2001 From: Shamim Rehman Date: Thu, 4 Jun 2026 15:03:35 -0400 Subject: [PATCH] Add Forge Python dependency constraints --- .github/workflows/ci.yml | 6 +++--- constraints.txt | 17 +++++++++++++++++ tests/test_ci_workflow.py | 25 ++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 constraints.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c2bbec..5d90f34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: pip install -e ".[dev]" + run: pip install -c constraints.txt -e ".[dev]" - name: Lint run: ruff check forge_cli/ tests/ @@ -46,8 +46,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade "pip>=26.1" - python -m pip install -e ".[dev]" + python -m pip install -c constraints.txt -e ".[dev]" python -m pip install pip-audit - name: Run pip-audit - run: python -m pip_audit --progress-spinner off + run: python -m pip_audit --progress-spinner off -r constraints.txt diff --git a/constraints.txt b/constraints.txt new file mode 100644 index 0000000..9d76160 --- /dev/null +++ b/constraints.txt @@ -0,0 +1,17 @@ +# Python 3.11 CI dependency constraints. +# Regenerate from a clean environment with: +# python -m pip install -e ".[dev]" +# python -m pip freeze --exclude-editable +annotated-doc==0.0.4 +iniconfig==2.3.0 +markdown-it-py==4.2.0 +mdurl==0.1.2 +packaging==26.2 +pluggy==1.6.0 +Pygments==2.20.0 +pytest==9.0.3 +PyYAML==6.0.3 +rich==15.0.0 +ruff==0.15.16 +shellingham==1.5.4 +typer==0.26.7 diff --git a/tests/test_ci_workflow.py b/tests/test_ci_workflow.py index d739b14..423c116 100644 --- a/tests/test_ci_workflow.py +++ b/tests/test_ci_workflow.py @@ -6,6 +6,7 @@ ROOT = Path(__file__).resolve().parents[1] CI_WORKFLOW = ROOT / ".github" / "workflows" / "ci.yml" +PYTHON_CONSTRAINTS = ROOT / "constraints.txt" TAGGED_ACTION_REF = re.compile(r"uses:\s+[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+@v\d+") @@ -17,7 +18,29 @@ def test_ci_workflow_has_dependency_security_gate() -> None: assert "dependency-security:" in workflow assert 'python -m pip install --upgrade "pip>=26.1"' in workflow assert "python -m pip install pip-audit" in workflow - assert "python -m pip_audit --progress-spinner off" in workflow + assert "python -m pip_audit --progress-spinner off -r constraints.txt" in workflow + + +def test_ci_installs_project_dependencies_with_python_constraints() -> None: + workflow = CI_WORKFLOW.read_text() + + assert 'pip install -c constraints.txt -e ".[dev]"' in workflow + assert 'python -m pip install -c constraints.txt -e ".[dev]"' in workflow + + +def test_python_constraints_pin_ci_dependency_set() -> None: + assert PYTHON_CONSTRAINTS.exists() + content = PYTHON_CONSTRAINTS.read_text() + + for package in ("typer", "rich", "pyyaml", "pytest", "ruff"): + assert f"{package}==" in content.lower() + + unconstrained_lines = [ + line + for line in content.splitlines() + if line.strip() and not line.startswith("#") and "==" not in line + ] + assert unconstrained_lines == [] def test_github_actions_are_pinned_to_commit_shas() -> None: