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
49 changes: 30 additions & 19 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -73,30 +73,41 @@ else
fi
echo ""

# 4. Check test coverage threshold (if FoundationUI sources/tests changed)
# 4. Check test coverage threshold (FoundationUI)
echo "4️⃣ Checking test coverage threshold..."
MERGE_BASE=$(git merge-base origin/main HEAD 2>/dev/null || echo "HEAD")
if git diff $MERGE_BASE...HEAD --name-only | grep -qE '^FoundationUI/(Sources|Tests)/'; then
echo " FoundationUI code detected in commits, checking coverage..."
if command -v python3 &> /dev/null; then
COVERAGE_THRESHOLD=${ISOINSPECTOR_MIN_TEST_COVERAGE:-0.67}

# Run coverage analysis with threshold check
if python3 coverage_analysis.py --threshold "$COVERAGE_THRESHOLD" -v >/dev/null 2>&1; then
echo -e "${GREEN}✅ Test coverage check passed${NC}"
echo " Threshold: $COVERAGE_THRESHOLD (67%)"
COVERAGE_THRESHOLD=${ISOINSPECTOR_MIN_TEST_COVERAGE:-0.67}
COVERAGE_TEST_LOG="$LOG_DIR/foundationui-coverage-test-$(date +%Y%m%d-%H%M%S).log"
COVERAGE_REPORT="$LOG_DIR/foundationui-coverage-report-$(date +%Y%m%d-%H%M%S).txt"

PLATFORM=$(uname -s)
if [[ "$PLATFORM" != "Darwin" ]]; then
echo -e "${YELLOW}⚠️ FoundationUI coverage requires macOS SwiftUI SDKs; skipping on $PLATFORM${NC}"
else
echo " Running FoundationUI tests with coverage..."
if swift test --package-path FoundationUI --enable-code-coverage 2>&1 | tee "$COVERAGE_TEST_LOG"; then
echo -e "${GREEN}✅ FoundationUI tests with coverage passed${NC}"
echo " Log: $COVERAGE_TEST_LOG"

if command -v python3 &> /dev/null; then
if python3 coverage_analysis.py --threshold "$COVERAGE_THRESHOLD" --report "$COVERAGE_REPORT" -v; then
echo -e "${GREEN}✅ Test coverage check passed${NC}"
echo " Threshold: $COVERAGE_THRESHOLD (67%)"
echo " Report: $COVERAGE_REPORT"
else
echo -e "${RED}❌ Test coverage below threshold${NC}"
echo " Threshold: $COVERAGE_THRESHOLD (67%)"
echo " Report: $COVERAGE_REPORT"
echo " For guidance, see Documentation/ISOInspector.docc/Guides/TestingAndCoverage.md"
FAILED=$((FAILED + 1))
fi
else
echo -e "${RED}❌ Test coverage below threshold${NC}"
echo " Run: python3 coverage_analysis.py --verbose"
echo " For more details on how to improve test coverage, see:"
echo " Documentation/ISOInspector.docc/Guides/TestingAndCoverage.md"
FAILED=$((FAILED + 1))
echo -e "${YELLOW}⚠️ Python3 not available, skipping coverage check${NC}"
fi
else
echo -e "${YELLOW}⚠️ Python3 not available, skipping coverage check${NC}"
echo -e "${RED}❌ FoundationUI tests with coverage failed${NC}"
echo " Log: $COVERAGE_TEST_LOG"
FAILED=$((FAILED + 1))
fi
else
echo " No FoundationUI code changes detected, skipping coverage check"
fi
echo ""

Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
paths:
- 'Sources/**'
- 'Tests/**'
- 'FoundationUI/**'
- 'scripts/**'
- 'Package.swift'
- 'Package.resolved'
Expand All @@ -21,6 +22,7 @@ on:
paths:
- 'Sources/**'
- 'Tests/**'
- 'FoundationUI/**'
- 'scripts/**'
- 'Package.swift'
- 'Package.resolved'
Expand Down Expand Up @@ -181,6 +183,40 @@ jobs:
if-no-files-found: error
retention-days: 14

coverage-gate:
name: Coverage Gate (FoundationUI)
runs-on: macos-14
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Swift
uses: SwiftyLab/setup-swift@v1
with:
swift-version: '6.0'

- name: Create log directory
run: mkdir -p Documentation/Quality

- name: Run FoundationUI tests with coverage
run: swift test --package-path FoundationUI --enable-code-coverage 2>&1 | tee Documentation/Quality/foundationui-coverage-test.log

- name: Enforce coverage threshold (67%)
run: |
Comment on lines +201 to +205

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Coverage gate skipped for FoundationUI-only changes

