From d9baf3af9e7ec4a911e4d4698fb03686b2095138 Mon Sep 17 00:00:00 2001 From: Weicheng Zhao Date: Thu, 1 Oct 2026 17:57:59 -0400 Subject: [PATCH] ci: add dependency-free Python syntax and config validation --- .github/CI.md | 19 ++++++++ .github/workflows/python-syntax-config.yml | 51 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .github/CI.md create mode 100644 .github/workflows/python-syntax-config.yml diff --git a/.github/CI.md b/.github/CI.md new file mode 100644 index 0000000..95c0f48 --- /dev/null +++ b/.github/CI.md @@ -0,0 +1,19 @@ +# CI coverage + +[Python syntax / config validation](workflows/python-syntax-config.yml) runs on +pushes, pull requests, and manual dispatch using Python 3.12 on a hosted Linux +runner, with a five-minute job timeout. + +- Compiles the bytes of every Git-tracked `.py` file in memory without importing + or executing application code or writing bytecode. Fails if no Python files + are tracked. Source encoding declarations are respected. +- Parses only `config/config.spec.json` and `config/root_config.json` + as JSON, rejecting malformed JSON and nonstandard NaN/Infinity constants. + This checks syntax only, not configuration schema or application semantics. +- Installs no application dependencies and uses only the Python standard library. + Editor and development-environment JSON files are outside this check. + +This is syntax validation, not runtime testing or a guarantee of Python 3.12 +runtime compatibility. It does not exercise imports, dependencies, authentication, +network APIs, recording/uploading, GUIs, installers, training, or evaluation. +It does not discover tests or download models, datasets, or browsers. diff --git a/.github/workflows/python-syntax-config.yml b/.github/workflows/python-syntax-config.yml new file mode 100644 index 0000000..09d7b09 --- /dev/null +++ b/.github/workflows/python-syntax-config.yml @@ -0,0 +1,51 @@ +name: Python syntax / config validation + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + syntax-config: + name: Python syntax / config validation + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Check out source + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Set up Python 3.12 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + - name: Compile tracked Python source without executing it + shell: python -I {0} + run: | + import os + import subprocess + from pathlib import Path + + tracked = subprocess.check_output(["git", "ls-files", "-z", "--", "*.py"]) + paths = [os.fsdecode(path) for path in tracked.split(b"\0") if path] + if not paths: + raise SystemExit("No tracked Python source files found.") + for path in paths: + compile(Path(path).read_bytes(), path, "exec", dont_inherit=True) + print(f"Syntax valid: {len(paths)} tracked Python files.") + - name: Parse application JSON configuration + shell: python -I {0} + run: | + import json + from pathlib import Path + + def reject_constant(value): + raise ValueError(f"Invalid JSON constant: {value}") + + paths = ["config/config.spec.json","config/root_config.json"] + for path in paths: + json.loads(Path(path).read_bytes(), parse_constant=reject_constant) + print(f"JSON syntax valid: {path}")