From ac5bc6eac23e282fed171e5a84abde5b7eb5bd83 Mon Sep 17 00:00:00 2001 From: lukisch <55554266+lukisch@users.noreply.github.com> Date: Tue, 3 Nov 2026 21:33:17 +0100 Subject: [PATCH] chore(hygiene): harden CI test matrix, resolve gitignore contradiction & add contract tests [G 2026-11-03] --- .github/workflows/source-platform-smoke.yml | 4 ++- .github/workflows/tests.yml | 7 ++++- .gitignore | 1 - CHANGELOG.md | 6 ++++ tests/test_metadata.py | 35 +++++++++++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/.github/workflows/source-platform-smoke.yml b/.github/workflows/source-platform-smoke.yml index 4e385cc..752c38b 100644 --- a/.github/workflows/source-platform-smoke.yml +++ b/.github/workflows/source-platform-smoke.yml @@ -60,7 +60,9 @@ jobs: libxcb-xfixes0 - name: Install Python dependencies - run: pip install -r requirements.txt + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt - name: Run source-platform smoke run: python source_platform_smoke.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 84af32a..f7b572b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -35,7 +35,12 @@ jobs: requirements-dev.txt - name: Install dependencies - run: python -m pip install -r requirements-dev.txt + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements-dev.txt + + - name: Run Ruff linter + run: ruff check . - name: Run tests run: python -m pytest -q diff --git a/.gitignore b/.gitignore index 31e546a..d34273d 100644 --- a/.gitignore +++ b/.gitignore @@ -130,7 +130,6 @@ pytest*.txt # ---- Interne Steuerungsdateien ---- DECISIONS.md -PORTIERUNGSPLAN.md TODO.md DONE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ad30938..22b80cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/). ## [Unreleased] +### CI matrix hardening, gitignore hygiene & contract test extension (2026-11-03) +- Hardened GitHub Actions test workflow `.github/workflows/tests.yml` with automated pip upgrade and explicit `ruff check .` linter validation prior to running pytest. +- Hardened `.github/workflows/source-platform-smoke.yml` dependency installation with automated pip upgrade. +- Resolved `.gitignore` pattern contradiction by removing tracked project document `PORTIERUNGSPLAN.md` from the ignored steering files list. +- Extended `tests/test_metadata.py` with contract tests verifying 100% parity between tracked repository files and `MANIFEST.in` (`test_manifest_in_tracked_files_parity`), ensuring zero tracked files are accidentally ignored by `.gitignore` (`test_no_tracked_files_ignored_by_gitignore`), and validating CI linter execution and dependency tooling. + ### Repository and gitignore hygiene (2026-10-31) - Untracked internal marketing and processing document (`MARKETING-LOG.txt`) in compliance with user policy T-20260926-455218633 and GITHUB-POLICY.md ยง4. - Added pattern protection for `MARKETING-LOG.txt`, `*MARKETING-LOG.txt`, and `*STATUS-LOG.txt` in `.gitignore`. diff --git a/tests/test_metadata.py b/tests/test_metadata.py index d23dafa..e541820 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -190,11 +190,15 @@ def test_ci_workflows_timeout_and_concurrency() -> None: assert "concurrency:" in tests_yml assert "cancel-in-progress: true" in tests_yml + assert "ruff check ." in tests_yml + assert "pip install --upgrade pip" in tests_yml + smoke_yml = (workflows_dir / "source-platform-smoke.yml").read_text(encoding="utf-8") assert "timeout-minutes: 15" in smoke_yml assert "contents: read" in smoke_yml assert "concurrency:" in smoke_yml assert "cancel-in-progress: true" in smoke_yml + assert "pip install --upgrade pip" in smoke_yml def test_stale_workflow_present_and_configured() -> None: @@ -357,3 +361,34 @@ def test_internal_marketing_log_not_tracked() -> None: import subprocess proc = subprocess.run(["git", "ls-files", "MARKETING-LOG.txt"], cwd=ROOT, capture_output=True, text=True) assert proc.stdout.strip() == "", "MARKETING-LOG.txt must not be tracked in git" + + +def test_manifest_in_tracked_files_parity() -> None: + """Verifies that all tracked repository files are explicitly declared in MANIFEST.in and exist on disk.""" + import subprocess + manifest = (ROOT / "MANIFEST.in").read_text(encoding="utf-8") + manifest_includes = { + line.split("include ", 1)[1].strip() + for line in manifest.splitlines() + if line.strip().startswith("include ") + } + missing_files = [f for f in manifest_includes if not (ROOT / f).exists()] + assert not missing_files, f"Files declared in MANIFEST.in do not exist on disk: {missing_files}" + + proc = subprocess.run(["git", "ls-files"], cwd=ROOT, capture_output=True, text=True) + tracked_files = [f.replace("\\", "/") for f in proc.stdout.splitlines() if f.strip()] + unmanifested = [f for f in tracked_files if f not in manifest_includes] + assert not unmanifested, f"Tracked files missing from MANIFEST.in: {unmanifested}" + + +def test_no_tracked_files_ignored_by_gitignore() -> None: + """Verifies that no git-tracked file is matched by .gitignore patterns.""" + import subprocess + proc = subprocess.run(["git", "ls-files"], cwd=ROOT, capture_output=True, text=True) + tracked_files = [f.strip() for f in proc.stdout.splitlines() if f.strip()] + ignored_tracked = [] + for rel_path in tracked_files: + res = subprocess.run(["git", "check-ignore", "--no-index", rel_path], cwd=ROOT, capture_output=True, text=True) + if res.returncode == 0: + ignored_tracked.append(rel_path) + assert not ignored_tracked, f"Tracked files match .gitignore patterns: {ignored_tracked}"