ci: Add docs assignment-table auto-updater
Update docs assignments / update (push) Successful in 57s
Update docs assignments / update (push) Successful in 57s
Regenerate the marked network-assignment tables in docs/ from nixos.allAssignments (nix run .#update-docs-assignments, registered in pkgs/default.nix), preserving hand-written Notes cells. The workflow runs on pushes to the docs branch and commits any table updates back; flip its trigger to master when the docs branch merges.
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
name: Update docs assignments
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [docs-kimi-new]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
if: "!contains(github.event.head_commit.message, 'docs: update assignment tables')"
|
||||||
|
runs-on: ubuntu-26.04
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: cachix/install-nix-action@v31
|
||||||
|
with:
|
||||||
|
github_access_token: ${{ secrets.GH_PULL_TOKEN }}
|
||||||
|
extra_nix_config: |
|
||||||
|
extra-substituters = https://nix-cache.nul.ie
|
||||||
|
extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
|
||||||
|
|
||||||
|
- name: Update assignment tables
|
||||||
|
run: nix run .#update-docs-assignments
|
||||||
|
|
||||||
|
- name: Commit and push if changed
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
REPO_URL: ${{ gitea.repositoryUrl }}
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git remote set-url origin "${REPO_URL/https:\/\//https:\/\/oauth2:${GITEA_TOKEN}@}"
|
||||||
|
git add docs/
|
||||||
|
if ! git diff --cached --quiet; then
|
||||||
|
git commit -m "docs: update assignment tables"
|
||||||
|
git push
|
||||||
|
fi
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Update assignment tables in docs/ from nixos.allAssignments."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
DOCS_DIR = Path("docs")
|
||||||
|
HEADER = "| Name | Assignment | IPv4 | IPv6 | Domain | Notes |"
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_ip(ip: dict) -> str:
|
||||||
|
addr = ip.get("address")
|
||||||
|
if addr is None:
|
||||||
|
return "—"
|
||||||
|
mask = ip.get("mask")
|
||||||
|
gateway = ip.get("gateway")
|
||||||
|
parts = [f"{addr}/{mask}"]
|
||||||
|
if gateway is not None:
|
||||||
|
parts.append(f"gw {gateway}")
|
||||||
|
return f"`{' '.join(parts)}`"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_notes(lines: list[str]) -> dict[str, str]:
|
||||||
|
"""Extract existing Notes indexed by Assignment from a marked table."""
|
||||||
|
notes: dict[str, str] = {}
|
||||||
|
for line in lines:
|
||||||
|
stripped = line.strip()
|
||||||
|
if not stripped.startswith("|"):
|
||||||
|
continue
|
||||||
|
cells = [c.strip() for c in stripped.split("|")]
|
||||||
|
# Splitting "| a | b |" produces ['', 'a', 'b', '']
|
||||||
|
if len(cells) < 8:
|
||||||
|
continue
|
||||||
|
key = cells[2]
|
||||||
|
if key == "Assignment":
|
||||||
|
continue
|
||||||
|
notes[key] = cells[6]
|
||||||
|
return notes
|
||||||
|
|
||||||
|
|
||||||
|
def render_table(assignments: dict, notes: dict[str, str]) -> list[str]:
|
||||||
|
lines = [
|
||||||
|
HEADER,
|
||||||
|
"|---|---|---|---|---|---|",
|
||||||
|
]
|
||||||
|
for key, a in assignments.items():
|
||||||
|
name = a.get("name", key)
|
||||||
|
alt = ", ".join(a.get("altNames", []))
|
||||||
|
if alt:
|
||||||
|
name = f"{name} ({alt})"
|
||||||
|
lines.append(
|
||||||
|
"| "
|
||||||
|
+ " | ".join(
|
||||||
|
[
|
||||||
|
name,
|
||||||
|
key,
|
||||||
|
fmt_ip(a.get("ipv4", {})),
|
||||||
|
fmt_ip(a.get("ipv6", {})),
|
||||||
|
a.get("domain") or "—",
|
||||||
|
notes.get(key, ""),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ " |"
|
||||||
|
)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def process_file(path: Path, all_assignments: dict) -> bool:
|
||||||
|
box_name = path.stem
|
||||||
|
if box_name not in all_assignments:
|
||||||
|
return False
|
||||||
|
|
||||||
|
text = path.read_text()
|
||||||
|
lines = text.splitlines()
|
||||||
|
|
||||||
|
marker_re = re.compile(r"^<!--\s*assignments:\s*(\S+)\s*-->$")
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
m = marker_re.match(line.strip())
|
||||||
|
if m and m.group(1) == box_name:
|
||||||
|
end_idx = None
|
||||||
|
for j in range(i + 1, len(lines)):
|
||||||
|
if lines[j].strip() == "<!-- assignments-end -->":
|
||||||
|
end_idx = j
|
||||||
|
break
|
||||||
|
if end_idx is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
old_inner = lines[i + 1 : end_idx]
|
||||||
|
notes = parse_notes(old_inner)
|
||||||
|
new_table = render_table(all_assignments[box_name], notes)
|
||||||
|
new_lines = (
|
||||||
|
lines[: i + 1]
|
||||||
|
+ ["<!-- assignments-start -->"]
|
||||||
|
+ new_table
|
||||||
|
+ ["<!-- assignments-end -->"]
|
||||||
|
+ lines[end_idx + 1 :]
|
||||||
|
)
|
||||||
|
if new_lines != lines:
|
||||||
|
path.write_text("\n".join(new_lines) + "\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
result = subprocess.run(
|
||||||
|
["nix", "eval", ".#nixfiles.config.nixos.allAssignments", "--json"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
all_assignments = json.loads(result.stdout)
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
for path in sorted(DOCS_DIR.rglob("*.md")):
|
||||||
|
if process_file(path, all_assignments):
|
||||||
|
print(f"updated {path}")
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
return 1 if changed else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -11,4 +11,8 @@ in
|
|||||||
chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
|
chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
|
||||||
windowtolayer = callPackage ./windowtolayer.nix { };
|
windowtolayer = callPackage ./windowtolayer.nix { };
|
||||||
swaylock-plugin = callPackage ./swaylock-plugin.nix { };
|
swaylock-plugin = callPackage ./swaylock-plugin.nix { };
|
||||||
|
|
||||||
|
update-docs-assignments = pkgs.writeShellScriptBin "update-docs-assignments" ''
|
||||||
|
exec ${pkgs.python3}/bin/python3 ${../ci/update-docs-assignments.py} "$@"
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user