Skip to content

Commit 6b40c7b

Browse files
committed
Fix registry always showing only latest submitted schema
schema_submission.yml: replace individual seed→ingest-one-schema→align→export steps with pipeline.py --fresh --skip-converters, which ingests ALL schemas in schemas/ after writing the new file. Previous behaviour seeded a fresh DB and ingested only the submitted schema, so every submission wiped the registry back to schema.org + that one schema. publish_registry.yml: also triggers on push to main (paths: schemas/**, neuro_ghost/**) so merging this PR immediately kicks a full rebuild with external converters (BIDS/NWB/DANDI/…). pipeline.py: add --issue option passed through to ingest_linkml.py for accurate provenance tracking on schema submissions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXeTeJsXisxTRXay6EoBSQ
1 parent b1d08c8 commit 6b40c7b

3 files changed

Lines changed: 74 additions & 56 deletions

File tree

.github/workflows/publish_registry.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ name: Rebuild & Publish Registry
44
# A schema submission (schema_submission.yml) handles per-PR incremental updates;
55
# this workflow does a full clean rebuild on a schedule.
66
on:
7+
push:
8+
branches: [main]
9+
paths:
10+
- "schemas/**"
11+
- "neuro_ghost/**"
12+
- "requirements.txt"
713
workflow_dispatch:
814
inputs:
915
bump:

.github/workflows/schema_submission.yml

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
issues: write
1414

1515
steps:
16+
# -----------------------------------------------------------------------
1617
- name: Checkout
1718
uses: actions/checkout@v4
1819

@@ -21,9 +22,36 @@ jobs:
2122
with:
2223
python-version: "3.12"
2324

25+
# -----------------------------------------------------------------------
26+
- name: Cache pip
27+
uses: actions/cache@v4
28+
with:
29+
path: ~/.cache/pip
30+
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
31+
restore-keys: ${{ runner.os }}-pip-
32+
33+
- name: Cache sentence-transformers model
34+
uses: actions/cache@v4
35+
with:
36+
path: ~/.cache/huggingface/hub
37+
key: hf-minilm-v2
38+
restore-keys: hf-
39+
40+
# Embeddings cache keyed on all schemas — new schema busts the cache and
41+
# forces a recompute, unchanged schemas reuse their cached vectors.
42+
- name: Cache embeddings
43+
uses: actions/cache@v4
44+
with:
45+
path: data/embeddings.parquet
46+
key: embeddings-${{ hashFiles('schemas/*.yml') }}-${{ github.run_id }}
47+
restore-keys: embeddings-${{ hashFiles('schemas/*.yml') }}-
48+
embeddings-
49+
50+
# -----------------------------------------------------------------------
2451
- name: Install dependencies
2552
run: pip install -r requirements.txt
2653

54+
# -----------------------------------------------------------------------
2755
- name: Parse issue metadata
2856
id: meta
2957
run: |
@@ -32,16 +60,17 @@ jobs:
3260
SCHEMA_NAME=$(echo "$SCHEMA_NAME" | xargs | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
3361
echo "schema_name=$SCHEMA_NAME" >> $GITHUB_OUTPUT
3462
35-
# Determine bump type:
36-
# label "breaking" → major, default → minor
3763
LABELS='${{ toJson(github.event.issue.labels.*.name) }}'
3864
if echo "$LABELS" | grep -q "breaking"; then
3965
echo "bump=major" >> $GITHUB_OUTPUT
4066
else
4167
echo "bump=minor" >> $GITHUB_OUTPUT
4268
fi
4369
44-
- name: Extract and convert schema from issue body
70+
# -----------------------------------------------------------------------
71+
# Write the submitted schema to schemas/{name}.yml so it's picked up
72+
# by pipeline.py alongside all previously committed schemas.
73+
- name: Extract and write schema file
4574
env:
4675
ISSUE_BODY: ${{ github.event.issue.body }}
4776
SCHEMA_NAME: ${{ steps.meta.outputs.schema_name }}
@@ -53,9 +82,6 @@ jobs:
5382
body = os.environ["ISSUE_BODY"]
5483
name = os.environ["SCHEMA_NAME"]
5584
56-
# Detect format from the code-fence language tag:
57-
# ```linkml / ```yaml / ```yml → already LinkML
58-
# ```json / ```json-schema → JSON Schema, needs conversion
5985
fenced = re.search(r'```([\w-]*)\s*\n(.*?)```', body, re.DOTALL)
6086
if fenced:
6187
lang = (fenced.group(1) or "yaml").lower()
@@ -65,13 +91,12 @@ jobs:
6591
content = body.strip()
6692
6793
json_schema_langs = {"json", "json-schema", "jsonschema"}
68-
linkml_langs = {"yaml", "yml", "linkml", ""}
6994
7095
os.makedirs("schemas", exist_ok=True)
7196
out_path = f"schemas/{name}.yml"
7297
7398
if lang in json_schema_langs:
74-
print(f"Detected format: JSON Schema (lang={lang!r}) — converting to LinkML…")
99+
print(f"Detected format: JSON Schema ({lang!r}) — converting…")
75100
sys.path.insert(0, ".")
76101
from neuro_ghost.converters.from_jsonschema import convert as js2lm
77102
try:
@@ -82,54 +107,36 @@ jobs:
82107
with open(out_path, "w") as f:
83108
yaml.dump(linkml_dict, f, default_flow_style=False,
84109
allow_unicode=True, sort_keys=False)
85-
print(f"Converted → {out_path} "
86-
f"({len(linkml_dict['classes'])} classes, "
87-
f"{len(linkml_dict['slots'])} slots)")
88-
elif lang in linkml_langs or lang not in json_schema_langs:
89-
print(f"Detected format: LinkML (lang={lang!r})")
110+
print(f"Converted → {out_path} "
111+
f"({len(linkml_dict['classes'])} classes)")
112+
else:
113+
print(f"Detected format: LinkML ({lang!r})")
90114
with open(out_path, "w") as f:
91115
f.write(content)
92116
print(f"Wrote {out_path}")
93-
else:
94-
print(f"ERROR: Unsupported schema format '{lang}'. "
95-
"Use ```yaml (LinkML) or ```json (JSON Schema).")
96-
sys.exit(1)
97117
PYEOF
98118
119+
# -----------------------------------------------------------------------
99120
- name: Validate LinkML schema
100121
run: |
101-
python neuro_ghost/validate_schema.py schemas/${{ steps.meta.outputs.schema_name }}.yml
102-
103-
- name: Seed schema.org (if DB not cached)
122+
python neuro_ghost/validate_schema.py \
123+
schemas/${{ steps.meta.outputs.schema_name }}.yml
124+
125+
# -----------------------------------------------------------------------
126+
# Full rebuild from all schemas/*.yml in the repo (including the new one
127+
# written above). --skip-converters keeps CI fast — external schemas
128+
# (BIDS/NWB/DANDI/…) are refreshed by the weekly publish_registry.yml.
129+
- name: Rebuild registry (all local schemas)
104130
run: |
105-
python neuro_ghost/seed.py \
106-
--db registry.lbug \
107-
--registry-version 1.0.0
108-
109-
- name: Ingest schema
110-
run: |
111-
python neuro_ghost/ingest_linkml.py \
112-
--file schemas/${{ steps.meta.outputs.schema_name }}.yml \
113-
--db registry.lbug \
131+
python neuro_ghost/pipeline.py \
132+
--fresh \
133+
--skip-converters \
134+
--bump ${{ steps.meta.outputs.bump }} \
114135
--issue ${{ github.event.issue.number }} \
115136
--agent "${{ github.event.issue.user.login }}"
116137
117-
- name: Run alignment
118-
run: |
119-
python neuro_ghost/align.py \
120-
--source ${{ steps.meta.outputs.schema_name }} \
121-
--db registry.lbug
122-
123-
- name: Export + version registry
124-
run: |
125-
python neuro_ghost/export_json.py \
126-
--db registry.lbug \
127-
--bump ${{ steps.meta.outputs.bump }} \
128-
--issue ${{ github.event.issue.number }} \
129-
--agent "${{ github.event.issue.user.login }}" \
130-
--schema ${{ steps.meta.outputs.schema_name }}
131-
132-
- name: Commit all artifacts
138+
# -----------------------------------------------------------------------
139+
- name: Commit registry + schema file
133140
run: |
134141
git config user.name "github-actions[bot]"
135142
git config user.email "github-actions[bot]@users.noreply.github.com"
@@ -139,23 +146,24 @@ jobs:
139146
data/versions/ \
140147
data/provenance.json
141148
git diff --cached --quiet || git commit -m \
142-
"feat(registry): ingest ${{ steps.meta.outputs.schema_name }} from issue #${{ github.event.issue.number }}"
149+
"feat(registry): ingest ${{ steps.meta.outputs.schema_name }} (issue #${{ github.event.issue.number }})"
143150
git push
144151
152+
# -----------------------------------------------------------------------
145153
- name: Comment success
146154
if: success()
147155
uses: actions/github-script@v7
148156
with:
149157
script: |
150-
const name = "${{ steps.meta.outputs.schema_name }}";
151-
const pagesUrl = `https://${context.repo.owner}.github.io/${context.repo.repo}`;
158+
const name = "${{ steps.meta.outputs.schema_name }}";
159+
const pagesUrl = "https://sensein.group/NeuroGhost/";
152160
await github.rest.issues.createComment({
153161
owner: context.repo.owner, repo: context.repo.repo,
154162
issue_number: context.issue.number,
155163
body: [
156164
`✅ **\`${name}\` ingested successfully.**`,
157165
``,
158-
`- Classes, properties, and alignments committed.`,
166+
`- All schemas rebuilt and aligned.`,
159167
`- Provenance logged to \`data/provenance.json\`.`,
160168
`- Archived snapshot in \`data/versions/\`.`,
161169
``,
@@ -178,8 +186,7 @@ jobs:
178186
body: [
179187
`❌ **Ingestion failed.**`,
180188
``,
181-
`Check the run log for the specific LinkML validation error (e.g. an undefined slot, ` +
182-
`\`is_a\` parent, or range reference).`,
189+
`Check the run log for validation errors (undefined slot, \`is_a\` parent, or range).`,
183190
``,
184191
`[View run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})`,
185192
].join("\n"),

neuro_ghost/pipeline.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ def _run(cmd: list[str]) -> None:
5757
help="Version bump type for the registry export.")
5858
@click.option("--agent", default="local", show_default=True,
5959
help="Who is running this pipeline (recorded in provenance).")
60+
@click.option("--issue", default="",
61+
help="GitHub issue number to record in provenance (schema submissions).")
6062
def cli(db: str, fresh: bool, skip_converters: bool,
61-
schemas: tuple, bump: str, agent: str) -> None:
63+
schemas: tuple, bump: str, agent: str, issue: str) -> None:
6264
"""Run the full NeuroGhost ingestion pipeline."""
6365

6466
py = sys.executable
@@ -90,10 +92,13 @@ def cli(db: str, fresh: bool, skip_converters: bool,
9092
sys.exit(1)
9193

9294
for schema_file in targets:
93-
_run([py, str(HERE / "ingest_linkml.py"),
94-
"--file", str(schema_file),
95-
"--db", db,
96-
"--agent", agent])
95+
cmd = [py, str(HERE / "ingest_linkml.py"),
96+
"--file", str(schema_file),
97+
"--db", db,
98+
"--agent", agent]
99+
if issue:
100+
cmd += ["--issue", issue]
101+
_run(cmd)
97102

98103
# 5. Align
99104
_run([py, str(HERE / "align.py"), "--db", db])

0 commit comments

Comments
 (0)