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
4 changes: 3 additions & 1 deletion .github/workflows/source-platform-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ pytest*.txt

# ---- Interne Steuerungsdateien ----
DECISIONS.md
PORTIERUNGSPLAN.md
TODO.md
DONE.md

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
35 changes: 35 additions & 0 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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}"
Loading