fix(ci): restore defusedxml dependency parity

This commit is contained in:
rookiestar28
2026-04-08 02:34:34 +08:00
parent 0f133ec6e0
commit e7c0566efe
7 changed files with 77 additions and 2 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ jobs:
- name: Install preflight deps - name: Install preflight deps
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
python -m pip install cryptography python -m pip install -r requirements.txt
- name: R120 preflight - name: R120 preflight
run: | run: |
python scripts/preflight_check.py --strict python scripts/preflight_check.py --strict
+1
View File
@@ -3,3 +3,4 @@
# Keep this file aligned with `pyproject.toml` project.dependencies. # Keep this file aligned with `pyproject.toml` project.dependencies.
# #
cryptography>=41.0 cryptography>=41.0
defusedxml>=0.7.1
+5
View File
@@ -213,6 +213,11 @@ if ! "$VENV_PY" -c "import cryptography" >/dev/null 2>&1; then
echo "[pre-push] INFO: installing cryptography into project venv ($VENV_DIR) ..." >&2 echo "[pre-push] INFO: installing cryptography into project venv ($VENV_DIR) ..." >&2
pip_install_or_fail "required for S57 secrets-at-rest encryption paths/tests" cryptography pip_install_or_fail "required for S57 secrets-at-rest encryption paths/tests" cryptography
fi fi
if ! "$VENV_PY" -c "import defusedxml" >/dev/null 2>&1; then
# IMPORTANT: keep local/CI parity with requirements.txt and WeChat ingress tests.
echo "[pre-push] INFO: installing defusedxml into project venv ($VENV_DIR) ..." >&2
pip_install_or_fail "required for S85 fail-closed XML parsing paths/tests" defusedxml
fi
require_cmd npm require_cmd npm
+2 -1
View File
@@ -6,7 +6,7 @@ Validates the build environment before deployment or test execution.
Checks: Checks:
1. Python version (>=3.10) 1. Python version (>=3.10)
2. Node.js version (>=18.0.0, per package.json + TEST_SOP) 2. Node.js version (>=18.0.0, per package.json + TEST_SOP)
3. Essential Python dependencies (cryptography) 3. Essential Python dependencies (cryptography, defusedxml)
Usage: Usage:
python scripts/preflight_check.py [--strict] python scripts/preflight_check.py [--strict]
@@ -23,6 +23,7 @@ MIN_NODE_VERSION = (18, 0, 0)
REQUIRED_PYTHON_PACKAGES = [ REQUIRED_PYTHON_PACKAGES = [
("cryptography", "41.0"), ("cryptography", "41.0"),
("defusedxml", "0.7.1"),
] ]
# Colors for output # Colors for output
+5
View File
@@ -123,6 +123,11 @@ if ! "$VENV_PY" -c "import cryptography" >/dev/null 2>&1; then
echo "[tests] Installing cryptography into project venv ($VENV_DIR) ..." echo "[tests] Installing cryptography into project venv ($VENV_DIR) ..."
pip_install_or_fail "required for S57 secrets-at-rest encryption tests" cryptography pip_install_or_fail "required for S57 secrets-at-rest encryption tests" cryptography
fi fi
if ! "$VENV_PY" -c "import defusedxml" >/dev/null 2>&1; then
# IMPORTANT: keep local full-test bootstrap aligned with requirements.txt.
echo "[tests] Installing defusedxml into project venv ($VENV_DIR) ..."
pip_install_or_fail "required for S85 fail-closed XML parsing tests" defusedxml
fi
NODE_MAJOR="$(node -p "process.versions.node.split('.')[0]")" NODE_MAJOR="$(node -p "process.versions.node.split('.')[0]")"
if [ "$NODE_MAJOR" -lt 18 ]; then if [ "$NODE_MAJOR" -lt 18 ]; then
+11
View File
@@ -169,6 +169,17 @@ if (-not $hasCryptography) {
Invoke-Checked "pip install cryptography" { & $venvPython -m pip install cryptography } Invoke-Checked "pip install cryptography" { & $venvPython -m pip install cryptography }
} }
$hasDefusedXml = $true
& $venvPython -c "import defusedxml" | Out-Null
if ($LASTEXITCODE -ne 0) {
$hasDefusedXml = $false
}
if (-not $hasDefusedXml) {
# IMPORTANT: keep Windows full-test bootstrap aligned with requirements.txt.
Write-Host "[tests] Installing defusedxml into project venv (S85 fail-closed XML parsing) ..."
Invoke-Checked "pip install defusedxml" { & $venvPython -m pip install defusedxml }
}
# Ensure Node >= 18 # Ensure Node >= 18
$nodeMajor = [int]((& node -p "process.versions.node.split('.')[0]").Trim()) $nodeMajor = [int]((& node -p "process.versions.node.split('.')[0]").Trim())
if ($nodeMajor -lt 18) { if ($nodeMajor -lt 18) {
@@ -0,0 +1,52 @@
import ast
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REQUIREMENTS = ROOT / "requirements.txt"
PRE_PUSH = ROOT / "scripts" / "pre_push_checks.sh"
FULL_TESTS_LINUX = ROOT / "scripts" / "run_full_tests_linux.sh"
FULL_TESTS_WINDOWS = ROOT / "scripts" / "run_full_tests_windows.ps1"
PREFLIGHT = ROOT / "scripts" / "preflight_check.py"
PYPROJECT = ROOT / "pyproject.toml"
CI_WORKFLOW = ROOT / ".github" / "workflows" / "ci.yml"
def _parse_required_python_packages():
module = ast.parse(PREFLIGHT.read_text(encoding="utf-8"))
for node in module.body:
if not isinstance(node, ast.Assign):
continue
for target in node.targets:
if isinstance(target, ast.Name) and target.id == "REQUIRED_PYTHON_PACKAGES":
return ast.literal_eval(node.value)
raise AssertionError("REQUIRED_PYTHON_PACKAGES missing from scripts/preflight_check.py")
class DependencyParityContractTests(unittest.TestCase):
def test_requirements_stays_aligned_with_declared_runtime_dependencies(self):
requirements = REQUIREMENTS.read_text(encoding="utf-8")
pyproject = PYPROJECT.read_text(encoding="utf-8")
self.assertIn("cryptography>=41.0", requirements)
self.assertIn("defusedxml>=0.7.1", requirements)
self.assertIn('dependencies = ["cryptography>=41.0", "defusedxml>=0.7.1"]', pyproject)
def test_preflight_declares_all_essential_runtime_packages(self):
required = _parse_required_python_packages()
self.assertIn(("cryptography", "41.0"), required)
self.assertIn(("defusedxml", "0.7.1"), required)
def test_local_acceptance_bootstraps_install_defusedxml(self):
self.assertIn("import defusedxml", PRE_PUSH.read_text(encoding="utf-8"))
self.assertIn("pip install defusedxml", FULL_TESTS_WINDOWS.read_text(encoding="utf-8"))
self.assertIn("import defusedxml", FULL_TESTS_LINUX.read_text(encoding="utf-8"))
def test_frontend_e2e_preflight_uses_requirements_contract(self):
workflow = CI_WORKFLOW.read_text(encoding="utf-8")
self.assertIn("python -m pip install -r requirements.txt", workflow)
if __name__ == "__main__":
unittest.main()