From afd5b38ca97ea40f96a94b851be293e7772b9155 Mon Sep 17 00:00:00 2001 From: Conrad Schulz Date: Wed, 10 Jun 2026 10:54:25 +0200 Subject: [PATCH] docs(wp12): document portability model (env/config, init-copilot, offline) README + USER + ADMIN + MAINTAINER aktualisiert: nicht-invasives Deploy (kein globales init.templateDir / git-init-Override), Opt-in-Alias 'git init-copilot', konfigurierbare Remote-Quelle (COPILOT_SETUP_REMOTE_SSH/_HTTP, Config-Datei ~/.config/copilot-setup/config) inkl. Offline-Modus und graceful skip, deploy --with-self-update-hook, neue VS-Code-Editionen in der Pfad-Erkennung. Tote IP 192.168.178.6 aus der Doku entfernt. MAINTAINER: CI/selftest dokumentiert, Skript-Paare synchron halten, neue Fallstricke ($USER/set -u, fish-Funktions-Scoping). --- README.md | 47 ++++++++++++++++++++++++++++++++++---------- docs/ADMIN.md | 49 ++++++++++++++++++++++++++++++++++++++++------ docs/MAINTAINER.md | 35 ++++++++++++++++++++++++--------- docs/USER.md | 16 +++++++++------ 4 files changed, 116 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 59f5b75..320fef0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Dieses Repo enthält alle Konfigurationsdateien die nötig sind um GitHub Copilo - **User-Level Settings** – Copilot-Flags und Senior-Dev-Grundverhalten (per Settings Sync auf alle Geräte) - **Prompt Files** – 10 wiederverwendbare Agent-Workflows (`/requirements`, `/new-feature`, `/architecture`, etc.) -- **Git-Templates** – automatisch in jedes neue Repo kopiert via `git init` (per Git-Alias) +- **Git-Templates** – per Opt-in in ein Repo kopiert (`git init-copilot` oder `copilot-bootstrap.sh`) - **Bootstrap-Skript** – bestehende und geclonte Repos in Sekunden ausstatten (POSIX sh, läuft überall) - **Update-Mechanismus** – Templates und Prompts in allen Repos mit einem Befehl aktuell halten: `git copilot-update` @@ -24,19 +24,39 @@ git copilot-update ``` Was das macht: -1. **Setup-Repo pullen** – `~/.copilot-setup/` (SSH, HTTP-Fallback zu `http://192.168.178.6:8083/cschulz/rd13_copilot_setup`) +1. **Setup-Quelle holen** – aus konfiguriertem Remote oder lokalem Klon (`COPILOT_SETUP_DIR`); offline nutzbar 2. **Globale Templates updaten** – `~/.git-templates/` + VS Code Prompt-Dateien 3. **Repo-lokale Hooks updaten** – `.git/hooks/pre-commit` 4. **`copilot-instructions.md`** – nur überschreiben wenn noch TODO-Platzhalter enthalten (Backup `.bak` wird angelegt) +Die Remote-Quelle ist **nicht** fest verdrahtet. Konfiguration (Vorrang: Env > Config-Datei): + +| Variable | Zweck | +|---|---| +| `COPILOT_SETUP_REMOTE_SSH` | SSH-URL des Setup-Repos | +| `COPILOT_SETUP_REMOTE_HTTP` | HTTP-URL (Fallback) | +| `COPILOT_SETUP_DIR` | Lokaler Klon/Arbeitskopie (Offline-Betrieb) | +| `COPILOT_SETUP_CONFIG` | Alternativer Pfad zur Config-Datei | + +Config-Datei (sh-Syntax) unter `~/.config/copilot-setup/config`: + +```sh +COPILOT_SETUP_REMOTE_SSH="ssh://git@host:22/you/rd13_copilot_setup.git" +COPILOT_SETUP_REMOTE_HTTP="https://host/you/rd13_copilot_setup.git" +``` + +Ist keine Quelle erreichbar, endet `git copilot-update` **ohne Fehler** (graceful skip) – +es gibt dann nichts zu aktualisieren. + > **Empfehlung:** In jedem Repo nach einem `git pull` auf dem Setup-Repo ausführen, > oder wenn ein neues Feature-Prompt oder eine Hook-Verbesserung verfügbar ist. -### Auto-Update für das Setup-Repo selbst +### Opt-in: Auto-Deploy für das Setup-Repo selbst -Nach `deploy.sh` ist im Setup-Repo selbst ein `post-merge` Hook aktiv: +Standardmäßig setzt `deploy.sh` **keine** automatischen Hooks. Wer will, dass nach jedem +`git pull` im Setup-Repo automatisch neu deployt wird: ```bash -git pull # im Setup-Repo → deploy.sh läuft automatisch → alle Templates sofort aktuell +bash scripts/deploy.sh --with-self-update-hook # installiert post-merge Auto-Deploy ``` ### Opt-in: Auto-Update in anderen Repos nach git pull @@ -62,7 +82,13 @@ bash scripts/deploy.sh # macOS (bash) fish scripts/deploy.fish # Linux mit fish ``` -Das Skript legt alles an den richtigen Orten ab. +Das Skript legt alles an den richtigen Orten ab. Es ist **nicht-invasiv**: es überschreibt +weder den globalen `git init` noch setzt es `init.templateDir` (fremde `git init`/`git clone` +bleiben unberührt). Für Auto-Bootstrap eines neuen Repos gibt es den Opt-in-Alias: + +```bash +git init-copilot mein-neues-repo # = git init + copilot-bootstrap +``` ### Bestehende oder geclonte Repos ausstatten @@ -99,7 +125,7 @@ rd13_copilot_setup/ │ ├── done-check.prompt.md /done-check – Definition of Done Checkliste │ ├── docker.prompt.md /docker – Docker/Compose-Aufgaben │ └── history.prompt.md /history – Agent-History loggen + Kontext aktualisieren -├── git-templates/ ← Wird via git config --global init.templateDir gesetzt +├── git-templates/ ← Quelle für ~/.git-templates (kein globales init.templateDir) │ ├── .github/ │ │ └── copilot-instructions.md ← Template mit TODO-Feldern + Konventionen │ ├── .vscode/ @@ -159,7 +185,7 @@ rd13_copilot_setup/ ## Was jedes Repo automatisch bekommt -Nach `git init` (via Alias) oder `copilot-bootstrap.sh`: +Nach `git init-copilot` oder `copilot-bootstrap.sh`: | Was | Wo | |---|---| @@ -194,9 +220,10 @@ Nach `git init` (via Alias) oder `copilot-bootstrap.sh`: ## Neues Repo einrichten – Checkliste -Nach `git init` (mit eingerichtetem Alias) passiert alles **automatisch**. +Mit dem Opt-in-Alias `git init-copilot ` passiert alles **automatisch** +(= `git init` + `copilot-bootstrap.sh`). Der Standard-`git init` bleibt unberührt. -Nach `git clone` oder ohne Alias: +Nach `git clone` oder für ein bestehendes Repo: ```bash # Option A: Bootstrap-Skript (empfohlen) diff --git a/docs/ADMIN.md b/docs/ADMIN.md index 440faf3..b7ad1c3 100644 --- a/docs/ADMIN.md +++ b/docs/ADMIN.md @@ -30,19 +30,27 @@ fish scripts/deploy.fish # fish (Linux) | Schritt | Was | Ziel | |---|---|---| -| 1 | VS Code User-dir ermitteln | plattformspezifisch (Server / lokal / macOS) | +| 1 | VS Code User-dir ermitteln | Server / Insiders / VSCodium / Cursor / Flatpak / macOS / Windows-WSL | | 2 | `settings.json` deployen | `~/.vscode-server/data/User/` (oder Äquivalent) | | 3 | Prompt Files deployen | `~/.vscode-server/data/User/prompts/` | | 4 | Git-Templates deployen | `~/.git-templates/` inkl. Hooks, Docs, History-Template | -| 5 | Bootstrap-Skript installieren | `~/.local/bin/copilot-bootstrap.sh` | -| 6 | Git-Alias setzen | `~/.gitconfig` → `git init` ruft Bootstrap automatisch auf | +| 5 | Bootstrap- + Update-Skripte installieren | `~/.local/bin/` | +| 6 | Git-Aliase setzen | `~/.gitconfig` → `git init-copilot` (opt-in) + `git copilot-update` | + +> **Nicht-invasiv:** `deploy.sh` setzt **kein** globales `init.templateDir` und überschreibt +> **nicht** den Standard-`git init`. Fremde `git init`/`git clone` bleiben unberührt. +> Auto-Bootstrap nur über den expliziten Alias `git init-copilot `. +> Optional installiert `bash scripts/deploy.sh --with-self-update-hook` den +> post-merge Auto-Deploy für das Setup-Repo selbst. --- ## Git-Templates verwalten Die Templates unter `git-templates/` werden beim Deployen nach `~/.git-templates/` kopiert. -Sie werden bei **jedem** `git init` automatisch in neue Repos kopiert (via `init.templateDir`). +Von dort nutzen sie `copilot-bootstrap.sh` und `git copilot-update`. Sie werden **nicht** +automatisch bei jedem `git init` kopiert (kein globales `init.templateDir` mehr) – das +geschieht nur per Opt-in: `git init-copilot ` oder `copilot-bootstrap.sh `. **Struktur nach Deploy:** ``` @@ -117,7 +125,7 @@ git copilot-update | Schritt | Was | Besonderheit | |---|---|---| -| 0 | Setup-Repo Cache aktualisieren (`~/.copilot-setup/`) | SSH, HTTP-Fallback | +| 0 | Setup-Quelle holen (`~/.copilot-setup/` oder `COPILOT_SETUP_DIR`) | Remote o. lokaler Klon; offline = graceful skip | | 1b | **Script selbst aktualisieren** (`~/.local/bin/copilot-update.sh`) | startet neue Version via `exec` | | 2 | `~/.git-templates/` aktualisieren | Hooks, Docs, History-Template | | 3 | VS Code Prompt-Dateien aktualisieren | `~/.vscode-server/.../prompts/` | @@ -131,6 +139,34 @@ git copilot-update --- +## Setup-Quelle konfigurieren (Remote / Offline) + +`git copilot-update` braucht eine Quelle. Reihenfolge: **Umgebungsvariable > Config-Datei**. +Ist nichts erreichbar, endet der Befehl **ohne Fehler** (graceful skip) – dann gibt es +schlicht nichts zu aktualisieren. + +| Variable | Zweck | +|---|---| +| `COPILOT_SETUP_REMOTE_SSH` | SSH-URL des Setup-Repos | +| `COPILOT_SETUP_REMOTE_HTTP` | HTTP-URL (Fallback) | +| `COPILOT_SETUP_DIR` | Lokaler Klon/Arbeitskopie – Offline-Betrieb ohne Netz | +| `COPILOT_SETUP_CONFIG` | Alternativer Pfad zur Config-Datei | + +Config-Datei (sh-Syntax) unter `~/.config/copilot-setup/config` +(bzw. `$XDG_CONFIG_HOME/copilot-setup/config`): + +```sh +COPILOT_SETUP_REMOTE_SSH="ssh://git@dein-host:22/you/rd13_copilot_setup.git" +COPILOT_SETUP_REMOTE_HTTP="https://dein-host/you/rd13_copilot_setup.git" +# Alternativ rein lokal/offline: +# COPILOT_SETUP_DIR="$HOME/dotfiles/copilot-setup" +``` + +> Die fish-Variante **sourcet** die Datei nicht, sondern parst `KEY="value"` selbst – +> dieselbe Datei funktioniert für beide Shells. + +--- + ## Bestehende Repos ausstatten ```bash @@ -172,7 +208,8 @@ fish_add_path ~/.local/bin | Problem | Ursache | Lösung | |---|---|---| | `copilot-bootstrap.sh: command not found` | `~/.local/bin` nicht im PATH | Siehe "PATH" oben | -| `git init` ruft Bootstrap nicht auf | Git-Alias nicht gesetzt | `deploy.sh` erneut ausführen | +| `git init-copilot` nicht gefunden | Git-Alias nicht gesetzt | `deploy.sh` erneut ausführen | +| `git copilot-update`: „Keine Setup-Quelle" | Remote nicht konfiguriert/erreichbar | `COPILOT_SETUP_REMOTE_*` oder `COPILOT_SETUP_DIR` setzen (s. Abschnitt oben) | | Hook schlägt fehl: Tests fehlen | Code geändert ohne Tests | `/write-tests` in Copilot Chat, oder `.copilot-no-tests` anlegen | | Hook schlägt fehl: Doku fehlt | Code geändert ohne Doku-Update | Docs aktualisieren, oder `.copilot-no-docs` anlegen | | Hook schlägt fehl: Session fehlt | `*_session.md` nicht gestaged | Copilot Chat → `/history`, dann `git add history/` | diff --git a/docs/MAINTAINER.md b/docs/MAINTAINER.md index 09d579c..8789a6e 100644 --- a/docs/MAINTAINER.md +++ b/docs/MAINTAINER.md @@ -59,30 +59,33 @@ rd13_copilot_setup/ │ ├── deploy.sh ← Bash-Deploy (macOS + Linux) │ ├── deploy.fish ← Fish-Deploy (Linux) │ ├── copilot-bootstrap.sh ← POSIX-sh Bootstrap für einzelne Repos +│ ├── copilot-bootstrap.fish ← Fish-Variante (voll funktionsgleich) │ ├── copilot-update.sh ← Aktualisiert Templates + Hooks in Repos -│ └── copilot-bootstrap.fish ← Fish-Variante (legacy, optional) +│ ├── copilot-update.fish ← Fish-Variante +│ └── selftest.sh ← CI/lokaler Bootstrap-Dry-Run (sh+fish) └── user-settings/ └── settings.json ← VS Code User-Level Settings (Layer 1) ``` --- -## Wie `git init` automatisiert wird +## Wie `git init-copilot` funktioniert (Opt-in) -Git hat keinen `post-init` Hook – `.github/` und `.vscode/` befinden sich im Working Tree, nicht in `.git/`, weshalb `init.templateDir` allein nicht ausreicht. +Git hat keinen `post-init` Hook – `.github/` und `.vscode/` befinden sich im Working Tree, nicht in `.git/`, weshalb `init.templateDir` allein nicht ausreicht. Statt den globalen `git init` zu überschreiben (invasiv – würde auch bei `git clone` fremder Repos greifen), gibt es einen **separaten Opt-in-Alias** `init-copilot`. -**Lösung: Git-Alias mit Rekursionsschutz** +**Git-Alias mit Rekursionsschutz** In `~/.gitconfig` (wird von deploy.sh/.fish gesetzt): ```ini [alias] - init = !f() { dir=.; for a in "$@"; do case "$a" in -*) ;; *) dir="$a" ;; esac; done; "$(git --exec-path)/git-init" "$@" && "$HOME/.local/bin/copilot-bootstrap.sh" "$dir"; }; f + init-copilot = !f() { dir=.; for a in "$@"; do case "$a" in -*) ;; *) dir="$a" ;; esac; done; "$(git --exec-path)/git-init" "$@" && "$HOME/.local/bin/copilot-bootstrap.sh" "$dir"; }; f ``` - `!` → externer Shell-Befehl (via `/bin/sh`), kein Git-Subcommand -- `$(git --exec-path)/git-init` → ruft das echte `git-init`-Binary direkt auf, umgeht den Alias → **kein Rekursions-Loop** -- Letzte Nicht-Flag-Argument wird als Zielverzeichnis erkannt (`dir=.` als Default) +- `$(git --exec-path)/git-init` → ruft das echte `git-init`-Binary direkt auf → **kein Rekursions-Loop** +- Letztes Nicht-Flag-Argument wird als Zielverzeichnis erkannt (`dir=.` als Default) - Nach erfolgreichem `git init` wird `copilot-bootstrap.sh` ausgeführt +- Der Standard-`git init` bleibt unverändert; frühere invasive `alias.init`/`init.templateDir` werden von deploy.sh gezielt entfernt --- @@ -108,9 +111,18 @@ Dateien unter `git-templates/` bearbeiten → `deploy.sh` ausführen → neue Re **Wichtig beim Ändern von `git-templates/hooks/pre-commit`:** Die Datei muss nach dem Deployen ausführbar sein (`chmod +x`). `deploy.sh` erledigt das automatisch. -## Deploy-Skripte ändern +## Shell-Skripte ändern -`deploy.sh` (bash) ist die Referenzimplementierung. `deploy.fish` sollte immer dieselben Schritte in Fish-Syntax abbilden. Nach Änderungen beide synchron halten. +Alle Skripte gibt es paarweise (POSIX/bash + fish) und müssen synchron bleiben: +`deploy`, `copilot-bootstrap`, `copilot-update`. Die `.sh`-Variante ist jeweils die +Referenz, die `.fish`-Variante bildet dieselben Schritte in Fish-Syntax ab. + +CI (`.github/workflows/ci.yml`) prüft bei jedem Push/PR: +- `shellcheck` für alle `*.sh` + git-Hooks +- `fish -n` für alle `*.fish` +- `scripts/selftest.sh` (Bootstrap-Dry-Run sh+fish gegen isoliertes Fake-HOME) + +Lokal vor dem Commit: `sh scripts/selftest.sh` ausführen. --- @@ -128,6 +140,9 @@ Dateien unter `git-templates/` bearbeiten → `deploy.sh` ausführen → neue Re | pre-commit Hook als Quality Gate (6 Checks) | Automatisches Netz: Tests, Doku, 3-Zielgruppen, PROJECT_CONTEXT, Requirements, Session-Datei; Opt-outs via `.copilot-no-tests` / `.copilot-no-docs` / `.copilot-no-requirements` | | Check 6: Session-Datei muss in jedem Commit gestaged sein | Jeder Commit ist mit Agent-Session verknüpft; kein Opt-out; erzwingt `/history` vor `git commit` | | Check 6 prüft Datum + `### Prompt`-Inhalt | Verhindert reine Nachtrag-Blöcke ohne echte Prompt-Einträge; Session-Datei muss heutiges Datum im Namen tragen | +| Kein globales `init.templateDir`, Opt-in `git init-copilot` | Standard-`git init`/`git clone` bleiben unberührt; Quality Gate landet nur in bewusst gewählten Repos | +| Remote-Quelle konfigurierbar (env/Config) + Offline-Modus | Keine hartkodierte Infrastruktur; `git copilot-update` läuft auch ohne Netz und endet graceful (exit 0) | +| `detect_vscode_user_dir` in jedem Skript dupliziert | Skripte laufen standalone aus `~/.local/bin` → keine gemeinsame Lib sourcebar; bewusst kopiert statt geteilt | ## Bekannte Fallstricke @@ -136,3 +151,5 @@ Dateien unter `git-templates/` bearbeiten → `deploy.sh` ausführen → neue Re | `Syntax error: word unexpected` in `copilot-update.sh` Zeile ~60 | Box-Drawing-Zeichen (`────`) direkt ans `fi` angehängt statt auf eigener Zeile | `fi` allein auf Zeile, Kommentar-Linie separat (`# ──`) | | Self-Update überschreibt manuell deployten Fix | Self-Update holt Version aus Remote-Cache, der noch kaputten Stand hat | Erst committen + pushen, dann manuell deployen: `cp scripts/copilot-update.sh ~/.local/bin/` | | Leerzeile vor `---` in `copilot-instructions.md` wird entfernt | `$(awk ...)` strippt trailing newlines; `printf '%s\n%s\n'` setzt Blöcke direkt zusammen | `printf '%s\n\n%s\n'` verwenden | +| `$USER` unbound unter `set -u` | `deploy.sh` nutzt `set -euo pipefail`; `$USER` fehlt in minimalen Envs (`env -i`, CI) | In `detect_vscode_user_dir` `${USER:-}` statt `$USER` | +| fish: Funktion ändert Skript-Variable nicht | fish-Funktionen sehen Caller-Locals nicht | `set -g` für Zähler/Flags die eine Funktion schreibt (z. B. `_append_gitignore`) | diff --git a/docs/USER.md b/docs/USER.md index b50141d..546424a 100644 --- a/docs/USER.md +++ b/docs/USER.md @@ -28,7 +28,7 @@ Das Skript erledigt **einmalig** alles automatisch: | Prompt Files | `~/.vscode-server/data/User/prompts/` | | Git-Templates | `~/.git-templates/` | | Bootstrap-Skript | `~/.local/bin/copilot-bootstrap.sh` | -| Git-Alias `init` | `~/.gitconfig` | +| Git-Alias `init-copilot` (opt-in) | `~/.gitconfig` | ### Schritt 3: VS Code Settings Sync aktivieren (optional) @@ -41,11 +41,13 @@ Das Skript erledigt **einmalig** alles automatisch: ### Neues Repo anlegen ```bash -git init mein-projekt +git init-copilot mein-projekt cd mein-projekt ``` -Der `git init`-Alias legt automatisch `.github/copilot-instructions.md` und `.vscode/` an. Danach: +Der Opt-in-Alias `git init-copilot` macht `git init` **und** Bootstrap in einem Schritt – +er legt `.github/copilot-instructions.md`, `.vscode/`, `docs/`, `history/` und den +pre-commit Hook an. (Der normale `git init` bleibt unverändert.) Danach: 1. Die `TODO`-Felder in `.github/copilot-instructions.md` ausfüllen 2. Committen: @@ -84,7 +86,7 @@ In GitHub Copilot Chat einfach `/` tippen: ## Was jedes neue Repo bekommt -Nach `git init` oder `copilot-bootstrap.sh` erhält jedes Repo automatisch: +Nach `git init-copilot` oder `copilot-bootstrap.sh` erhält jedes Repo automatisch: | Was | Wo | Zweck | |---|---|---| @@ -113,8 +115,10 @@ export PATH="$HOME/.local/bin:$PATH" # bash/zsh fish_add_path ~/.local/bin # fish ``` -**`git init` legt keine Copilot-Dateien an** -Das deploy-Skript wurde noch nicht auf diesem System ausgeführt. Schritt 1+2 wiederholen. +**`git init-copilot: command not found` oder keine Copilot-Dateien** +Entweder wurde das deploy-Skript noch nicht ausgeführt (Schritt 1+2 wiederholen), oder +du hast den normalen `git init` benutzt – nutze `git init-copilot` für Auto-Bootstrap, +oder rufe in einem bestehenden Repo `copilot-bootstrap.sh` auf. **Der pre-commit Hook blockiert meinen Commit** Der Hook hat Tests, Dokumentation, Session-Datei oder Requirements vermisst. Optionen: