Skip to content

Fix Scrutinizer coverage step with .scrutinizer.yml - #89

Merged
mosbth merged 7 commits into
masterfrom
fix/scrutinizer-coverage
Aug 23, 2026
Merged

Fix Scrutinizer coverage step with .scrutinizer.yml#89
mosbth merged 7 commits into
masterfrom
fix/scrutinizer-coverage

Conversation

@mosbth

@mosbth mosbth commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Scrutinizer's coverage step has been failing (see the "Build Status Scrutinizer" /
"Code Coverage" badges in the README). Its stored build config predates the
uv migration:

  • it installs a stale, hardcoded dependency list via raw pip
    (coverage feedparser beautifulsoup4 chardet requests discord), none of
    which matches the actual dependencies in pyproject.toml
  • it runs coverage run --source=. -m unittest discover -b without
    -s tests, so it discovers 0 tests (tests/ has no __init__.py) and
    exits with code 5 — confirmed by reproducing locally:
    python3 -m unittest discover -bRan 0 tests, vs.
    python3 -m unittest discover -s tests -bRan 60 tests ... OK

This adds a version-controlled .scrutinizer.yml that runs the project's
real tooling instead (uv sync then uv run pytest --cov=irc2phpbb --cov-report=xml), so the build config stays in sync with pyproject.toml
rather than depending on Scrutinizer's stale web-UI/auto-detected settings.
Also adds coverage.xml to .gitignore, matching the existing
.coverage/htmlcov/ entries.

Related to #88, which documents some other small housekeeping changes
pushed directly to master around the same time.

Test plan

  • uv run pytest --cov=irc2phpbb --cov-report=xml locally produces
    coverage.xml (60 passed) in the py-cc format Scrutinizer expects
  • Scrutinizer picks up .scrutinizer.yml and the coverage step passes
    on this branch/PR

Scrutinizer's stored build config predates the uv migration: it installs a
stale, hardcoded dependency list via raw pip (coverage feedparser
beautifulsoup4 chardet requests discord, none of which match
pyproject.toml) and runs `unittest discover -b` without `-s tests`, so it
finds zero tests and the coverage step exits with code 5.

Version-controlling the build config with the project's actual tooling
(uv sync + pytest --cov) keeps it in sync with pyproject.toml going forward.

Related to #88.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
The curl|sh installer failed with exit code 127 in Scrutinizer's build
environment (curl isn't present in its Python runtime image), before
uv sync ever got a chance to run. pip is guaranteed to exist since it's
part of the Python runtime Scrutinizer just built, so install uv through
it instead — also avoids depending on network access to astral.sh.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
mosbth and others added 5 commits August 23, 2026 22:50
Pulls in the docs-deploy-on-PR fix from #90.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
- test_main.py: argparse's error message for an invalid choice quotes the
  choices list differently between Python patch releases ("'irc', 'discord'"
  on 3.12.3, "irc, discord" on 3.12.14) — normalize that before comparing so
  the test doesn't depend on the exact patch version.
- .scrutinizer.yml: Scrutinizer's own coverage-report post-processing shells
  out to a bare `coverage` command, which only existed inside the uv-managed
  .venv ("bash: coverage: command not found"). Install it globally via pip
  alongside uv so it's on PATH.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
py-cc is coverage.py's own SQLite data file format, not the Cobertura-style
XML report — Scrutinizer's coverage step was trying to open coverage.xml as
that database and failing ("file is not a database"). Drop --cov-report=xml
(pytest-cov already writes .coverage by default) and point the coverage
config at .coverage instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
Scrutinizer runs coverage collection as its own build node, independent of
the "build" node — confirmed via the inspection's normalized Config view,
which showed "coverage" still running its legacy stored command
(python3 -m pip install coverage feedparser beautifulsoup4 chardet requests
discord; coverage run --source=. -m unittest discover -b) even after
.scrutinizer.yml's "build" section was correctly picked up by the
"analysis"/"tests" nodes. Add an explicit top-level "coverage" section
(reusing the same dependencies/test command via YAML anchors) so this node
uses the project's real tooling too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
A bare top-level "coverage:" key isn't valid config (confirmed by
Scrutinizer's own "Unrecognized option" error) — nodes are only
configurable nested under build.nodes.<name>, per
https://scrutinizer-ci.com/docs/guides/python/continuous-integration-deployment.
The previous bare "build:" (without "nodes") happened to reach the
"analysis" and "tests" nodes via some backward-compat shorthand, but never
touched the separate legacy "coverage" node.

Explicitly define all three of this repo's existing nodes (analysis, tests,
coverage) so none of them fall back to the old stored web-UI config.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax5CKcNH5hwbYNJoRGLyAC
@mosbth
mosbth merged commit 0334e24 into master Aug 23, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant