From f216b1cbf5b8e85f4d3a1ead4a05c958e89c9ee6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:50:40 +0000 Subject: [PATCH 1/3] Initial plan From 1d7c0b9c49cb7a42b4f3addfd7fc4299a5a3147d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:56:42 +0000 Subject: [PATCH 2/3] Add workflow and script to create one GitHub Issue per tool Co-authored-by: mooneyme <7425288+mooneyme@users.noreply.github.com> --- .../create_tool_issues.cpython-312.pyc | Bin 0 -> 9154 bytes .github/scripts/create_tool_issues.py | 222 ++++++++++++++++++ .github/workflows/create-tool-issues.yml | 28 +++ 3 files changed, 250 insertions(+) create mode 100644 .github/scripts/__pycache__/create_tool_issues.cpython-312.pyc create mode 100644 .github/scripts/create_tool_issues.py create mode 100644 .github/workflows/create-tool-issues.yml diff --git a/.github/scripts/__pycache__/create_tool_issues.cpython-312.pyc b/.github/scripts/__pycache__/create_tool_issues.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9607f0fdcd0892228792ef6d60d3a1c63ebe0161 GIT binary patch literal 9154 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 literal 0 HcmV?d00001 diff --git a/.github/scripts/create_tool_issues.py b/.github/scripts/create_tool_issues.py new file mode 100644 index 0000000..ddc9a99 --- /dev/null +++ b/.github/scripts/create_tool_issues.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python3 +"""Create one GitHub issue per tool in the data-schema-excercise repository. + +This script is idempotent: it checks whether an open issue with the expected +title already exists before creating a new one. Run it via the companion +GitHub Actions workflow, or locally (requires the ``gh`` CLI and a token +with ``issues: write`` permission): + + python3 .github/scripts/create_tool_issues.py +""" + +import json +import os +import subprocess +import sys +import tempfile + +REPO = "G-PST/data-schema-excercise" +BASE_URL = "https://github.com/G-PST/data-schema-excercise" +INSTRUCTIONS_URL = ( + f"{BASE_URL}/blob/main/.github/ISSUE_TEMPLATE/fill_out_schema.md" +) + +# (Display name, YAML filename) for every tool in data_schemas/ +TOOLS = [ + ("Sienna Data Model", "sienna_data_model.yaml"), + ("GenX Data Model", "genx_data_model.yaml"), + ("Grid Data Model", "grid_data_model.yaml"), + ("CommonEnergySystemModel", "common_energy_system_model.yaml"), + ("PyPSA Data Model", "pypsa_data_model.yaml"), + ("Encoord Data Model", "encoord_data_model.yaml"), + ("CIM/ENTSO-E", "cim_entso_e.yaml"), +] + + +def gh(*args): + """Run a ``gh`` CLI command and return the CompletedProcess.""" + return subprocess.run(["gh"] + list(args), capture_output=True, text=True) + + +def ensure_label(): + """Create the ``fill-out-schema`` label if it does not already exist.""" + r = gh( + "label", "create", "fill-out-schema", + "--repo", REPO, + "--color", "0075ca", + "--description", "Fill out existing tool data schema sheet", + "--force", + ) + if r.returncode != 0: + print(f"Warning: could not create label: {r.stderr}", file=sys.stderr) + + +def issue_exists(title): + """Return True if an open issue with this title already exists.""" + r = gh( + "issue", "list", + "--repo", REPO, + "--state", "open", + "--json", "title", + "--limit", "100", + ) + if r.returncode != 0: + return False + issues = json.loads(r.stdout or "[]") + return any(i["title"] == title for i in issues) + + +def build_body(tool_name, yaml_file): + """Return the Markdown body for the issue.""" + yaml_url = f"{BASE_URL}/blob/main/data_schemas/{yaml_file}" + branch_name = yaml_file.replace(".yaml", "") + + return f"""\ +## Tool + +**Tool / Schema Name:** {tool_name} +**YAML file:** [`data_schemas/{yaml_file}`]({yaml_url}) + +--- + +## Background + +This repository collects **data schema information sheets** for power systems +planning tools used for cross-project comparison at the +**G-PST Power System Planning Interoperability Data Schema Workshop**. + +A placeholder YAML file for **{tool_name}** already exists at +`data_schemas/{yaml_file}`. Please fill it out and open a Pull Request. + +--- + +## Instructions + +Full step-by-step instructions are in +[`fill_out_schema.md`]({INSTRUCTIONS_URL}). + +### Quick Summary + +1. Open [`data_schemas/{yaml_file}`]({yaml_url}). +2. Replace every `<...>` placeholder with real information. +3. Use `~` (YAML null) for any fields that do not apply. +4. Validate locally (see **Validation** below). +5. Open a Pull Request targeting `main` and link this issue in the description. + +### File Location and Naming Convention + +- **File to edit:** `data_schemas/{yaml_file}` +- Keep the existing filename — do not rename it. +- The file lives in the `data_schemas/` directory at the repository root. + +### Required Sections + +All sections in the YAML must be addressed: + +| Section | Key Fields | +|---------|------------| +| `identity` | schema_name, organization, maintainers, repository, documentation, license, version, maturity | +| `summary` | description, modeling_domains_supported, what_does_it_NOT_cover, data_captured, conceptual_structure | +| `design` | key_decisions, schema_format, implementation_languages, interoperability, units_handling, validation_approach, governance | +| `usage` | tools_built_on_schema, largest_real_world_dataset, who_is_using_it, data_available | +| `challenges` | known_limitations, hardest_problems_encountered | +| `interoperability` | areas_of_overlap_with_other_schemas, what_would_convergence_require, biggest_thing_others_should_know | +| `card_metadata` | prepared_by, date | + +### Validation + +Run `yamllint` locally before pushing: + +```bash +pip install yamllint +yamllint -c .yamllint.yaml data_schemas/{yaml_file} +``` + +CI will also lint your file automatically when you open a PR. + +### Opening a Pull Request + +**External contributors (Fork & PR):** +1. Fork this repository. +2. Edit `data_schemas/{yaml_file}` in your fork. +3. Open a PR to `main` titled: `Fill out data schema sheet: {tool_name}`. +4. Paste this issue's URL in the PR description. + +**Contributors with write access (Branch & PR):** + +```bash +git checkout main && git pull +git checkout -b fill-schema/{branch_name} +# Edit data_schemas/{yaml_file} +git add data_schemas/{yaml_file} +git commit -m "Fill out data schema sheet: {tool_name}" +git push origin fill-schema/{branch_name} +``` + +Then open a PR on GitHub targeting `main` and link this issue. + +--- + +## Acceptance Criteria + +- [ ] All `<...>` placeholders in `data_schemas/{yaml_file}` replaced with real content (or `~` where not applicable) +- [ ] `identity` section complete: schema_name, organization, maintainers, repository, license, version, maturity +- [ ] `summary` section describes what the schema covers **and** what it does NOT cover +- [ ] `design` section covers key decisions, schema format, and implementation languages +- [ ] `usage` section includes real-world datasets and known users +- [ ] `challenges` section lists known limitations +- [ ] `interoperability` section addresses overlap with other schemas in this comparison +- [ ] `card_metadata` filled in (prepared_by, date) +- [ ] `yamllint` passes locally with no errors +- [ ] Pull Request opened targeting `main` with this issue linked in the PR description +- [ ] PR reviewed and merged by a maintainer + +--- + +_Questions? Comment on this issue._ +""" + + +def create_issue(tool_name, yaml_file): + title = f"Fill out data schema sheet: {tool_name}" + + if issue_exists(title): + print(f"Issue already exists for '{tool_name}', skipping.") + return + + body = build_body(tool_name, yaml_file) + + with tempfile.NamedTemporaryFile( + mode="w", suffix=".md", delete=False + ) as tmp: + tmp.write(body) + tmp_path = tmp.name + + try: + r = gh( + "issue", "create", + "--repo", REPO, + "--title", title, + "--body-file", tmp_path, + "--label", "fill-out-schema", + ) + if r.returncode == 0: + print(f"Created issue for '{tool_name}': {r.stdout.strip()}") + else: + print( + f"ERROR creating issue for '{tool_name}': {r.stderr}", + file=sys.stderr, + ) + sys.exit(1) + finally: + os.unlink(tmp_path) + + +def main(): + ensure_label() + for tool_name, yaml_file in TOOLS: + create_issue(tool_name, yaml_file) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/create-tool-issues.yml b/.github/workflows/create-tool-issues.yml new file mode 100644 index 0000000..c4a1892 --- /dev/null +++ b/.github/workflows/create-tool-issues.yml @@ -0,0 +1,28 @@ +name: Create tool data-schema issues + +# Runs automatically the first time these files land on main, and can be +# triggered manually at any time. The script is idempotent — re-running it +# will not create duplicate issues. +on: + push: + branches: + - main + paths: + - .github/workflows/create-tool-issues.yml + - .github/scripts/create_tool_issues.py + workflow_dispatch: + +jobs: + create-issues: + name: Create one issue per tool + runs-on: ubuntu-latest + permissions: + issues: write + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Create issues for each tool + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: python3 .github/scripts/create_tool_issues.py From 969c68d20431a0f59aba9ea65e9d32f459ebb01e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:57:02 +0000 Subject: [PATCH 3/3] Add .gitignore to exclude Python pycache; remove accidentally committed .pyc Co-authored-by: mooneyme <7425288+mooneyme@users.noreply.github.com> --- .../create_tool_issues.cpython-312.pyc | Bin 9154 -> 0 bytes .gitignore | 3 +++ 2 files changed, 3 insertions(+) delete mode 100644 .github/scripts/__pycache__/create_tool_issues.cpython-312.pyc create mode 100644 .gitignore diff --git a/.github/scripts/__pycache__/create_tool_issues.cpython-312.pyc b/.github/scripts/__pycache__/create_tool_issues.cpython-312.pyc deleted file mode 100644 index 9607f0fdcd0892228792ef6d60d3a1c63ebe0161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9154 zcmb7JU2GdycAgoM5;>xN{VzNAP2|L)B2so_JC5QywJph3ZOe+J{8)}N9C60dNaPGN zGqg;u+|_ndtPKQ+jAqv^7D0`6AGA#hI6#4C=2jK9|z2}~L?z!iF=iGDuxv^0e@cibTTgGp83c|nBNAO5~;o)@@ZV8$& zA!wo|WyJ}R|4S1R{|`-s_N@35iK-Pr-di#_4;25TI5}6B042#b$=;N#I*W1 zg$Y@U;@zOd@Q!OT-i=xV-c4E@?`FM4Yn<&A1Uo7Tdh>g}7@|;=ic+FU{S#3TPTIQa z>dZ2AcFJ&17bcnEI0c>Mb(^`Cm1Ty>+-aR@s;efQ%(R|Ulls++Zf6WfXSSZV9K*Hj zVoH|BrwxZW8QaLaV8RSd&*d#wH{CvFxC~u0vkse^*1^tZs>!UpZu+Cm8SXS6M!%ZZ zGp?@5uHj~Nre-0YR%H5B!*Lxpsb98ion=U7!<=F&Gxa%=J;m5)0nA)>#ZWn;jFro) zreT?~Kds{#7he#-vS%-6t+{Sy*(_^i)NHoMI&J-pf??|p@0(6fO{dfBY^di_YT9-4PG3)t$1#Q3^*oCHV9#XMn(WD`hS?KHF*G*z z(tt8PaBk%6@$rG4%SJYnG)H-J9rm3=itT#JnX?nJ_)!|hNiKgVJ zDpgc-Sr9j$(#=9N)mbaa>ayiQ!Fm-#XI97CAJ?9Cr2UA9a zqVpET;Z19$X&EVwj2*8XWlO%8chnyaQ)(M9GnQqq5ow$5)onoDaB}Ee&%p5b*!ko@ zsU>6NAcpH$ip~|0@%I(~tHZkx+S>SV%{?opg>T8e@&bc-AGU|FTCedm#9tB zr1wMbg}l}=ArUS;M>ejq8uKKja1(`@+PYh?z0C?G=CeAs(THtjbjL}RrK#!hgj8gc7K6v}7UmaWu|5e|o?a7a{f7<+c!|-x=_#tS7HCl|Lf@c2k zS9sNGk#JE9X<@gjO)a9;Y4uuEi@nDYSP-rW^TJFR9oIdYJo_v}OSrT?{Lvaf84bQx z|9>gGE4e;5VMB`ds9fhE#rMtYxO`uiOcLal>XXTgm9^}0-TwX09?Gbt#$-~{y>$T)l{yD8 zJj3uFauQZ@FsCgHh$a+g&a|$(#0i)RJg4cD9)Cr(O;Go-j8({LTtrV6Py9aiYuE&& z(uWgue38rH(SeckW!ba74A7w*$=inMmg^i>(`~yP!d`_XiMD4(Hmz+ruA2_oA)l|k z3snjHoN>HhEm3(T+Pt`Zd1v=ZwB?<>E78`)BP-Eu%R5e@_^_caR=04x(j-JKJ3r{W+rHd%^poCy?EARyU!ud6kPzKrH-d4dx)sbU=ru($P^50LE>&Z~7E<#?Mjkf*ii3Z>^g7VU!m4k-;C@(9TzyH{Wk;eS6}@#BK2}qJJL!Yb=*{yBzNIY~DvH3?~RQL5`}su@iu*ypmpsEwLa#z0frYmPs`0 z9zxv!@veom&`i~9tr8+K4c`>!!R@A~MNk4ql_WApX@cf)=&uZ43 z$tEpCqX0}EC-S9DmA2OeTRcYc0M_X#MR_xurVGcb zw8Of(YGL0nA$|_=vt@cNz`ZFl1+@cq(`KovYk-0N%<-59Y zm^jWLK}MgpvT!1-su(UqS68V6La#d|q#zep0n@MOc9Erzrc$Y6IBwLa zg`Y@p7@|{JbyZVxZ;HKyIj8?P%{sZ}Ow1s`RR_$1F7&KMCmk%AW_e*qKA*)A?qG_& ztY!_Ei@tg^a&#RgSUnW||xjAGB>L^&UHWb>Fykqvsw zH!sh_T)k(tgl{ykG!Ea;lv_-rlLto%&6p0oQ#clvxN^H0Esu+zZadvI;&($UnL-XM ze7dZWLBNLYFhx4)Qcs*CXb1D*9M7t0w3;v!RCHQ|$`#F`p&Z32xJe$>vil!qYLF(-e zChYBqZf4M7s5%*hoaR(Pozg*w$*+Num?{Rn$CCPt8nsvndkP zR3VoqNWlR+l7nJwN0}@bSyw?1Px0Ldov|MrSD~G%Apel{PQH%rk`^rF0+fP7S~5_< zr>|a74TQ$9K(5}*G_n-B2_}5DCOnbC!!N!(n8>thLmRFF3DGI%;CzYzo@NKT^9*9$ zREZIgOLY|MvO@F8s(FR*M6s|}Y+rV;=F2okrvWSwHXx>giDNF@s=L{wF~ui`t&JJ* z&RFJY-eDG!`ZIulN=|oGnjVdvho{2$nlf4BbEcW{?Xn6qvP|dQH02tw7%omwezwL> z1LX@2jfpLiPNyeTXIjo19yUW;Ea)Z&1(wV(?vIHXFL=84RtetvL*gULCx_S^c?&h` zSO5UiWksuCdw8H0To|%zcv&OlvP^2MdXrIq%M-9eGPV{M$@vdl#hRD^Z0ORpjY;sc z9o9Jr*TBcllb8My{t!O?QnqjRS)0I*w!bfvRt0ufJ2Fyan?`xcBp3ZrB`4D--k z>tkskr*}G})mU>L>|>?BPIE^vqQceH0QNqIy)=3@Kr8UA+31*dR~O)Ubw=DX@eCPL zGn9g0ohNMUnCaD7R#y!J@pi$$~@ebyrwldN$ZgH57j-TEpi9r8sWR9 zx{_OYFM#N}74G)9A!!2c$sBv)k&4*;1Scmm18f>o5Nyrhf9BZ>oQ0puD5o$%gC!%e z$|D3aH~>29M5vcWWB}s@kn$V^oIflYz>)CBt8pK`o8plkrIh*tbp3z1lmFd+1S3{G zNHCyhUXyUYgh1SZd+Q5PfI<}30;S>hc{A3N=TzWFy!L=^;3NXJerI?L81OoeK@k#m zcQ=n$)_M(KxbHOr#y;o=d<`>`EnqON>?8+yZhQcFhw~#WG%1d@oq$CxtOtB3@8&R% zxCY{bF6%v3I*22xA%nwwH22n?1G2wnek6ksY&C8V7-!Z3G#NU~2PWV71Ej86Nr0>f zN>v0aP8FcJ)tQLQY#Z?A4^bOybHoJyA8ZlcvnEOe{?2-GPz1LYbppPl(D@ZZp9395 zi#c*p8kk=pWMidWn%wCuP(TiL_wch|RX_lnlSQT13M=sU`$ti$Y9rn*$=s_T!4MrTX14 zFKO`~N3=$*sd@`gH(xhHnap*M*3552yJ~dM!gbIJ`pxTz@i{{oz;#cMe?`VDys9_z z4{La~Re5e-*BPJG&!uc6e`YqIcz@IC%w5VZdX$tXU-xL6S0!-w1dTH+D6Rg_M^-6| zLWgibaKt&}n=c?Si{$GES3?(sIk7`{G?yROaG4XlK8Y>ErCpDVrP_!1p?_V<2L6`q zE5-NW$Tn-_^9Y$!WpS<)!e!(j62D*xO~~TTCT%U5&?+48#A(L>8p8aFD2cO zOcIVJ34M8fn(kZdRwAUWQrhI*&%mj1QM|E3`w;QA4~&kUA6>mxt|73=B7RGoDACHZ zw>B*n$Lewvmy>yp^=-&d=-N2lciTwrKohtH;n8n7OmWh>e6me<9pwm)vqs*gB)Cns zP!1zO;g%%}DdvJnjt_}w%AeZ@>BTq+&9EGDb9s!O%PV=+o#x4BhwikT5dc2MSSR+cGk2Yj4*dO*zdQ0#*K*6i{Vm&XP28OL&q%1T>D#E#*z)%28>bgveCrHy?Oejn zFQPlY>mkWV^#A@gCB!_@so{Hv*5l*I?*2`okGoH__U{os*%ayDRsYGJZT*Ks88lWO zN`VuQ{@|)NfCo`ny+rC4F2NMx5`=5G{n!{_u?aWf21H1R!?;+Wy`~1*y3~dqnj5m+=+b= z?fP8^wcL%Aql!ZP6(!MHu2+zd$ta4w4?OICdeQADH&6Q*mH3@V50##w*BN?|9=NpL z2BA2H3(Q3#{<6jA} zuY}gG1oJ2qcLeA@?fhZo);g;GQHd5 s;=u>Iv!WP&@Op@eyB-XRA@S)-TnNXnmp%*a_}6gsPY2OE+|GsiA9<=$VgLXD diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3bbe7b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +*.pyo