redmine: Projekt-Wikis lesen und schreiben (0.3.0)
Uebernimmt redmine.py aus inmedias.it/dokumentierer@4159e0a, byte-identisch. Neuer Unterbefehl `wiki` nach dem Muster von `news`: ohne --title auflisten, mit --title anzeigen, zusaetzlich mit --text/--text-file schreiben. Dazu --comment, --parent und --version. Mitgezogen: SKILL.md (Befehlsreferenz und Frontmatter), plugin.json und marketplace.json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d00d195ac3
commit
e1ed8688f0
4 files changed
+107
-8
No files matched your search
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "redmine",
|
||||
"version": "0.2.0",
|
||||
"description": "Redmine via REST-API: Projekte/Tickets/Versionen/News auflisten, anlegen, aktualisieren, kommentieren (redmine.py).",
|
||||
"version": "0.3.0",
|
||||
"description": "Redmine via REST-API: Projekte/Tickets/Versionen/News/Wiki-Seiten auflisten, anlegen, aktualisieren, kommentieren (redmine.py).",
|
||||
"author": {
|
||||
"name": "inmedias.it"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
name: redmine
|
||||
description: Redmine-Projekte, -Tickets, -Versionen und -News lesen/anlegen/aktualisieren via REST-API. Use when the user mentions "Redmine", "Ticket", "Issue in Redmine", "Meilenstein/Milestone/Version", "Projektstand/News" or die Projekte "pg-wissen"/"devops".
|
||||
version: 0.2.0
|
||||
description: Redmine-Projekte, -Tickets, -Versionen, -News und Projekt-Wikis lesen/anlegen/aktualisieren via REST-API. Use when the user mentions "Redmine", "Ticket", "Issue in Redmine", "Meilenstein/Milestone/Version", "Projektstand/News", "Redmine-Wiki" or die Projekte "pg-wissen"/"devops".
|
||||
version: 0.3.0
|
||||
---
|
||||
|
||||
# Redmine (redmine.py)
|
||||
|
||||
Interagiert mit Redmine (https://redmine.inmedias.it) über die REST-API:
|
||||
Projekte, Tickets, Versionen und News auflisten, anzeigen, anlegen,
|
||||
aktualisieren und kommentieren - über die mitgelieferte, self-contained
|
||||
Projekte, Tickets, Versionen, News und Projekt-Wikis auflisten, anzeigen,
|
||||
anlegen, aktualisieren und kommentieren - über die mitgelieferte, self-contained
|
||||
`redmine.py`. Namen werden auf IDs aufgelöst (Projekt, Tracker, Status,
|
||||
Priorität, Version).
|
||||
|
||||
@@ -94,6 +94,34 @@ Zwei Eigenheiten der Redmine-API:
|
||||
|
||||
Format ist Markdown, wie bei Tickets.
|
||||
|
||||
### Projekt-Wiki
|
||||
|
||||
```bash
|
||||
./redmine.py wiki --project devops # Seiten auflisten
|
||||
./redmine.py wiki --project devops --title Wiki # Seite anzeigen
|
||||
./redmine.py wiki --project devops --title Wiki --version 2
|
||||
|
||||
./redmine.py wiki --project devops --title "Bericht" \
|
||||
--text-file bericht.md --comment "Erhebung vom 13.10."
|
||||
|
||||
./redmine.py wiki --project devops --title "Unterseite" \
|
||||
--text-file u.md --parent "Bericht" # Seite einhängen
|
||||
```
|
||||
|
||||
Drei Eigenheiten:
|
||||
|
||||
- **Anlegen und Ändern sind derselbe `PUT`.** Ein Tippfehler im Titel erzeugt
|
||||
sonst stillschweigend eine neue Seite. `redmine.py` sieht deshalb vorher nach
|
||||
und meldet „Angelegt" bzw. „Geändert".
|
||||
- **Leerzeichen werden zu Unterstriche.** Redmine normalisiert den Titel; beide
|
||||
Schreibweisen treffen dieselbe Seite.
|
||||
- **Die Startseite heißt `Wiki`.** Existiert sie nicht, ist das Projekt-Wiki
|
||||
leer und `/projects/<kennung>/wiki` läuft ins Leere. Eine Seite mit genau
|
||||
diesem Titel legt die Startseite an.
|
||||
|
||||
Löschen deckt `redmine.py` bewusst nicht ab - dafür
|
||||
`DELETE /projects/<kennung>/wiki/<Titel>.json`.
|
||||
|
||||
## Zugangsdaten
|
||||
|
||||
`redmine.py` bringt **keinen** Schlüssel mit. Jede/r hinterlegt einen eigenen
|
||||
|
||||
@@ -25,6 +25,9 @@ Beispiele:
|
||||
uv run redmine.py news --project devops
|
||||
uv run redmine.py news --project devops --title "Kurz" --description-file text.md
|
||||
uv run redmine.py news --id 1 --description-file korrigiert.md
|
||||
uv run redmine.py wiki --project devops
|
||||
uv run redmine.py wiki --project devops --title Wiki
|
||||
uv run redmine.py wiki --project devops --title Bericht --text-file bericht.md
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -32,6 +35,7 @@ import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
@@ -317,6 +321,64 @@ def cmd_news(s, a):
|
||||
print(f"Angelegt in Projekt {pid} -> {s.base}/projects/{pid}/news")
|
||||
|
||||
|
||||
def cmd_wiki(s, a):
|
||||
"""Wiki-Seiten eines Projekts auflisten, lesen oder schreiben.
|
||||
|
||||
Drei Betriebsarten, unterschieden an den Angaben:
|
||||
ohne --title Seiten des Projekts auflisten
|
||||
--title Seite anzeigen
|
||||
--title mit --text/--text-file Seite schreiben (PUT legt an oder ändert)
|
||||
|
||||
Redmine nimmt zum Schreiben denselben PUT für Anlegen und Ändern. Damit ein
|
||||
Tippfehler im Titel nicht unbemerkt eine neue Seite erzeugt, wird vorher
|
||||
nachgesehen, ob die Seite schon existiert, und das Ergebnis entsprechend
|
||||
gemeldet.
|
||||
|
||||
Die Startseite eines Projekt-Wikis heißt bei Redmine standardmäßig `Wiki`.
|
||||
"""
|
||||
pid = resolve_project(s, a.project)
|
||||
base = f"/projects/{pid}/wiki"
|
||||
|
||||
if not a.title:
|
||||
pages = api(s, "GET", f"{base}/index.json").get("wiki_pages", [])
|
||||
if a.json:
|
||||
return print(json.dumps(pages, ensure_ascii=False, indent=2))
|
||||
if not pages:
|
||||
return print("— keine Wiki-Seiten")
|
||||
for w in sorted(pages, key=lambda x: x["title"]):
|
||||
eltern = w.get("parent", {}).get("title")
|
||||
print(f" v{w.get('version', '?'):<3} {str(w.get('updated_on', ''))[:10]} "
|
||||
f"{w['title']}" + (f" (unter {eltern})" if eltern else ""))
|
||||
return
|
||||
|
||||
titel = quote(a.title, safe="")
|
||||
text = read_text(a.text, a.text_file)
|
||||
|
||||
if text is None:
|
||||
pfad = f"{base}/{titel}" + (f"/{a.version}" if a.version else "") + ".json"
|
||||
w = api(s, "GET", pfad).get("wiki_page", {})
|
||||
if a.json:
|
||||
return print(json.dumps(w, ensure_ascii=False, indent=2))
|
||||
autor = w.get("author", {}).get("name", "?")
|
||||
print(f"# {w.get('title')} (v{w.get('version')}, {autor}, "
|
||||
f"{str(w.get('updated_on', ''))[:16]})")
|
||||
print(f"# {s.base}/projects/{pid}/wiki/{titel}")
|
||||
print("---")
|
||||
return print(w.get("text", ""))
|
||||
|
||||
seite = {"text": text}
|
||||
if a.comment:
|
||||
seite["comments"] = a.comment
|
||||
if a.parent:
|
||||
seite["parent_title"] = a.parent
|
||||
# Vorher nachsehen: 404 heißt anlegen, alles andere ändern.
|
||||
r = s.request("GET", f"{s.base}{base}/{titel}.json")
|
||||
neu = r.status_code == 404
|
||||
api(s, "PUT", f"{base}/{titel}.json", data=json.dumps({"wiki_page": seite}))
|
||||
print(f"{'Angelegt' if neu else 'Geändert'}: {a.title} "
|
||||
f"-> {s.base}/projects/{pid}/wiki/{titel}")
|
||||
|
||||
|
||||
def cmd_meta(s, a):
|
||||
spec = {
|
||||
"trackers": ("/trackers.json", "trackers"),
|
||||
@@ -387,6 +449,15 @@ def main():
|
||||
pv.add_argument("--due", help="Fälligkeitsdatum (YYYY-MM-DD)")
|
||||
pv.add_argument("--description", help="Beschreibung")
|
||||
|
||||
pw = sub.add_parser("wiki", help="Wiki-Seiten auflisten, lesen oder schreiben")
|
||||
pw.add_argument("--project", required=True, help="Projekt (ID/Identifier/Name)")
|
||||
pw.add_argument("--title", help="Seitentitel - ohne Angabe werden die Seiten aufgelistet")
|
||||
pw.add_argument("--text", help="Seiteninhalt; gesetzt heißt: schreiben statt anzeigen")
|
||||
pw.add_argument("--text-file", help="Datei oder '-' für stdin")
|
||||
pw.add_argument("--comment", help="Änderungskommentar (erscheint in der Historie)")
|
||||
pw.add_argument("--parent", help="Titel der übergeordneten Seite")
|
||||
pw.add_argument("--version", help="alte Fassung anzeigen (Versionsnummer)")
|
||||
|
||||
pm = sub.add_parser("meta", help="Stammdaten auflisten")
|
||||
pm.add_argument("kind", choices=["trackers", "statuses", "priorities"])
|
||||
|
||||
@@ -395,7 +466,7 @@ def main():
|
||||
{
|
||||
"me": cmd_me, "projects": cmd_projects, "issues": cmd_issues, "show": cmd_show,
|
||||
"create": cmd_create, "update": cmd_update, "comment": cmd_comment,
|
||||
"news": cmd_news, "versions": cmd_versions, "meta": cmd_meta,
|
||||
"news": cmd_news, "versions": cmd_versions, "wiki": cmd_wiki, "meta": cmd_meta,
|
||||
}[a.cmd](s, a)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user