Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

hawser — Extensions, plugins, authentification & CI/CD

Comment hawser reste ouvert à ses frontières : il orchestre git, les forges et les outils de build — il ne les réimplémente jamais. Tout ce qui est spécifique à une tâche (systèmes de build, forges, étapes personnalisées) s’enfiche depuis l’extérieur via des interfaces stables et sans surprise. Se combine avec ARCHITECTURE.md (internes) et COMPLIANCE.md (preuves).

Règles de conception, dans l’ordre :

  1. Natif git. Si c’est déjà un fichier texte que git comprend (lock, alternates, gitdir), utilisez-le. Jamais de base de données cachée.
  2. Orchestrer, ne pas réimplémenter. haw décide quoi et quand ; les outils de l’utilisateur font le comment. haw ne connaît rien de CMake, Bazel, Yocto, Jenkins — il délègue au shell.
  3. Tuyaux Unix. Vue humaine dans le TUI ; vue machine via --format json sur stdout. Tout ce que haw affiche, un script peut le consommer.
  4. Échec ouvert. Une forge inconnue, un jeton manquant, un plugin absent dégrade une seule fonctionnalité — cela ne bloque jamais sync/tree/status.

1. Mécanismes d’extension

Quatre couches, de la moins coûteuse d’abord. Choisissez la plus basse qui résout le problème.

1.1 run — exécuter n’importe quelle commande sur tous les dépôts

La trappe de sortie universelle. Exécution parallèle de commandes sur chaque dépôt (filtrable par groupe).

haw run 'git fetch --tags'
haw run --group firmware 'cmake --build build'

Aucun plugin nécessaire pour les 80 % des cas : « faire X dans chaque dépôt ».

1.2 Hooks — exécuter des scripts à des points du cycle de vie

Hooks de style git déclenchés autour des opérations haw. Les scripts se trouvent dans .haw/hooks/ (ou sont déclarés dans le manifeste) et reçoivent le contexte via l’environnement + JSON sur stdin.

HookSe déclenche
pre-sync / post-syncavant/après un haw sync
pre-lock / post-lockautour de la (re)génération du lockfile
post-switchaprès haw switch <stack>
post-change-startaprès la création d’une branche de changeset

Exemple — installer un hook git qui rejette un commit lorsque haw.lock est périmé (la garantie d’intégrité « à la git ») :

haw hooks install    # écrit un pre-commit qui exécute `haw verify --lock`

1.3 Commandes par dépôt dans le manifeste

Déclarez comment un dépôt est construit/testé afin que haw puisse le piloter sans coder en dur le moindre outil de build.

[repo.app-mqtt]
remote = "github"
repo   = "app-mqtt.git"
rev    = "release/2.x"
build  = "cmake --build build --preset release"   # haw délègue simplement au shell
test   = "ctest --test-dir build"

haw reste agnostique quant au système de build : CMake, Bazel, Meson, Cargo, Make — tout n’est que des chaînes de caractères.

1.4 Plugins de sous-commande — haw-<name> sur le PATH

Le modèle git / cargo / kubectl. Un haw foo … qui n’est pas intégré exécute haw-foo depuis le PATH, en transmettant les arguments et le contexte de l’espace de travail (via l’environnement + HAW_JSON sur stdin). La communauté livre haw-jira, haw-bazel, haw-sbom-scan sans toucher au cœur.

  • Découverte : tout exécutable nommé haw-* sur le PATH.
  • Contrat : haw transmet la racine de l’espace de travail, le stack courant et les dépôts résolus au format JSON sur stdin ; le plugin affiche les résultats au format JSON sur stdout ; haw les rend ou les redirige.
  • Isolation : les plugins sont des processus distincts — un plugin défectueux ne peut pas faire planter haw.

Le cœur reste petit. haw maintient le moteur de composition + orchestration ; les intégrations (chaque particularité de forge, chaque outil de build, chaque tracker) vivent dans les plugins et les hooks.

1.5 Interface machine — --format json

Chaque commande de lecture (status, tree, change status, verify, evidence) propose --format json avec un schéma stable et versionné, plus des codes de sortie stables. C’est ce que consomment la CI, les tableaux de bord et les plugins. Le TUI est pour les humains ; le JSON est pour les machines.


2. Authentification (fonctionne sur n’importe quel dépôt)

Le déclic d’adoption : l’authentification de transport est gratuite ; l’authentification de forge est sur adhésion. haw n’invente jamais son propre magasin d’identifiants.

2.1 Transport (clone / fetch / push) — zéro configuration

haw délègue au git de l’utilisateur, il hérite donc automatiquement de l’authentification git existante :

  • Clés SSH via ssh-agent (le défaut en entreprise/embarqué).
  • HTTPS via les assistants git credential (Git Credential Manager, osxkeychain, cache).

Fonctionne avec n’importe quel hôte — GitHub, GitLab, Gitea, Bitbucket, auto-hébergé, SSH nu — sans intégration. Si git clone fonctionne, haw sync fonctionne. C’est exactement ainsi que repo et west s’authentifient : ils ne le font pas.

2.2 API de forge (ouvrir/lire PR-MR, statut CI) — jeton, uniquement à l’usage

