Repository navigation
Automate CI coverage, chaos and survey workflow tests - #59
Closed
denniswu28 wants to merge 16 commits into
Closed
denniswu28 wants to merge 16 commits into
denniswu28 wants to merge 16 commits into
Conversation
Configure coverage.py to measure the hallmark package with branch coverage and repository-relative paths, so data from separate CI jobs on Linux and macOS can be combined. Add pytest-cov and pytest-timeout to the dev dependency group and document `pytest --cov` for local runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the separate build and ssh-transport jobs with one test matrix that installs the OpenSSH server and runs the complete suite with HALLMARK_RUN_SSH_TESTS=1 on Python 3.9-3.14 (Linux) and 3.9/3.14 (macOS). Run CI for pull requests into any branch so stacked feature branches are tested, lint once in its own job, update the actions to their current majors, and check the built distributions with twine. Move the ruff exclusions to the top-level table so `ruff check .` no longer parses the shell cells in the demo notebooks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Click 8.1, the newest release for Python 3.9, makes CliRunner read exhausted input as an empty line instead of raising EOFError, so an empty answer to the clone download prompt declines rather than aborts there. Real terminals abort on end of input with both versions; only the test harness differs. Expect the empty-line behaviour when Click is older than 8.2 so the Python 3.9 CI job tests the same outcomes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each test job writes coverage data under its OS and Python version and uploads it. A coverage job combines them, writes the report to the job summary, uploads XML and HTML reports, and fails below 90%. Some branches only run on one Python version or operating system, so no single job sees the total. The floor lives in the workflow rather than in pyproject.toml because pytest-cov would apply it to each partial run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upload the combined coverage.xml from the coverage job, verified with OIDC so no repository secret is needed; pull requests from forks upload tokenless. The upload cannot fail CI, and codecov.yml marks Codecov's statuses informational, so the floor in the workflow remains the only gate. Add a coverage badge and describe the coverage workflow in the contribution guide. The Codecov GitHub App must be installed on the lanisrc organization for uploads to be accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the disposable OpenSSH server fixture from test_ssh_integration.py into conftest.py, unchanged, so survey workflow and fault-injection tests can serve data over the same loopback server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a real threaded HTTP server for tests that serves a directory on 127.0.0.1 with python, Apache or CyVerse style listings, records each request, and applies scripted per-path faults: status codes, resets, short or unannounced-length bodies, flipped bytes, stalls, slow drips, redirects and pages without listings. Unlike MockServer, it exercises the real Requests and urllib3 code paths. Add deterministic generators for scaled-down DESI healpix, EHT UVFITS, simulation export and telescope layouts, a CliRunner helper, and fixtures that start servers and refuse non-loopback HTTP requests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add end-to-end tests for each workflow in doc/usecase.rst: telescope ingest and update, a bare simulation catalog with explicit downloads over SSH, isolated worktrees, nightly programmatic ingest, in-memory ParaFrame selection and private lab data from a named SSH remote. Also test DESI-like and EHT-like releases over loopback HTTP: published sha256 checksums and listing sizes are recorded, URL-pattern adds read no payloads, downloads honour --filter, --fmt and --output, a data release update is rescanned and refreshed, a silently corrupted file is rejected while the rest succeed, and Git catalogs and published snapshots clone with a download prompt. A loopback guard keeps every request on this machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Serve releases from the loopback HTTP server while it resets connections, truncates bodies, returns 404/429/5xx, stalls, flips bytes and redirects. Every faulted file must fail alone, leaving no partial destination or temporary file and no URL in the error, while the other files arrive intact; downloads must complete on a rerun; and a failed rescan, including an unreadable SSH folder, must leave the committed catalog and index untouched. chaos.py adds a snapshot of a repository's tracked state and an invariant check for corruption (unopenable repositories, objects that do not match their checksums, committed files without objects, git fsck errors) and leftover temporary files. A body truncated without Content-Length is still accepted when the catalog records the file's size but no checksum; that test is a strict expected failure until the download size is verified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fail the Nth file replacement or write with ENOSPC or EIO while staging, committing and downloading, and make an output folder read-only. A failed commit must keep the branch pointer, leave no corrupt object and succeed when retried; a download that runs out of space or permission must fail only the affected file. Dothm.save_state writes config.yml, meta.yml and data.tsv one at a time, so a failure after the first write leaves state files from different generations; those cases are strict expected failures until the writes are made atomic together. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run hm in a child process that sends itself SIGKILL at a chosen call while staging, committing, checking out, adding a worktree or downloading. The parent requires the kill to have happened, then checks that the repository is not corrupt and that rerunning the command finishes the job. An interrupted download must never leave a partial destination and must keep its unfinished data in a separate file. Two known recovery bugs are strict expected failures: a checkout killed after moving files to its backup folder cannot be rerun, and add_worktree skips restoring files when its destination already has .hm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A seeded "monkey" edits, stages, commits and switches branches while injecting full-disk and I/O errors, and a second one republishes, rescans and downloads a release while the server misbehaves. Instead of modelling every rule, they check what must always hold: operations succeed or raise a documented error; a failed operation changes neither the repository nor the worktree; checked-out files match their catalogued checksums; nothing is ever corrupt; and downloaded files are always versions the server published. A failure prints its seed, recent operations and the command that reproduces it. HALLMARK_CHAOS_SEED and HALLMARK_CHAOS_STEPS widen the search. The monkey found that checkout before the first commit raises a raw GitCommandError, recorded as a strict expected failure. Known bugs are listed where the monkey steers around them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With HALLMARK_RUN_LIVE_TESTS=1, follow the public-collection examples in doc/private_data.rst: catalog DESI DR1 healpix files and verify the downloads against the release's sha256 manifest, and catalog and download EHT M87 UVFITS files from CyVerse, including through a URL pattern. Every plan is checked before approval so a run downloads a few megabytes at most. Tests skip, rather than fail, when an archive is down or times out. CyVerse lists sizes such as "554K", which Hallmark does not record, so CyVerse downloads are limited to single, exactly named files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every night, run the chaos tests on Linux (Python 3.9 and 3.14) and macOS with fresh seeds and 2000 random operations per seed, keeping the failed repositories as artifacts, and run the live survey tests. Scheduled and manual runs start only from the default branch, so pull requests that change these tests or the workflow run it too, with fewer operations. Document how to run and extend these tests and how to record the bugs they find. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CyVerse listings can take longer than Hallmark's read timeout even after the availability probe succeeds. Treat timeouts and server errors during the catalog scan, as during downloads, as the archive being unavailable, so the nightly job reports Hallmark failures rather than archive load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
denniswu28
added a commit
that referenced
this pull request
Oct 10, 2026
The first CI run on this branch combined 90.45% branch coverage across all eight test jobs, with 27-29 tests failing in each. A floor of 90 would leave under half a point of margin, so use #59's rule of one point below the whole-number total: 89. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
denniswu28
added a commit
that referenced
this pull request
Oct 10, 2026
Both CI runs on #59 failed to download the Codecov CLI from cli.codecov.io, and fail_ci_if_error: false hid that, so Codecov has never received a report. Install the CLI from PyPI instead, and let an upload error fail the step but not the job, so a rejected or failed upload is visible while the in-workflow floor stays the only gate.
denniswu28
added a commit
that referenced
this pull request
Oct 10, 2026
The first CI run on this branch combined 90.45% branch coverage across all eight test jobs, with 27-29 tests failing in each. A floor of 90 would leave under half a point of margin, so use #59's rule of one point below the whole-number total: 89.
Author
|
Retiring this draft. Work has moved from |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Sets up CI that tests the whole repository with coverage, and adds fault-injection ("chaos monkey") and survey-workflow test suites. Stacked on
ram/clean-up; retarget todev/mainonce that merges.CI (
.github/workflows/ci.yml)main/dev, and manual dispatch.coveragejob combines coverage from all 8 jobs, writes the report to the job summary, uploads XML/HTML, uploads to Codecov (OIDC, no secret), and enforces a 90% floor in CI itself. Codecov statuses are informational.distribution-and-docsadditionally runstwine check --strictand smoke-tests bothhmandhallmark.ruff check .works.Nightly (
.github/workflows/nightly.yml): chaos tests with fresh seeds and 2,000 random operations per seed (Linux 3.9/3.14, macOS 3.14), and live downloads of ~2 MB from DESI DR1 and EHT/CyVerse. It also runs on PRs that touch these tests, since schedules only start frommain.Tests
test/http_server.py: a real loopback HTTP server (python/Apache/CyVerse listings) with scripted faults: resets, short and unannounced-length bodies, 404/429/5xx, stalls, slow drips, bit flips, redirects.test/test_survey.py(-m survey): one scenario perdoc/usecase.rstuse case, plus DESI-like and EHT-like releases, release updates, silent corruption, Git and snapshot clones. No request leaves the machine.test/test_chaos_*.py(-m chaos): network faults, full disk and I/O errors, SIGKILL at chosen calls, and seeded random operation sequences checked against repository invariants.test/test_survey_live.py(-m survey_live, opt-in): real DESI DR1 and EHT downloads, size-capped, and skipped when an archive is down.Bugs found (strict expected failures; each fix goes on its own branch)
Dothm.save_statewrites state files non-atomically, so a failedaddcan leave mixed generations: A failed add can leave config.yml, meta.yml and data.tsv from different states #55add_worktreererun after a crash leaves the worktree without files: add_worktree rerun after an interruption leaves the worktree without files #57GitCommandError: Checkout before the first commit shows a raw Git error #58Also fixes a Python 3.9-only test failure caused by Click 8.1's
CliRunner(it never ran in CI onram/clean-up).Needs an org admin
Install the Codecov GitHub App on
lanisrc, then rerun thecoveragejob. Until then the upload step logs a warning and CI is gated by the in-workflow floor.Testing
actionlinton both workflows;codecov.ymlvalidated;twine check/Sphinx-Wpass.hm add .from a subfolder drops staged rows); not fixed here.cli.codecov.io, so nothing was uploaded; the step is non-blocking. Uploads also need the Codecov app installed (above).🤖 Generated with Claude Code