Skip to content

Commit 78484cf

Browse files
authored
Merge pull request #3 from OpenNeuroOrg/rf/ondiagnostics-refactor
rf: Use ondiagnostics tools to fetch data
2 parents 4e3ba37 + 41e7a2a commit 78484cf

53 files changed

Lines changed: 3180 additions & 1310 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/update-data.yml

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Update Dashboard Data
22

33
on:
44
schedule:
5-
- cron: '0 6 * * *' # Daily at 6am UTC
5+
- cron: "0 6 * * *" # Daily at 6am UTC
66
workflow_dispatch:
77

88
permissions:
@@ -22,7 +22,7 @@ jobs:
2222
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
2323

2424
- name: Set up Python
25-
run: uv python install 3.13
25+
run: uv python install 3.14
2626

2727
- name: Restore bare repo cache
2828
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
@@ -31,20 +31,8 @@ jobs:
3131
key: git-repos-${{ github.run_id }}
3232
restore-keys: git-repos-
3333

34-
- name: Fetch GraphQL data
35-
run: uv run scripts/fetch_graphql.py --output-dir data
36-
37-
- name: Check GitHub mirrors
38-
run: uv run scripts/check_github.py --output-dir data
39-
40-
- name: Check S3 versions
41-
run: uv run scripts/check_s3_version.py --output-dir data
42-
43-
- name: Check S3 files
44-
run: uv run scripts/check_s3_files.py --output-dir data --cache-dir ~/.cache/openneuro-dashboard/repos
45-
46-
- name: Generate summary
47-
run: uv run scripts/summarize.py --output-dir data
34+
- name: Run pipeline
35+
run: uv run openneuro-dashboard run-all
4836

4937
- name: Commit and push if changed
5038
run: |

CLAUDE.md

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ OpenNeuro Dataset Monitor — a static HTML/JS dashboard with a Python data pipe
88

99
## Architecture
1010

11-
**Data Pipeline** (5-stage ETL):
11+
**Data Pipeline** (5-stage ETL, implemented in `code/src/openneuro_dashboard/`):
1212

1313
```
14-
fetch_graphql.pycheck_github.pycheck_s3_version.pycheck_s3_files.py → summarize.py
14+
fetch-graphqlcheck-githubcheck-s3-versioncheck-s3-files → summarize
1515
```
1616

1717
Each stage reads outputs from previous stages and can be run independently.
@@ -20,28 +20,39 @@ Each stage reads outputs from previous stages and can be run independently.
2020

2121
**Data**: Pipeline outputs go to `data/` as JSON. The dashboard loads these via fetch. Schema defined in `schema/openneuro-dashboard.yaml` (LinkML, version 1.0.0).
2222

23-
## Running Scripts
23+
## Running the Pipeline
2424

25-
All Python scripts use **`uv`** with inline PEP 723 dependency declarations (no requirements.txt or pyproject.toml). Run with:
25+
The pipeline is an installable Python package with a `openneuro-dashboard` CLI:
2626

2727
```bash
28-
uv run scripts/fetch_graphql.py
29-
uv run scripts/check_github.py
30-
uv run scripts/check_s3_version.py
31-
uv run scripts/check_s3_files.py --cache-dir ~/.cache/openneuro-dashboard/repos
28+
cd code
29+
uv sync
30+
uv run openneuro-dashboard run-all --output-dir ../data
3231
```
3332

34-
Test data generators:
33+
Individual stages:
34+
35+
```bash
36+
cd code
37+
uv run openneuro-dashboard fetch-graphql --output-dir ../data
38+
uv run openneuro-dashboard check-github --output-dir ../data
39+
uv run openneuro-dashboard check-s3-version --output-dir ../data
40+
uv run openneuro-dashboard check-s3-files --output-dir ../data --cache-dir ~/.cache/openneuro-dashboard/repos
41+
uv run openneuro-dashboard summarize --output-dir ../data
42+
```
43+
44+
Test data generation:
45+
3546
```bash
36-
uv run scripts/gen_data/graphql.py
37-
uv run scripts/gen_data/github.py
38-
uv run scripts/gen_data/s3_version.py
47+
cd code
48+
uv run openneuro-dashboard gen-data --output-dir ../data --seed 42
3949
```
4050

41-
After running either the full or test scripts, aggregate summary data with:
51+
## Running Tests
4252

4353
```bash
44-
uv run scripts/summarize.py
54+
cd code
55+
uv run --group test pytest -v
4556
```
4657

4758
## Serving the Dashboard
@@ -54,7 +65,7 @@ python -m http.server 8000
5465
## Key Conventions
5566

5667
- Dataset IDs match pattern `^ds[0-9]{6}$`
57-
- All output JSON files include `schemaVersion: "1.1.0"` (from `scripts/utils.py:SCHEMA_VERSION`)
68+
- All output JSON files include `schemaVersion: "1.1.0"` (from `code/src/openneuro_dashboard/utils.py:SCHEMA_VERSION`)
5869
- Snapshot metadata and file listings are immutable; registry, check results, and summary are mutable
59-
- Scripts use async I/O (asyncio) and include `--validate` flags for data consistency checking
60-
- Python requires >=3.13
70+
- Pipeline modules use async I/O (asyncio) and include `--validate` flags for data consistency checking
71+
- Python requires >=3.14

README.md

Lines changed: 40 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ A dashboard for tracking synchronization status of OpenNeuro datasets across Gra
99
The monitoring system uses a multi-stage pipeline that generates static JSON files consumed by a client-side dashboard:
1010

1111
```
12-
GraphQLGitHub Check → S3 Version → Git Trees → S3 Diff → Summarize → Dashboard
12+
fetch-graphqlcheck-github → check-s3-version → check-s3-files → summarize
1313
```
1414

1515
Each stage reads from previous stages and writes new check files, allowing incremental updates and independent execution.
1616

17+
The pipeline is implemented as an installable Python package under `code/`, exposing an `openneuro-dashboard` CLI.
18+
1719
### Data Model
1820

1921
All data files (aspirationally) follow a versioned schema defined in `schema/openneuro-dashboard.yaml` (LinkML format).
@@ -45,13 +47,15 @@ data/datasets/{id}/
4547
### Check Logic
4648

4749
#### GitHub Check
50+
4851
- Uses `git ls-remote --symref` to fetch all refs
4952
- Validates:
5053
- All snapshot tags exist on GitHub
5154
- HEAD points to latest snapshot
5255
- Commit SHAs match GraphQL data
5356

5457
#### S3 Version Check
58+
5559
- Fetches `dataset_description.json` from S3
5660
- Extracts version from `DatasetDOI` field
5761
- **Edge cases**:
@@ -64,6 +68,7 @@ data/datasets/{id}/
6468
- All other cases allow file comparison with assumed version
6569

6670
#### S3 File Diff
71+
6772
- Compares S3 file listing against git tree
6873
- Uses version from `s3-version.json` (either from DOI or assumed latest)
6974
- Skipped if S3 is blocked (403)
@@ -72,83 +77,68 @@ data/datasets/{id}/
7277
### Status Values
7378

7479
**Per-check statuses**:
80+
7581
- `ok`: Check passed
7682
- `warning`: Minor issues (e.g., assumed version, HEAD mismatch)
7783
- `error`: Check failed or blocked
7884
- `version-mismatch`: S3 DOI version ≠ latest snapshot
7985
- `pending`: Check not yet run
8086

8187
**Special flags**:
82-
- `s3Blocked: true` in summary indicates 403 error (shows lock icon 🔒)
83-
84-
## Running the Pipeline
8588

86-
Some scripts declare dependencies in their headers.
87-
The simplest way to run these scripts is `uv run`.
89+
- `s3Blocked: true` in summary indicates 403 error (shows lock icon)
8890

89-
### Stage 1: Fetch GraphQL Data
91+
## Setup
9092

9193
```bash
92-
uv run scripts/fetch_graphql.py --output-dir data
94+
uv sync
9395
```
9496

95-
Queries OpenNeuro GraphQL API for all public datasets and their snapshots. Creates:
96-
- `datasets-registry.json`
97-
- Per-dataset `snapshots.json` and `snapshots/{tag}/metadata.json`
97+
Requires Python 3.14+.
9898

99-
**Options**:
100-
- `--page-size N`: Datasets per GraphQL page (default: 100)
101-
- `--prefetch N`: Pages to buffer (default: 2)
102-
- `--verbose`: Detailed logging
99+
## Running the Pipeline
103100

104-
### Stage 2: Check GitHub Mirrors
101+
### Full Pipeline
105102

106103
```bash
107-
uv run scripts/check_github.py --output-dir data
104+
uv run openneuro-dashboard run-all
108105
```
109106

110-
Validates GitHub mirror status for all datasets.
111-
112-
**Options**:
113-
- `--concurrency N`: Parallel git operations (default: 10)
114-
- `--validate`: Run post-check validation
115-
- `--verbose`: Detailed logging
116-
117-
### Stage 3: Check S3 Versions
107+
### Individual Stages
118108

119109
```bash
120-
uv run scripts/check_s3_version.py --output-dir data
121-
```
110+
# Stage 1: Fetch GraphQL data
111+
uv run openneuro-dashboard fetch-graphql
122112

123-
Fetches `dataset_description.json` from S3 and extracts versions.
113+
# Stage 2: Check GitHub mirrors
114+
uv run openneuro-dashboard check-github
124115

125-
**Options**:
126-
- `--concurrency N`: Parallel HTTP requests (default: 20)
127-
- `--validate`: Run post-check validation
116+
# Stage 3: Check S3 versions
117+
uv run openneuro-dashboard check-s3-version
128118

129-
### Stage 4: Fetch Git File Trees
119+
# Stage 4: Check S3 files
120+
uv run openneuro-dashboard check-s3-files --cache-dir ~/.cache/openneuro-dashboard/repos
130121

131-
(Not yet implemented - currently using generated test data)
132-
133-
Should fetch file listings from git for each snapshot tag:
134-
```bash
135-
git clone --bare --depth=1 --filter=blob:none --branch {tag} {repo}
136-
git ls-files --with-tree {tag}
122+
# Stage 5: Summarize
123+
uv run openneuro-dashboard summarize
137124
```
138125

139-
### Stage 5: Generate S3 File Diffs
126+
Common options:
140127

141-
(Not yet implemented - currently using generated test data)
128+
- `--verbose` / `-v`: Enable verbose output
129+
- `--max-datasets N`: Limit number of datasets (for `fetch-graphql` and `run-all`)
142130

143-
Should compare S3 file listings against git trees and create `s3-diff.json`.
144-
145-
### Stage 6: Summarize
131+
### Generating Test Data
146132

147133
```bash
148-
uv run scripts/summarize.py --output-dir data
134+
uv run openneuro-dashboard gen-data --num-datasets 50 --seed 42
149135
```
150136

151-
Reads all check files and generates `all-datasets.json` with aggregated results.
137+
## Running Tests
138+
139+
```bash
140+
uv run --group test pytest -v
141+
```
152142

153143
## Dashboard
154144

@@ -165,7 +155,6 @@ Static HTML/CSS/JS dashboard served from the repository root.
165155
### Serving
166156

167157
```bash
168-
# Python
169158
python -m http.server 8000
170159
```
171160

@@ -174,43 +163,29 @@ Navigate to `http://localhost:8000`
174163
### Features
175164

176165
**Main view**:
166+
177167
- Sortable/filterable dataset table
178168
- Summary statistics by status
179169
- Search by dataset ID
180170
- Color-coded status badges
181-
- Lock icons (🔒) for blocked S3 datasets
171+
- Lock icons for blocked S3 datasets
182172

183173
**Detail view**:
174+
184175
- Snapshot history
185176
- Detailed check results with expandable sections
186177
- File diff viewer (when mismatches exist)
187178
- Lazy-loaded file listings
188179

189-
## Test Data Generation
190-
191-
Located in `scripts/gen_data/`, these scripts simulate pipeline stages for development:
192-
193-
```bash
194-
python scripts/gen_data/graphql.py
195-
python scripts/gen_data/github.py
196-
python scripts/gen_data/s3_version.py
197-
python scripts/gen_data/s3_version.py
198-
```
199-
200-
## Development Workflow
201-
202-
1. **Add real pipeline stage**: Implement stage script (e.g., `fetch_git_trees.py`)
203-
2. **Update test generator**: Modify corresponding `gen_data/*.py` to match
204-
3. **Test incrementally**: Run new stage, then existing summarize + dashboard
205-
4. **Validate**: Use `--validate` flags to check data consistency
206-
207180
## Data Immutability
208181

209182
**Immutable** (never changes once created):
183+
210184
- `snapshots/{tag}/metadata.json`
211185
- `snapshots/{tag}/files.json`
212186

213187
**Mutable** (updated on each check run):
188+
214189
- `datasets-registry.json`
215190
- `github.json`
216191
- `s3-version.json`
@@ -219,15 +194,6 @@ python scripts/gen_data/s3_version.py
219194

220195
This allows caching of snapshot data while keeping check results fresh.
221196

222-
## Future Enhancements
223-
224-
- [ ] Implement git tree fetching (stage 4)
225-
- [ ] Implement S3 file diff (stage 5)
226-
- [ ] Scripts to auto-fix issues based on outputs
227-
- [ ] Schedule data updates in CI
228-
- [ ] Track historical trends
229-
- [ ] Integration with GitHub issues to track known problems
230-
231197
## Schema Evolution
232198

233199
The LinkML schema (`schema/openneuro-dashboard.yaml`) includes a `schemaVersion` field in all data files. When making breaking changes:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""OpenNeuro Dashboard data-population tools.
2+
3+
ondiagnostics modules used
4+
--------------------------
5+
- ``ondiagnostics.graphql``: GraphQLResponse, PageInfo, create_client, get_page
6+
(pagination over the OpenNeuro GraphQL API in fetch_graphql.py)
7+
- ``ondiagnostics.subprocs``: git
8+
(async subprocess wrapper for bare-clone / fetch in check_s3_files.py)
9+
- ``ondiagnostics.tasks.git``: list_refs
10+
(remote ref listing for GitHub mirror checks in check_github.py)
11+
12+
Dashboard-specific logic
13+
------------------------
14+
- fetch_graphql: writes datasets-registry.json and per-snapshot metadata
15+
- check_github: compares registry against GitHub mirror refs
16+
- check_s3_version: extracts S3 export version from dataset_description.json
17+
- check_s3_files: diffs git tree against S3 object listing
18+
- summarize: aggregates per-dataset check results into all-datasets.json
19+
- utils: shared JSON I/O helpers and schema version constant
20+
"""

0 commit comments

Comments
 (0)