Seules les fonctionnalités PR/MR nécessitent des identifiants d’API, résolus dans cet ordre :

  1. Environnement : GITHUB_TOKEN / GH_TOKEN, GITLAB_TOKEN, HAW_FORGE_TOKEN.
  2. Réutiliser le jeton stocké d’un CLI existant : gh auth token, glab auth.
  3. git credential pour les jetons HTTPS.
  4. Flux d’appareil OAuth (haw auth login) — affiche un code à saisir dans un navigateur, sans redirection localhost, fonctionne sans interface/via SSH ; le jeton est stocké dans le trousseau de l’OS. C’est le modèle gh / docker login / aws sso.
  • Auto-hébergé : URL de base d’API configurable par forge (GitHub Enterprise, GitLab self-managed). Obligatoire pour le marché cible.
  • Isolé (air-gapped) : jeton via env/fichier uniquement ; pas de flux navigateur, pas de sortie (voir COMPLIANCE §6).
  • Ne jamais persister un jeton dans haw.toml, haw.lock, les journaux ou l’état de l’espace de travail (COMPLIANCE §5.6). Masquez les chaînes ayant l’apparence d’un identifiant.

2.3 Détection de forge

haw met en correspondance l’URL distante de chaque dépôt → forge (GitHub/GitLab/…) via le trait Forge. Hôte inconnu → le transport fonctionne toujours ; seules les fonctionnalités PR/MR se désactivent pour ce dépôt. Échec ouvert.


3. Intégration CI/CD

haw est conçu pour être piloté par des pipelines, pas seulement par des humains.

3.1 Checkout reproductible

haw sync --locked      # matérialise l'arbre exact de haw.lock ; échoue si le lock est manquant/périmé
haw verify             # vérifie que arbre sur disque == lock (porte de dérive) ; non nul en cas de dérive

--locked est le contrat CI : pas de résolution de rev, pas de non-déterminisme réseau — le lock committé fait loi. Déterministe sur Linux/macOS/Windows (COMPLIANCE §8).

3.2 Portes via JSON + codes de sortie

haw status --format json | jq -e '.repos[] | select(.dirty or .drift)' && exit 1 || true

Codes de sortie stables : 0 ok, valeurs non nulles distinctes pour dérive / échec de vérification / échec de signature.

3.3 Jetons en CI

Injectez les jetons de forge comme secrets CI (GITHUB_TOKEN dans Actions, variables masquées dans GitLab). Pas de connexion interactive dans les pipelines. Le transport utilise la clé SSH du runner ou un jeton de déploiement.

3.4 Cache de partage d’objets (CI rapide)

haw sync --locked --shared   # git alternates contre un cache miroir préchauffé ; fichier texte, pas de liens symboliques

Mettez le miroir en cache entre les exécutions pour éviter de re-cloner de grands arbres de dépôts.

3.5 Preuves dans le pipeline de version

haw evidence --out haw-evidence.tar.zst   # baseline + SBOM + provenance + enregistrement de config de l'outil

Attachez à la version pour le paquet de données de certification (COMPLIANCE §3, §4).

3.6 GitHub Actions (ébauche)

- uses: actions/checkout@v4
- run: cargo install hawser
- run: haw sync --locked --shared
  env: { GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} }
- run: haw verify
- run: haw run --group firmware 'cmake --build build --preset release'

3.7 GitLab CI (ébauche)

build:
  script:
    - haw sync --locked
    - haw verify
    - haw run 'make'
  variables: { GITLAB_TOKEN: $CI_JOB_TOKEN }

4. Où cela s’inscrit dans le plan

Ajouts au plan par phases dans ARCHITECTURE.md §6 ; chaque élément est cadré pour garder le cœur petit et pousser les intégrations vers les frontières. État au 2026-07-15 : tout ce qui suit est livré, à l’exception de la connexion par flux d’appareil OAuth (reportée — ARCHITECTURE DR-14) et de la charge utile SBOM/provenance complète de haw evidence (bundle actuel : manifeste, lock, journal d’audit, JSON de statut, enregistrement de l’outil).

CapacitéCouchePhase
run en parallèle sur les dépôts (alias forall)cœur3
--format json + schémas/codes de sortie stablescœur1→3
Transport de forge (natif git, zéro configuration)haw-git1
Jetons d’API de forge (env / réutilisation gh-glab)haw-forge1 (GH), 3 (GL)
Connexion par flux d’appareil OAuth + trousseauhaw-forgereporté (DR-14)
URL de base de forge auto-hébergéehaw-forge3
Hooks de cycle de vie (pre/post-sync, …)cœur + haw hooks4
haw hooks install (pre-commit lock périmé)cœur4
Commandes build/test par dépôt dans le manifestemodèle de manifeste4
Plugins de sous-commande (haw-<name> sur le PATH)dispatch hawser5
Contrat JSON stdin/stdout des pluginscœur5
Porte de dérive haw verify (CI)cœur1→2
Bundle haw evidencecœur3
Cache de partage d’objets --sharedhaw-git2

Contrainte directrice : le cœur ne développe jamais de dépendance forte envers un outil de build, un tracker ou un système de CI spécifique. Ceux-ci arrivent sous forme de hooks, de commandes par dépôt ou de plugins haw-*.