Skip to content

Commit 0819435

Browse files
authored
Merge pull request #2 from G-PST/copilot/create-github-issues-for-tools
Add GitHub Actions workflow to create per-tool data-schema issues
2 parents 427d526 + 969c68d commit 0819435

3 files changed

Lines changed: 253 additions & 0 deletions

File tree

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/usr/bin/env python3
2+
"""Create one GitHub issue per tool in the data-schema-excercise repository.
3+
4+
This script is idempotent: it checks whether an open issue with the expected
5+
title already exists before creating a new one. Run it via the companion
6+
GitHub Actions workflow, or locally (requires the ``gh`` CLI and a token
7+
with ``issues: write`` permission):
8+
9+
python3 .github/scripts/create_tool_issues.py
10+
"""
11+
12+
import json
13+
import os
14+
import subprocess
15+
import sys
16+
import tempfile
17+
18+
REPO = "G-PST/data-schema-excercise"
19+
BASE_URL = "https://github.com/G-PST/data-schema-excercise"
20+
INSTRUCTIONS_URL = (
21+
f"{BASE_URL}/blob/main/.github/ISSUE_TEMPLATE/fill_out_schema.md"
22+
)
23+
24+
# (Display name, YAML filename) for every tool in data_schemas/
25+
TOOLS = [
26+
("Sienna Data Model", "sienna_data_model.yaml"),
27+
("GenX Data Model", "genx_data_model.yaml"),
28+
("Grid Data Model", "grid_data_model.yaml"),
29+
("CommonEnergySystemModel", "common_energy_system_model.yaml"),
30+
("PyPSA Data Model", "pypsa_data_model.yaml"),
31+
("Encoord Data Model", "encoord_data_model.yaml"),
32+
("CIM/ENTSO-E", "cim_entso_e.yaml"),
33+
]
34+
35+
36+
def gh(*args):
37+
"""Run a ``gh`` CLI command and return the CompletedProcess."""
38+
return subprocess.run(["gh"] + list(args), capture_output=True, text=True)
39+
40+
41+
def ensure_label():
42+
"""Create the ``fill-out-schema`` label if it does not already exist."""
43+
r = gh(
44+
"label", "create", "fill-out-schema",
45+
"--repo", REPO,
46+
"--color", "0075ca",
47+
"--description", "Fill out existing tool data schema sheet",
48+
"--force",
49+
)
50+
if r.returncode != 0:
51+
print(f"Warning: could not create label: {r.stderr}", file=sys.stderr)
52+
53+
54+
def issue_exists(title):
55+
"""Return True if an open issue with this title already exists."""
56+
r = gh(
57+
"issue", "list",
58+
"--repo", REPO,
59+
"--state", "open",
60+
"--json", "title",
61+
"--limit", "100",
62+
)
63+
if r.returncode != 0:
64+
return False
65+
issues = json.loads(r.stdout or "[]")
66+
return any(i["title"] == title for i in issues)
67+
68+
69+
def build_body(tool_name, yaml_file):
70+
"""Return the Markdown body for the issue."""
71+
yaml_url = f"{BASE_URL}/blob/main/data_schemas/{yaml_file}"
72+
branch_name = yaml_file.replace(".yaml", "")
73+
74+
return f"""\
75+
## Tool
76+
77+
**Tool / Schema Name:** {tool_name}
78+
**YAML file:** [`data_schemas/{yaml_file}`]({yaml_url})
79+
80+
---
81+
82+
## Background
83+
84+
This repository collects **data schema information sheets** for power systems
85+
planning tools used for cross-project comparison at the
86+
**G-PST Power System Planning Interoperability Data Schema Workshop**.
87+
88+
A placeholder YAML file for **{tool_name}** already exists at
89+
`data_schemas/{yaml_file}`. Please fill it out and open a Pull Request.
90+
91+
---
92+
93+
## Instructions
94+
95+
Full step-by-step instructions are in
96+
[`fill_out_schema.md`]({INSTRUCTIONS_URL}).
97+
98+
### Quick Summary
99+
100+
1. Open [`data_schemas/{yaml_file}`]({yaml_url}).
101+
2. Replace every `<...>` placeholder with real information.
102+
3. Use `~` (YAML null) for any fields that do not apply.
103+
4. Validate locally (see **Validation** below).
104+
5. Open a Pull Request targeting `main` and link this issue in the description.
105+
106+
### File Location and Naming Convention
107+
108+
- **File to edit:** `data_schemas/{yaml_file}`
109+
- Keep the existing filename — do not rename it.
110+
- The file lives in the `data_schemas/` directory at the repository root.
111+
112+
### Required Sections
113+
114+
All sections in the YAML must be addressed:
115+
116+
| Section | Key Fields |
117+
|---------|------------|
118+
| `identity` | schema_name, organization, maintainers, repository, documentation, license, version, maturity |
119+
| `summary` | description, modeling_domains_supported, what_does_it_NOT_cover, data_captured, conceptual_structure |
120+
| `design` | key_decisions, schema_format, implementation_languages, interoperability, units_handling, validation_approach, governance |
121+
| `usage` | tools_built_on_schema, largest_real_world_dataset, who_is_using_it, data_available |
122+
| `challenges` | known_limitations, hardest_problems_encountered |
123+
| `interoperability` | areas_of_overlap_with_other_schemas, what_would_convergence_require, biggest_thing_others_should_know |
124+
| `card_metadata` | prepared_by, date |
125+
126+
### Validation
127+
128+
Run `yamllint` locally before pushing:
129+
130+
```bash
131+
pip install yamllint
132+
yamllint -c .yamllint.yaml data_schemas/{yaml_file}
133+
```
134+
135+
CI will also lint your file automatically when you open a PR.
136+
137+
### Opening a Pull Request
138+
139+
**External contributors (Fork & PR):**
140+
1. Fork this repository.
141+
2. Edit `data_schemas/{yaml_file}` in your fork.
142+
3. Open a PR to `main` titled: `Fill out data schema sheet: {tool_name}`.
143+
4. Paste this issue's URL in the PR description.
144+
145+
**Contributors with write access (Branch & PR):**
146+
147+
```bash
148+
git checkout main && git pull
149+
git checkout -b fill-schema/{branch_name}
150+
# Edit data_schemas/{yaml_file}
151+
git add data_schemas/{yaml_file}
152+
git commit -m "Fill out data schema sheet: {tool_name}"
153+
git push origin fill-schema/{branch_name}
154+
```
155+
156+
Then open a PR on GitHub targeting `main` and link this issue.
157+
158+
---
159+
160+
## Acceptance Criteria
161+
162+
- [ ] All `<...>` placeholders in `data_schemas/{yaml_file}` replaced with real content (or `~` where not applicable)
163+
- [ ] `identity` section complete: schema_name, organization, maintainers, repository, license, version, maturity
164+
- [ ] `summary` section describes what the schema covers **and** what it does NOT cover
165+
- [ ] `design` section covers key decisions, schema format, and implementation languages
166+
- [ ] `usage` section includes real-world datasets and known users
167+
- [ ] `challenges` section lists known limitations
168+
- [ ] `interoperability` section addresses overlap with other schemas in this comparison
169+
- [ ] `card_metadata` filled in (prepared_by, date)
170+
- [ ] `yamllint` passes locally with no errors
171+
- [ ] Pull Request opened targeting `main` with this issue linked in the PR description
172+
- [ ] PR reviewed and merged by a maintainer
173+
174+
---
175+
176+
_Questions? Comment on this issue._
177+
"""
178+
179+
180+
def create_issue(tool_name, yaml_file):
181+
title = f"Fill out data schema sheet: {tool_name}"
182+
183+
if issue_exists(title):
184+
print(f"Issue already exists for '{tool_name}', skipping.")
185+
return
186+
187+
body = build_body(tool_name, yaml_file)
188+
189+
with tempfile.NamedTemporaryFile(
190+
mode="w", suffix=".md", delete=False
191+
) as tmp:
192+
tmp.write(body)
193+
tmp_path = tmp.name
194+
195+
try:
196+
r = gh(
197+
"issue", "create",
198+
"--repo", REPO,
199+
"--title", title,
200+
"--body-file", tmp_path,
201+
"--label", "fill-out-schema",
202+
)
203+
if r.returncode == 0:
204+
print(f"Created issue for '{tool_name}': {r.stdout.strip()}")
205+
else:
206+
print(
207+
f"ERROR creating issue for '{tool_name}': {r.stderr}",
208+
file=sys.stderr,
209+
)
210+
sys.exit(1)
211+
finally:
212+
os.unlink(tmp_path)
213+
214+
215+
def main():
216+
ensure_label()
217+
for tool_name, yaml_file in TOOLS:
218+
create_issue(tool_name, yaml_file)
219+
220+
221+
if __name__ == "__main__":
222+
main()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Create tool data-schema issues
2+
3+
# Runs automatically the first time these files land on main, and can be
4+
# triggered manually at any time. The script is idempotent — re-running it
5+
# will not create duplicate issues.
6+
on:
7+
push:
8+
branches:
9+
- main
10+
paths:
11+
- .github/workflows/create-tool-issues.yml
12+
- .github/scripts/create_tool_issues.py
13+
workflow_dispatch:
14+
15+
jobs:
16+
create-issues:
17+
name: Create one issue per tool
18+
runs-on: ubuntu-latest
19+
permissions:
20+
issues: write
21+
contents: read
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- name: Create issues for each tool
26+
env:
27+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28+
run: python3 .github/scripts/create_tool_issues.py

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo

0 commit comments

Comments
 (0)