Skip to content

feat: add synthetic test data sets - #9

Open
uniqueg wants to merge 3 commits into
mainfrom
feat/6-test-resources
Open

uniqueg wants to merge 3 commits into
mainfrom
feat/6-test-resources

Conversation

@uniqueg

@uniqueg uniqueg commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Summary

Publishes small, open test data sets for the demos (D4.6 test resources).

  • data/synthetic-growth/node-a.csv and node-b.csv: one partition per Node, 50 rows each, CC0. The data are synthetic and made up by a seeded generator. They describe no person, organism or experiment.
  • data/manifest.json: the URL (raw GitHub, main), size and SHA-256 of every file. Demos and TES tasks reference the data through this manifest.
  • scripts/generate_test_data.py: the reproducible generator. The tests fail if the committed files differ from its output.
  • data/README.md and the root README document the data sets, their locations and how to regenerate them.
  • First tooling and CI for the repository: pyproject.toml with uv, ruff, mypy and pytest (100% coverage), and .github/workflows/ci.yml (Lint, Test, gate CI passed). The retired demo 2023-ecp-f2f is excluded.

The federated analytics demo (#5) uses this data and follows in a separate PR.

Closes #6

Verification

  • uv run pytest: 8 passed, 100% coverage
  • uv run ruff check ., uv run ruff format --check . and uv run mypy: clean
  • Run in a clean checkout of the branch
  • CI: Lint, Test and CI passed green (run 43502346076)

Review

adversarial-reviewer and quality-reviewer: no high findings. Fixed: line endings pinned with .gitattributes and an LF manifest, a note that the URLs follow main, a test for the documented difference between Nodes, match= on the error test, and one form of the commands in the docs.

Declined review findings

  • Duplicated setup steps in the Lint and Test jobs: this follows the org's CI pattern.
  • Silent offset fallback for unknown Node names in make_rows: harmless, because the module only uses known Nodes.

Note for the maintainer

  • After the merge, the new check CI passed can be required in the repo's ruleset (maintainer action).

🤖 Generated with Claude Code

Summary by Sourcery

Introduce reproducible synthetic test data and the tooling, documentation, and CI needed to validate it.

New Features:

  • Add a reproducible, CC0-licensed synthetic growth data set split into Node-specific CSV partitions with a manifest containing download metadata and checksums.

Enhancements:

  • Provide documentation describing the synthetic data, usage, provenance, and regeneration process.

Build:

  • Add uv project configuration and locked development dependencies for Ruff, mypy, pytest, and coverage enforcement.

CI:

  • Add GitHub Actions linting, formatting, type-checking, test, and aggregate CI gate jobs.

Documentation:

  • Document the repository test data and local CI verification commands.

Tests:

  • Add comprehensive generator tests, including deterministic output, manifest integrity, committed-data consistency, and Node partition differences.

Chores:

  • Pin repository line endings and exclude the retired demo from automated checks.

uniqueg and others added 2 commits November 13, 2026 21:25
Add one CSV partition per Node of a synthetic data set, a manifest
with URLs, sizes and checksums, and the seeded generator that writes
them. Tests check that the committed files match the generator. Add
CI (lint, test, gate) for the Python code of the repository.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep LF endings of the test data, write the manifest with LF, say that
the URLs follow main, and test the documented difference between the
partitions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Data structures

Add the synthetic-growth partitions and manifest that publish their Node assignments, download URLs, sizes, checksums, and dataset metadata.

  • data/manifest.json L1-31
  • data/synthetic-growth/node-a.csv L1-51
  • data/synthetic-growth/node-b.csv L1-51

Implementation

Implement deterministic generation of the Node partitions and their manifest, including the command-line entry point.

  • scripts/generate_test_data.py L1-168

Configuration

Configure Python development tooling and CI lint, test, and gate jobs, alongside repository ignore and line-ending rules.

  • .gitattributes L1-2
  • .github/workflows/ci.yml L1-93
  • .gitignore L183
  • pyproject.toml L1-41

Documentation

Document the synthetic datasets, their locations and regeneration, and the local checks for contributors.

  • README.md L29-35, L56-65, L98
  • data/README.md L1-55

Tests

Test generator determinism, partition differences, output and manifest integrity, CLI behavior, and agreement with committed data.

  • tests/test_generate_test_data.py L1-93

Lock files and vendored code

Lock the development dependency set used by the new Python tooling and CI.

  • uv.lock L1-487

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@uniqueg
uniqueg marked this pull request as ready for review November 13, 2026 20:33
@sourcery-ai

sourcery-ai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Linked issues

Checked at commit 50c6acb

#6 demo: provide test resources · 0 of 1 met

# Requirement Status Notes
1 Publish small, open test data sets and their locations, and reference them from the demos. 🟡 Partly met The synthetic CSVs and manifest are added and documented, but no demo references or uses them in this change; the PR says the federated analytics demo will follow in a separate PR.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 5 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="scripts/generate_test_data.py" line_range="113" />
<code_context>
+        content = _to_csv(make_rows(node=node))
+        target = out_dir / rel_path
+        target.parent.mkdir(parents=True, exist_ok=True)
+        target.write_bytes(content)
+        files.append(
+            {
</code_context>
<issue_to_address>
**Mixed data generations**

When generation is interrupted or different generator versions write to the same output directory, `write_data_sets` overwrites CSVs one at a time and writes the manifest afterward, leaving old and new partitions paired with a stale manifest if generation stops or overlaps; consumers see checksum mismatches or inconsistent partitions.

Generate the CSVs and manifest in a separate staging directory, then publish the completed generation atomically while preventing concurrent writers from mixing generations.

Also at `scripts/generate_test_data.py:139`.
</issue_to_address>

### Comment 2
<location path="data/manifest.json" line_range="17" />
<code_context>
+        {
+          "node": "node-a",
+          "path": "synthetic-growth/node-a.csv",
+          "url": "https://raw.githubusercontent.com/elixir-cloud-aai/elixir-cloud-demos/main/data/synthetic-growth/node-a.csv",
+          "sha256": "425161d3670348f82b5fa1144dc9528b236c5a02fab4e609d5bbcd02fcff0f0f",
+          "size": 1626
</code_context>
<issue_to_address>
**Manifest checksums stop matching**

When `main` advances between a client fetching the manifest and downloading its listed CSVs, the manifest URLs resolve to files from the newer revision, so checksum validation fails or a client combines partitions from different revisions.

Use immutable revision-specific URLs in the manifest instead of URLs that resolve through `main`.

Also at `data/manifest.json:24`.
</issue_to_address>

### Comment 3
<location path="scripts/generate_test_data.py" line_range="74-76" />
<code_context>
+            {
+                "sample_id": f"{node}-{idx + 1:03d}",
+                "condition": condition,
+                "od600": f"{max(0.01, rng.gauss(od_mean + offset, 0.1)):.3f}",
+                "expression": f"{rng.gauss(expr_mean, 1.5):.3f}",
+            }
+        )
+    return rows
</code_context>
<issue_to_address>
**Regeneration changes across Python versions**

When the generator is run under a supported Python version whose `gauss` implementation or math behavior differs from CI's Python 3.13, `random.Random.gauss` can produce a different sequence if its implementation or math behavior changes, so `make_rows` rewrites the CSV bytes and checksums and `test_committed_data_match_generator` fails under that interpreter.

Use a specified, version-independent sampling algorithm for the generated values, or constrain generation and artifact checks to a pinned Python runtime.
</issue_to_address>

### Comment 4
<location path="scripts/generate_test_data.py" line_range="118" />
<code_context>
+            {
+                "node": node,
+                "path": rel_path,
+                "url": f"{base_url}/{rel_path}",
+                "sha256": hashlib.sha256(content).hexdigest(),
+                "size": len(content),
</code_context>
<issue_to_address>
**Partition URLs have extra slash**

When a caller supplies a slash-terminated `base_url`, `write_data_sets` appends another slash when building each URL, producing an empty path segment; servers that distinguish repeated slashes do not find the file, so consumers cannot download the partition.

Normalize the trailing slash from `base_url` before joining it with `rel_path`.
</issue_to_address>

### Comment 5
<location path="README.md" line_range="29-31" />
<code_context>
 | --- | --- | --- |
 | [2023-ecp-f2f](demos/2023-ecp-f2f/README.md) | ELIXIR Compute Face-to-Face, Helsinki, Feb 7-8, 2023 | Task execution via the [Task Execution Service (TES) API](https://github.com/ga4gh/task-execution-schemas/) on Kubernetes and HPC; TES-based task distribution with random and distance-based task distribution logic; execution of a CWL workflow via the `cwl-tes` TES backend |

+## Test data
+
+The folder [`data/`](data/README.md) holds small, open and synthetic test
+data sets for the demos, e.g. one partition per Node for federated analytics.
+Its [`manifest.json`](data/manifest.json) lists the URL, size and checksum of
</code_context>
<issue_to_address>
**Demo references are missing**

The change documents test data for the demos and publishes a manifest, but does not reference the data from any demo. Add the data references to the demos that use it.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 5 findings to address first, and the CSV partitions and manifest become public and can be downloaded or copied into demo runs; reverting removes the current main URLs but does not erase the original commit or copies already taken. Because these are synthetic fixtures, incorrect values are bounded and can be replaced or regenerated.

Blocking findings: scripts/generate_test_data.py:113, data/manifest.json:17, scripts/generate_test_data.py:76, scripts/generate_test_data.py:118, README.md:31


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread scripts/generate_test_data.py Resolved
Comment thread data/manifest.json Resolved
Comment thread scripts/generate_test_data.py Resolved
Comment thread scripts/generate_test_data.py Resolved
Comment thread README.md Resolved
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

demo: provide test resources

1 participant