diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6803821 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: + branches: [master, main] + pull_request: + +permissions: + contents: read + +jobs: + shell: + name: Lint & self-test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: ShellCheck (POSIX/bash scripts + git hooks) + run: | + shellcheck --version + shellcheck scripts/*.sh \ + git-templates/hooks/pre-commit \ + git-templates/hooks/post-merge \ + git-templates/hooks/post-commit + + - name: Install fish + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq fish + + - name: Fish syntax check + run: | + for f in scripts/*.fish; do + echo "fish -n $f" + fish -n "$f" + done + + - name: Self-test (bootstrap dry-run, sh + fish) + run: sh scripts/selftest.sh diff --git a/scripts/copilot-bootstrap.sh b/scripts/copilot-bootstrap.sh index 1c1d162..02313a6 100644 --- a/scripts/copilot-bootstrap.sh +++ b/scripts/copilot-bootstrap.sh @@ -134,11 +134,12 @@ _append_gitignore() { fi } -_append_gitignore "data/**/*" "# Persistente Service-Daten (nie committen!)" -_append_gitignore "!data/.gitkeep" "" +_append_gitignore "data/**/*" "# Persistente Service-Daten (nie committen!)" +_append_gitignore "!data/.gitkeep" "" +_append_gitignore "*:Zone.Identifier" "# Windows Mark-of-the-Web / NTFS ADS cruft" if [ "$GITIGNORE_UPDATED" -eq 1 ]; then - echo " ✓ .gitignore aktualisiert (data/ excluded)" + echo " ✓ .gitignore aktualisiert (data/ + Windows-ADS excluded)" else echo " ─ .gitignore already has required entries, skipping" fi diff --git a/scripts/selftest.sh b/scripts/selftest.sh new file mode 100755 index 0000000..19c6666 --- /dev/null +++ b/scripts/selftest.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env sh +# selftest.sh – Funktionspruefung fuer copilot-bootstrap.{sh,fish}. +# +# Baut ein isoliertes Fake-Template-Verzeichnis und ein Ziel-Repo in einem +# temporaeren HOME und prueft, dass Bootstrap die erwartete Struktur erzeugt. +# Veraendert weder das echte HOME noch ein echtes Repo. Lokal und in CI nutzbar: +# sh scripts/selftest.sh +set -eu + +REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)" +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +build_template() { + tpl="$1" + mkdir -p "$tpl/.github" "$tpl/.vscode" "$tpl/hooks" "$tpl/docs" "$tpl/history/summary" + echo "framework" > "$tpl/.github/copilot-instructions.md" + echo '{}' > "$tpl/.vscode/settings.json" + echo '{}' > "$tpl/.vscode/extensions.json" + printf '#!/bin/sh\nexit 0\n' > "$tpl/hooks/pre-commit" + printf '#!/bin/sh\nexit 0\n' > "$tpl/hooks/post-commit" + for d in USER ADMIN MAINTAINER; do + echo "$d" > "$tpl/docs/$d.md" + done + echo ctx > "$tpl/history/summary/PROJECT_CONTEXT.md" +} + +assert_file() { + if [ ! -f "$1" ]; then + echo "FAIL: erwartete Datei fehlt: $1" >&2 + exit 1 + fi +} + +run_case() { + label="$1" + runner="$2" # sh | fish + script="$3" + home="$WORK/home_$label" + target="$WORK/target_$label" + mkdir -p "$home/.git-templates" "$target" + build_template "$home/.git-templates" + git -C "$target" init -q + + HOME="$home" "$runner" "$REPO_DIR/scripts/$script" "$target" >/dev/null + + assert_file "$target/.github/copilot-instructions.md" + assert_file "$target/.vscode/settings.json" + assert_file "$target/.vscode/extensions.json" + assert_file "$target/docs/USER.md" + assert_file "$target/docs/ADMIN.md" + assert_file "$target/docs/MAINTAINER.md" + assert_file "$target/history/summary/PROJECT_CONTEXT.md" + assert_file "$target/.git/hooks/pre-commit" + assert_file "$target/.git/hooks/post-commit" + assert_file "$target/data/.gitkeep" + if ! grep -q ':Zone.Identifier' "$target/.gitignore"; then + echo "FAIL: $label – .gitignore enthaelt kein Zone.Identifier-Muster" >&2 + exit 1 + fi + echo "PASS: $label ($script)" +} + +run_case sh_bootstrap sh copilot-bootstrap.sh + +if command -v fish >/dev/null 2>&1; then + run_case fish_bootstrap fish copilot-bootstrap.fish +else + echo "SKIP: fish nicht installiert – fish-Bootstrap uebersprungen" +fi + +echo "selftest OK"