The new coverage-gate job runs FoundationUI tests and enforces the 67% threshold, but the workflow’s path filters at the top of this file still omit FoundationUI/**. GitHub Actions won’t trigger the workflow at all when a PR only touches the FoundationUI package, so this gate never executes for the module it is intended to protect and those changes can merge without coverage enforcement. Please add the FoundationUI paths to the workflow triggers (or a dedicated workflow) so the gate actually runs for FoundationUI edits.

Useful? React with 👍 / 👎.

python3 coverage_analysis.py --threshold 0.67 --report Documentation/Quality/foundationui-coverage-report.txt -v
echo "Coverage report written to Documentation/Quality/foundationui-coverage-report.txt"

- name: Upload coverage artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: foundationui-coverage
path: |
Documentation/Quality/foundationui-coverage-test.log
Documentation/Quality/foundationui-coverage-report.txt
if-no-files-found: error
retention-days: 14

docc-archives:
name: Generate DocC Archives
runs-on: ubuntu-22.04
Expand Down
4 changes: 2 additions & 2 deletions DOCS/AI/ISOInspector_Execution_Guide/04_TODO_Workplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ The following plan decomposes delivery into dependency-aware phases. Each task i
| A3 | Set up DocC catalog and documentation publishing workflow. | Medium | 1 | A1 | DocC, SwiftPM | `docc` build succeeds; docs published artifact accessible. (Completed ✅ — generates archives via `scripts/generate_documentation.sh`, DocC catalogs live under `Sources/*/*.docc`, tutorials expanded in `DOCS/TASK_ARCHIVE/35_A3_DocC_Tutorial_Expansion/`, and CI publishing now delivered by the TODO #12-backed `docc-archives` job.) |
| A6 | Enforce SwiftFormat-based formatting locally and in CI. | Medium | 0.5 | A2 | swift-format, GitHub Actions | `.pre-commit-config.yaml` runs `swift format --in-place` on staged Swift files; CI step executes `swift format --mode lint` and fails on diff. Documentation updated in `README.md` tooling section. (Completed ✅ — archived in `DOCS/TASK_ARCHIVE/226_A6_Enforce_SwiftFormat_Formatting/`.) |
| A7 | Reinstate SwiftLint complexity thresholds across targets. | Medium | 0.75 | A2 | SwiftLint | `.swiftlint.yml` restores `cyclomatic_complexity`, `function_body_length`, `nesting`, and `type_body_length` with agreed limits; pre-commit runs `swiftlint lint --strict`; CI publishes analyzer report artifact. *(Completed ✅ — see `DOCS/INPROGRESS/Summary_of_Work.md`.)* |
| A8 | Gate test coverage using `coverage_analysis.py`. | Medium | 1 | A2 | Python, SwiftPM | `coverage_analysis.py --threshold 0.67` executes in pre-push and GitHub Actions after `swift test --enable-code-coverage`; pushes blocked and workflow fails when ratio drops. Coverage report archived under `Documentation/Quality/` per run. |
| A8 | Gate test coverage using `coverage_analysis.py`. | Medium | 1 | A2 | Python, SwiftPM | `coverage_analysis.py --threshold 0.67` executes in pre-push and GitHub Actions after `swift test --enable-code-coverage`; pushes blocked and workflow fails when ratio drops. Coverage report archived under `Documentation/Quality/` per run. *(Completed ✅ — enforced via pre-push gate and CI `coverage-gate` job with artifacts stored under `Documentation/Quality/`.)* |
| A9 | Automate strict concurrency checks for core and tests. | High | 1 | A2 | SwiftPM, GitHub Actions | Pre-push hook and CI workflow run `swift build --strict-concurrency=complete` and `swift test --strict-concurrency=complete`; logs show zero warnings. Results linked to `PRD_SwiftStrictConcurrency_Store.md` rollout checklist. (Completed ✅ — archived in `DOCS/TASK_ARCHIVE/225_A9_Swift6_Concurrency_Cleanup/`; includes post-A9 Swift 6 migration cleanup that removed redundant StrictConcurrency flags and aligned CI to Swift 6.0/Xcode 16.2.) |
| A10 | Add Swift duplication detection to CI. | Medium | 1 | A2 | GitHub Actions, Node, `jscpd` | `.github/workflows/swift-duplication.yml` runs `scripts/run_swift_duplication_check.sh` (wrapper for `npx jscpd@3.5.10`) on Swift sources for every PR/push. Workflow fails when duplicated lines exceed 1% or any block >45 lines repeats; artifact uploads console report. Plan + scope: `DOCS/AI/github-workflows/02_swift_duplication_guard/prd.md`. |
| A11 | Enable local CI execution on macOS. | Medium | 1.5 | A2 | Bash, Docker (optional) | Scripts in `scripts/local-ci/` replicate GitHub Actions workflows locally, supporting lint, build, test, and coverage jobs. Native and Docker execution modes available. Documentation in `scripts/local-ci/README.md` covers setup, usage, and troubleshooting. *(Completed ✅ — Phase 1 delivered in `DOCS/AI/github-workflows/04_local_ci_macos/`; see `Summary.md` for deliverables and coverage matrix.)* |

> **Current focus:** _BUG #001 Design System Color Token Migration_ archived to `DOCS/TASK_ARCHIVE/227_Bug001_Design_System_Color_Token_Migration/` (2025-11-16). ISOInspectorApp continues to use hardcoded `.accentColor` and manual opacity values in 6 view files instead of FoundationUI design tokens. Blocking FoundationUI Phase 5.2 completion. See archive for full analysis and blockers. Next candidate tasks in automation track: A7 (SwiftLint complexity), A8 (test coverage gate), A10 (duplication detection). Refer to `DOCS/INPROGRESS/next_tasks.md` and `DOCS/INPROGRESS/blocked.md` for day-to-day queue and active blockers.
> **Current focus:** _BUG #001 Design System Color Token Migration_ archived to `DOCS/TASK_ARCHIVE/227_Bug001_Design_System_Color_Token_Migration/` (2025-11-16). ISOInspectorApp continues to use hardcoded `.accentColor` and manual opacity values in 6 view files instead of FoundationUI design tokens. Blocking FoundationUI Phase 5.2 completion. See archive for full analysis and blockers. Next candidate task in automation track: A10 (duplication detection), following completion of A7 (SwiftLint complexity) and A8 (coverage gate). Refer to `DOCS/INPROGRESS/next_tasks.md` and `DOCS/INPROGRESS/blocked.md` for day-to-day queue and active blockers.
>
> **Bug resolved (2025-11-25):** Bug #235 — Smoke tests blocked by Sendable violations in `WindowSessionController` under strict concurrency. Fixed via sendable annotations + document loading refactor; see `DOCS/INPROGRESS/235_Sendable_SmokeTest_Build_Failure.md` for details and test evidence.
>
Expand Down
6 changes: 6 additions & 0 deletions DOCS/INPROGRESS/A8_Test_Coverage_Gate.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ Add automated coverage enforcement so pushes and CI runs fail when overall Swift
- [`ISOInspector_PRD_TODO.md`](../AI/ISOViewer/ISOInspector_PRD_TODO.md)
- [`DOCS/RULES`](../RULES)
- Relevant archives in [`DOCS/TASK_ARCHIVE`](../TASK_ARCHIVE)

## ✅ Resolution Notes — 2025-12-12

- **Pre-push enforcement:** `.githooks/pre-push` now runs `swift test --package-path FoundationUI --enable-code-coverage` followed by `coverage_analysis.py --threshold 0.67` (reporting to `Documentation/Quality/`). Pushes fail if either the coverage test run or threshold check fails. Threshold respects `ISOINSPECTOR_MIN_TEST_COVERAGE` when set.
- **CI enforcement:** `.github/workflows/ci.yml` adds a macOS `coverage-gate` job that executes the same FoundationUI coverage test run, invokes the coverage analysis with a 0.67 threshold, and uploads logs/reports from `Documentation/Quality/` as CI artifacts.
- **Artifacts:** Coverage logs and reports are stored under `Documentation/Quality/` for both local hooks and CI, providing a consistent audit trail for regressions.
15 changes: 15 additions & 0 deletions DOCS/INPROGRESS/Summary_of_Work.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## Summary of Work — 2025-12-12

### Completed Tasks
- ✅ **Task A8 — Test Coverage Gate**

### Implementation Highlights
- Added macOS-only FoundationUI coverage enforcement to `.githooks/pre-push`, running `swift test --enable-code-coverage` followed by `coverage_analysis.py --threshold 0.67` with reports under `Documentation/Quality/`.
- Introduced a macOS `coverage-gate` job in `.github/workflows/ci.yml` that mirrors the pre-push coverage gate and uploads coverage logs/reports as CI artifacts.
- Updated task trackers (`todo.md`, `DOCS/AI/ISOInspector_Execution_Guide/04_TODO_Workplan.md`, `DOCS/INPROGRESS/next_tasks.md`, and `DOCS/INPROGRESS/A8_Test_Coverage_Gate.md`) to record the completed coverage gate rollout and artifact locations.

### Verification
- ⚠️ `swift test --package-path FoundationUI --enable-code-coverage` (fails on Linux due to missing SwiftUI SDK; coverage gate runs on macOS runners in CI and on macOS developer machines.)

---

## Summary of Work — 2025-11-28

### Completed Tasks
Expand Down
8 changes: 4 additions & 4 deletions DOCS/INPROGRESS/next_tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ _Last updated: 2025-11-19 (UTC). Maintainers should update this file whenever ta

## 1. Automation & Quality Gates

1. **Task A8 – Test Coverage Gate** _(In Progress — `DOCS/INPROGRESS/A8_Test_Coverage_Gate.md`)_
- Wire `coverage_analysis.py --threshold 0.67` into `.githooks/pre-push` and `.github/workflows/ci.yml` immediately after `swift test --enable-code-coverage`.
- Publish the HTML or JSON coverage artifacts under `Documentation/Quality/` so regressions have concrete data.
- Update `todo.md` and `DOCS/AI/ISOInspector_Execution_Guide/04_TODO_Workplan.md` once the hook and CI gate are enforced.
1. **Task A8 – Test Coverage Gate** ✅ _(Completed — `DOCS/INPROGRESS/A8_Test_Coverage_Gate.md`)_
- `coverage_analysis.py --threshold 0.67` now runs in `.githooks/pre-push` after `swift test --enable-code-coverage` (macOS-only due to SwiftUI dependency) and blocks pushes on coverage failures.
- CI `coverage-gate` job executes the same workflow on macOS runners and publishes logs/reports under `Documentation/Quality/`.
- `todo.md` and the Execution Workplan have been updated to reflect the enforced gate and artifact locations.

2. **Task A10 – Swift Duplication Detection** _(Ready)_
- Add `.github/workflows/swift-duplication.yml` that runs `scripts/run_swift_duplication_check.sh` (wrapper around `npx jscpd@3.5.10`).
Expand Down
2 changes: 1 addition & 1 deletion todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- [x] #A7 Refactor DocumentSessionController to comply with type_body_length threshold — Extracted 7 services: BookmarkService, RecentsService, ParseCoordinationService, SessionPersistenceService, ValidationConfigurationService, ExportService, DocumentOpeningCoordinator. Reduced from 1652 lines to 347 lines (82% reduction). Removed swiftlint:disable directive. (Sources/ISOInspectorApp/State/DocumentSessionController.swift, Sources/ISOInspectorApp/State/Services/) _(Completed 2025-11-28.)_
- [x] #A7 Enable strict mode for main project after refactoring large files — CI and local hooks now run `swiftlint lint --strict` with JSON artifacts published for every run. (`.github/workflows/swiftlint.yml`, `.swiftlint.yml`, `.githooks/pre-commit`)

- [ ] Promote `coverage_analysis.py` to a shared quality gate by wiring it into `.githooks/pre-push` and `.github/workflows/ci.yml` after `swift test --enable-code-coverage`. (Scripts: `.githooks/pre-push`, `coverage_analysis.py`, `.github/workflows/ci.yml`)
- [x] Promote `coverage_analysis.py` to a shared quality gate by wiring it into `.githooks/pre-push` and `.github/workflows/ci.yml` after `swift test --enable-code-coverage`. (Scripts: `.githooks/pre-push`, `coverage_analysis.py`, `.github/workflows/ci.yml`) _(Completed 2025-12-12 — FoundationUI coverage run + threshold enforced locally/CI with artifacts under Documentation/Quality/.)_
- [ ] Add DocC + `missing_docs` enforcement to the lint pipeline so public APIs fail CI without documentation coverage, and capture the suppression playbook in `Documentation/ISOInspector.docc/Guides/DocumentationStyle.md`. (Config: `.swiftlint.yml`, `.github/workflows/documentation.yml`)
- [x] Extend `.githooks/pre-push` and `.github/workflows/ci.yml` with `swift build --strict-concurrency=complete`/`swift test --strict-concurrency=complete` runs, publishing logs referenced from `DOCS/AI/PRD_SwiftStrictConcurrency_Store.md`. (Scripts: `.githooks/pre-push`, `.github/workflows/ci.yml`) _(Completed 2025-11-15 — Task A9, archived at `DOCS/TASK_ARCHIVE/225_A9_Swift6_Concurrency_Cleanup/`)_
- [ ] Add `.github/workflows/swift-duplication.yml` that runs `scripts/run_swift_duplication_check.sh` (wrapper around `npx jscpd@3.5.10`) on all Swift targets, fails when duplicates exceed 1% or blocks >45 lines repeat, and uploads a console artifact. (Docs: `DOCS/AI/github-workflows/02_swift_duplication_guard/prd.md` + `TODO.md`)
Expand Down