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).
This commit is contained in:
Conrad Schulz 2026-06-10 10:54:25 +02:00
parent deca872ab2
commit afd5b38ca9
4 changed files with 116 additions and 31 deletions

View file

@ -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 <pfad>` 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)

View file

@ -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 <pfad>`.
> 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 <pfad>` oder `copilot-bootstrap.sh <pfad>`.
**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/` |

View file

@ -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`) |

View file

@ -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: