102 lines
3.5 KiB
Python
102 lines
3.5 KiB
Python
"""EINMALIGES Bootstrap-Skript: erzeugt config/tools.yaml aus der Support-Seite.
|
|
|
|
Findet alle "Tool <Name>"-Unterseiten von Seite 428909879 und schreibt pro Tool
|
|
einen Katalogeintrag (Name OHNE "Tool "-Praefix). Tool-weiter Scope = intern
|
|
(restriktiv). Danach wird config/tools.yaml MANUELL gepflegt.
|
|
|
|
Aufruf:
|
|
CONFLUENCE_URL=... CONFLUENCE_TOKEN=... python scripts/bootstrap_tools.py
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
|
|
from atlassian import Confluence
|
|
|
|
SUPPORT_PAGE = "428909879"
|
|
BASE = "https://arija-confluence.jaas.service.deutschebahn.com/spaces/BES/pages"
|
|
|
|
HEADER = """\
|
|
# =============================================================================
|
|
# TOOL-KATALOG der Wissensdatenbank
|
|
# Initial generiert aus 'Zentraler 1st Level Support' (428909879).
|
|
# AB JETZT MANUELL PFLEGEN. Allgemeines Wissen steht in config/general.yaml.
|
|
#
|
|
# AUFBAU PRO TOOL:
|
|
# - id / name / domain
|
|
# scope: intern # tool-weit: intern | extern | allgemein | mixed
|
|
# owners: ["a@db.de"] # intern Verantwortliche
|
|
# contact: "team@db.de" # herausgebbarer Kontakt (Default einfachbahn@deutschebahn.com)
|
|
# sources: # 1..n Quellen, beliebig mischbar
|
|
# - url: "..."
|
|
# strategy: confluence_tree # confluence_page|confluence_tree|confluence_faq|
|
|
# # crawler|sitemap|gitlab_md|file|pdf
|
|
# # scope/Optionen pro Quelle optional ueberschreibbar
|
|
#
|
|
# SCOPE:
|
|
# intern -> alles intern (Default, restriktiv; z.B. CRM Salesforce)
|
|
# extern -> alles extern
|
|
# allgemein -> gilt fuer intern UND extern
|
|
# mixed -> Tool hat Quellen mit unterschiedlichem Scope (KEINE Trennung pro Seite;
|
|
# im Zweifel zwei Quellen). Source-scope kann "intern,extern" sein.
|
|
#
|
|
# confluence_tree-Tiefe: options.max_depth (-1=alle Unterseiten, 0=nur Seite)
|
|
# =============================================================================
|
|
|
|
tools:
|
|
"""
|
|
|
|
|
|
def slug(s: str) -> str:
|
|
s = re.sub(r"^tool\s+", "", s.strip(), flags=re.I)
|
|
s = re.sub(r"[^a-z0-9]+", "-", s.lower())
|
|
return s.strip("-")[:40]
|
|
|
|
|
|
def clean_name(s: str) -> str:
|
|
return re.sub(r"^tool\s+", "", s.strip(), flags=re.I).strip()
|
|
|
|
|
|
def walk(client, pid, out=None):
|
|
out = out if out is not None else []
|
|
for ch in client.get_child_pages(pid) or []:
|
|
out.append((ch.get("id"), ch.get("title")))
|
|
walk(client, ch.get("id"), out)
|
|
return out
|
|
|
|
|
|
def main() -> None:
|
|
client = Confluence(
|
|
url=os.environ["CONFLUENCE_URL"], token=os.environ["CONFLUENCE_TOKEN"], cloud=False
|
|
)
|
|
tools = [(pid, t.strip()) for pid, t in walk(client, SUPPORT_PAGE)
|
|
if t.strip().lower().startswith("tool")]
|
|
|
|
lines = [HEADER.rstrip("\n")]
|
|
seen = set()
|
|
for pid, title in tools:
|
|
sid = slug(title)
|
|
if sid in seen:
|
|
sid = f"{sid}-{pid}"
|
|
seen.add(sid)
|
|
url = f"{BASE}/{pid}/" + re.sub(r"[^A-Za-z0-9]+", "+", title).strip("+")
|
|
lines += [
|
|
f" - id: {sid}",
|
|
f' name: "{clean_name(title)}"',
|
|
f" domain: {sid}",
|
|
" scope: intern",
|
|
" sources:",
|
|
f' - url: "{url}"',
|
|
" strategy: confluence_tree",
|
|
f' tags: ["{sid}"]',
|
|
]
|
|
|
|
with open("config/tools.yaml", "w", encoding="utf-8") as f:
|
|
f.write("\n".join(lines) + "\n")
|
|
print(f"config/tools.yaml geschrieben: {len(tools)} Tools (alle scope: intern)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|