devzone 0.8.2 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,12 +11,21 @@ set -euo pipefail
11
11
 
12
12
  ETAT="${DEVZONE_ETAT:-$HOME/.config/devzone/modules}"
13
13
  ICI="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
14
+ VERSIONS="$ICI/../core/scripts/versions.sh"
15
+ # Dossier de devzone (/workspaces/devzone) ; DEVZONE_RACINE pour les tests
16
+ RACINE="${DEVZONE_RACINE:-$(dirname "$ICI")}"
14
17
  MODULES=(ia kubernetes)
15
18
 
16
19
  # Assistants IA, versions figées : mettre à jour ici, puis devzone appliquer
17
- # (ou Rebuild Container)
18
- IA_PAQUETS=(@anthropic-ai/claude-code@2.1.286 opencode-ai@1.18.34)
19
- IA_NOMS=(@anthropic-ai/claude-code opencode-ai)
20
+ # (ou Rebuild Container). Une ligne par paquet, séparées par une ligne qui ne
21
+ # change pas : deux montées simultanées (workflow versions) se fusionnent sans
22
+ # conflit, git n'en signalant qu'entre lignes voisines modifiées.
23
+ # Claude Code
24
+ IA_CLAUDE=@anthropic-ai/claude-code@2.1.310
25
+ # opencode
26
+ IA_OPENCODE=opencode-ai@1.19.4
27
+ IA_PAQUETS=("$IA_CLAUDE" "$IA_OPENCODE")
28
+ IA_NOMS=("${IA_CLAUDE%@*}" "${IA_OPENCODE%@*}")
20
29
 
21
30
  description() {
22
31
  case "$1" in
@@ -126,10 +135,50 @@ appliquer_kubernetes() {
126
135
  fi
127
136
  }
128
137
 
138
+ # Lignes « paquet figée installée » des outils en retard ; échoue si le script
139
+ # versions.sh est absent ou ne peut pas répondre (l'état omet alors la ligne)
140
+ outils_retard() {
141
+ [ -f "$VERSIONS" ] || return 1
142
+ bash "$VERSIONS" --installees 2>/dev/null
143
+ }
144
+
145
+ # Remet repowarden à la version figée s'il en diffère, comme post-create.sh
146
+ # (il installe les hooks git globaux)
147
+ appliquer_repowarden() {
148
+ local ligne figee installee
149
+ [ -f "$VERSIONS" ] || return 0
150
+ ligne="$(bash "$VERSIONS" --installees 2>/dev/null | awk '$1 == "repowarden"' || true)"
151
+ [ -n "$ligne" ] || return 0
152
+ read -r _ figee installee <<<"$ligne"
153
+ npm install -g "repowarden@$figee" >/dev/null
154
+ repowarden install --global --lang fr
155
+ echo "devzone : repowarden $installee → $figee"
156
+ }
157
+
158
+ # Chemins des worktrees du dépôt devzone et des dépôts du workspace absents
159
+ # ici : créés de l'autre côté (hôte), un git worktree prune les casserait.
160
+ # Lecture seule : rien n'est supprimé ni réparé.
161
+ worktrees_absents() {
162
+ local depot ligne chemin
163
+ {
164
+ [ -e "$RACINE/.git" ] && echo "$RACINE"
165
+ find "$RACINE/workspace" -mindepth 2 -maxdepth 3 -name .git -type d 2>/dev/null | sed 's|/\.git$||'
166
+ } | while IFS= read -r depot; do
167
+ { git -C "$depot" worktree list --porcelain 2>/dev/null || true; } | while IFS= read -r ligne; do
168
+ case "$ligne" in
169
+ "worktree "*)
170
+ chemin="${ligne#worktree }"
171
+ [ -d "$chemin" ] || echo "$chemin"
172
+ ;;
173
+ esac
174
+ done
175
+ done || true
176
+ }
177
+
129
178
  # État complet : ✔ prêt, ✖ nécessaire, ○ facultatif, ⚠ à corriger ; chaque
130
179
  # point à faire avec sa commande (affiché à chaque démarrage)
131
180
  etat() {
132
- local nom email statut m
181
+ local nom email statut m retards chemin
133
182
  echo "devzone : état (devzone pour le réafficher)"
134
183
  nom="$(git config --get user.name || true)"
135
184
  email="$(git config --get user.email || true)"
@@ -146,6 +195,20 @@ etat() {
146
195
  else
147
196
  echo " ✔ GitHub connecté"
148
197
  fi
198
+ if retards="$(outils_retard)"; then
199
+ if [ -z "$retards" ]; then
200
+ echo " ✔ outils versions figées"
201
+ else
202
+ while read -r paquet figee installee; do
203
+ [ -n "$paquet" ] || continue
204
+ echo " ⚠ outils $paquet $installee installé, $figee figé : devzone appliquer"
205
+ done <<<"$retards"
206
+ fi
207
+ fi
208
+ while IFS= read -r chemin; do
209
+ [ -n "$chemin" ] || continue
210
+ echo " ⚠ worktree $chemin absent ici (créé hors du conteneur ?) : le gérer de ce côté-là, jamais git worktree prune ici (docs/reference.md, Worktrees git)"
211
+ done < <(worktrees_absents)
149
212
  for m in "${MODULES[@]}"; do
150
213
  if [ "$(valeur "$m")" = on ]; then
151
214
  printf ' ✔ module %-10s actif : %s\n' "$m" "$(description "$m")"
@@ -170,6 +233,7 @@ case "${1:-}" in
170
233
  activer) changer on "${2:-}" ;;
171
234
  desactiver) changer off "${2:-}" ;;
172
235
  appliquer)
236
+ appliquer_repowarden
173
237
  [ "$(valeur ia)" = off ] || appliquer_ia on
174
238
  ;;
175
239
  actif)
@@ -46,7 +46,7 @@ git config --global url.https://github.com/.insteadOf git@github.com:
46
46
 
47
47
  # repowarden, version figée (il installe des hooks git globaux) ; mettre à jour
48
48
  # en changeant la version ici, puis Rebuild Container
49
- npm install -g repowarden@4.12.0
49
+ npm install -g repowarden@4.12.1
50
50
  repowarden install --global --lang fr
51
51
 
52
52
  # Modules facultatifs (assistants IA, Kubernetes) : commande devzone, état
package/README.md CHANGED
@@ -110,6 +110,7 @@ Ces modules sont désactivés par défaut, activables à la demande depuis le co
110
110
 
111
111
  ## Questions fréquentes
112
112
 
113
+ - **Docker absent ou arrêté** : `npx devzone`, `make up`, `make rebuild` et `make desinstaller` vérifient Docker avant tout et disent quoi faire : l'installer (Docker Desktop, ou Docker Engine sous Linux), démarrer Docker Desktop, ou, sous Linux, ajouter ton compte au groupe `docker` (`sudo usermod -aG docker $USER`, puis une nouvelle session). Avec `npx devzone mon-devzone`, le dossier est créé quand même : une fois Docker démarré, `cd mon-devzone && make shell`.
113
114
  - **Le premier lancement est long** : c'est normal (construction de l'image, téléchargement des images de base). Il prend 4 à 5 min mesurées, plus le téléchargement des images de base sur une machine neuve.
114
115
  - **`make` est absent sous Windows** : tu peux utiliser `npx @devcontainers/cli` (voir le tableau « Au quotidien ») ou Git Bash. Les scripts sont compatibles (fins de ligne LF).
115
116
  - **Pas de cluster Kubernetes visible** : devzone ne crée jamais de cluster. Avec le module `kubernetes` actif, il tente de se connecter à celui de l'hôte. Sinon, crée un cluster local avec `kind create cluster`.
package/core/devzone CHANGED
@@ -66,6 +66,13 @@ EOF
66
66
  echo "Pour le lancer : cd $cible && make up"
67
67
  return 0
68
68
  fi
69
+ # Docker d'abord : le dossier reste prêt, à lancer une fois Docker démarré
70
+ # shellcheck source=SCRIPTDIR/scripts/docker.sh
71
+ . "$PAQUET/core/scripts/docker.sh"
72
+ if ! docker_pret "cd $cible && make shell"; then
73
+ echo " Le dossier est prêt : rien à refaire, sauf ce lancement." >&2
74
+ exit 1
75
+ fi
69
76
  echo "▶ Lancement (quelques minutes la première fois)…"
70
77
  if command -v make >/dev/null 2>&1; then
71
78
  make -C "$cible" up
@@ -91,7 +98,7 @@ case "${1:-}" in
91
98
  echo "✖ À lancer dans un dossier devzone (desinstaller.sh introuvable ici)." >&2
92
99
  exit 1
93
100
  fi
94
- bash "$desinstalleur"
101
+ DEVZONE_COMMANDE="devzone desinstaller" bash "$desinstalleur"
95
102
  ;;
96
103
  -*)
97
104
  echo "✖ option inconnue : $1 (devzone --help)" >&2
@@ -24,6 +24,11 @@ case "$GARDER" in "" | connexions) ;; *)
24
24
  ;;
25
25
  esac
26
26
 
27
+ # Docker d'abord : sans lui, chaque appel docker afficherait son erreur brute
28
+ # shellcheck source=SCRIPTDIR/docker.sh
29
+ . "$(dirname "${BASH_SOURCE[0]}")/docker.sh"
30
+ docker_pret "${DEVZONE_COMMANDE:-make desinstaller}" || exit 1
31
+
27
32
  # --- Inventaire --------------------------------------------------------------
28
33
  echo "▶ Inventaire (dossier $ICI)"
29
34
  conteneurs=() images=() dind=()
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+ # Vérification de Docker sur l'hôte, avant tout appel (sourcé par lancer.sh,
3
+ # desinstaller.sh et la commande npm core/devzone) : sans elle, l'utilisateur
4
+ # ne voit que l'erreur brute du CLI devcontainers ou de docker.
5
+ # DEVZONE_DOCKER : nom de la commande docker (tests : simuler son absence).
6
+ # Compatible bash 3.2 (macOS).
7
+
8
+ # Code 0 si Docker répond ; sinon, sur stderr, la cause (absent, sans droits,
9
+ # arrêté) et quoi faire, puis relancer $1 ; code 1. Rien de brut à l'écran.
10
+ docker_pret() {
11
+ local commande="$1" docker="${DEVZONE_DOCKER:-docker}" erreur
12
+ if ! command -v "$docker" >/dev/null 2>&1; then
13
+ {
14
+ echo "✖ Docker introuvable : devzone en a besoin pour faire tourner son conteneur."
15
+ echo " Installe Docker Desktop (macOS, Windows, Linux) : https://docs.docker.com/desktop/"
16
+ echo " ou, sous Linux, Docker Engine : https://docs.docker.com/engine/install/"
17
+ echo " puis relance $commande"
18
+ } >&2
19
+ return 1
20
+ fi
21
+ erreur="$("$docker" info 2>&1 >/dev/null)" && return 0
22
+ case "$erreur" in
23
+ *"permission denied"* | *"Permission denied"*)
24
+ {
25
+ echo "✖ Docker refuse l'accès : ton compte n'est pas dans le groupe docker."
26
+ echo " sudo usermod -aG docker \$USER, puis ouvre une nouvelle session (ou newgrp docker),"
27
+ echo " puis relance $commande"
28
+ } >&2
29
+ ;;
30
+ *)
31
+ {
32
+ echo "✖ Docker est installé mais ne répond pas (arrêté ?)."
33
+ echo " Démarre Docker Desktop (sous Linux sans Docker Desktop : sudo systemctl start docker),"
34
+ echo " puis relance $commande"
35
+ } >&2
36
+ ;;
37
+ esac
38
+ return 1
39
+ }
@@ -80,6 +80,11 @@ arreter() {
80
80
  }
81
81
  trap 'arreter; echo; echo "interrompu — journal : .devzone.log"; exit 130' INT TERM
82
82
 
83
+ # Docker d'abord : sans lui, le CLI ne donnerait qu'une erreur JSON brute
84
+ # shellcheck source=SCRIPTDIR/docker.sh
85
+ . "$(dirname "${BASH_SOURCE[0]}")/docker.sh"
86
+ docker_pret "${DEVZONE_COMMANDE:-make $mode}" || exit 1
87
+
83
88
  : >"$LOG"
84
89
  debut="$(date +%s)"
85
90
  derniere_annonce="$debut"
@@ -1,9 +1,11 @@
1
1
  #!/usr/bin/env bash
2
2
  # Versions figées du conteneur : compare repowarden (post-create.sh) et les
3
- # assistants IA (IA_PAQUETS, devzone) à la dernière version npm, ou applique
3
+ # assistants IA (lignes IA_…, devzone) à la dernière version npm, ou applique
4
4
  # une montée.
5
5
  # bash core/scripts/versions.sh
6
6
  # une ligne « paquet ancienne nouvelle » par paquet en retard, rien sinon
7
+ # bash core/scripts/versions.sh --installees
8
+ # une ligne « paquet figée installée » par outil installé en retard
7
9
  # bash core/scripts/versions.sh --appliquer <paquet> <version>
8
10
  # remplace cette version figée dans son fichier, rien d'autre
9
11
  # bash core/scripts/versions.sh --ticket-existant <paquet> <auteur>
@@ -15,18 +17,17 @@ ICI="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
15
17
  POST_CREATE="$ICI/.devcontainer/post-create.sh"
16
18
  DEVZONE="$ICI/.devcontainer/devzone"
17
19
 
18
- # Liste « paquet version » des versions figées dans les deux fichiers
20
+ # Liste « paquet version » des versions figées dans les deux fichiers ; dans
21
+ # devzone, une ligne IA_<NOM>=<paquet>@<version> par assistant IA
19
22
  figees() {
20
23
  local ligne element
21
24
  ligne="$(sed -nE 's/.*npm install -g (repowarden)@([^[:space:]]+).*/\1 \2/p' "$POST_CREATE" | head -1)"
22
25
  [ -z "$ligne" ] || echo "$ligne"
23
- ligne="$(sed -nE 's/^IA_PAQUETS=\((.*)\)/\1/p' "$DEVZONE" | head -1)"
24
- [ -n "$ligne" ] || return 0
25
- for element in $ligne; do
26
+ while read -r element; do
26
27
  case "$element" in
27
- *@*) echo "${element%@*} ${element##*@}" ;;
28
+ ?*@*) echo "${element%@*} ${element##*@}" ;;
28
29
  esac
29
- done
30
+ done < <(sed -nE 's/^IA_[A-Z0-9_]+=([^[:space:]()"]+)$/\1/p' "$DEVZONE")
30
31
  }
31
32
 
32
33
  # Vrai si la version $1 est plus récente que $2 (composants numériques)
@@ -70,6 +71,28 @@ lister() {
70
71
  done < <(figees)
71
72
  }
72
73
 
74
+ # Versions installées globalement (paquet version), lues en une seule fois ;
75
+ # échoue si npm ou jq ne répond pas (l'état omet alors la ligne)
76
+ installees() {
77
+ local json
78
+ json="$(npm ls -g --depth=0 --json 2>/dev/null || true)"
79
+ [ -n "$json" ] || return 1
80
+ printf '%s\n' "$json" | jq -r '.dependencies // {} | to_entries[] | "\(.key) \(.value.version)"'
81
+ }
82
+
83
+ # Une ligne « paquet figée installée » par outil installé dont la version
84
+ # diffère de la version figée ; un outil non installé n'est pas listé
85
+ comparer_installees() {
86
+ local paquet figee installee liste
87
+ liste="$(installees)"
88
+ while read -r paquet figee; do
89
+ [ -n "$paquet" ] || continue
90
+ installee="$(printf '%s\n' "$liste" | awk -v p="$paquet" '$1 == p { print $2; exit }')"
91
+ [ -n "$installee" ] || continue
92
+ [ "$installee" = "$figee" ] || echo "$paquet $figee $installee"
93
+ done < <(figees)
94
+ }
95
+
73
96
  # Affiche « numéro<TAB>titre » du ticket ouvert par $2 dont le titre commence
74
97
  # par « $1 », rien sinon : un ticket au même titre ouvert par un autre est ignoré.
75
98
  ticket_existant() {
@@ -116,7 +139,7 @@ appliquer() {
116
139
  { echo "versions : paquet inconnu : $paquet" >&2; exit 1; }
117
140
  motif="$(echapper "$paquet")"
118
141
  tmp="$(mktemp)"
119
- sed -E "s|(${motif}@)[^ )]+|\1${version}|" "$fichier" >"$tmp"
142
+ sed -E "s|^(IA_[A-Z0-9_]+=${motif}@)[^[:space:]]+$|\1${version}|" "$fichier" >"$tmp"
120
143
  fi
121
144
  cat "$tmp" >"$fichier"
122
145
  rm -f "$tmp"
@@ -124,19 +147,20 @@ appliquer() {
124
147
 
125
148
  case "${1:-}" in
126
149
  "") lister ;;
150
+ --installees) comparer_installees ;;
127
151
  --appliquer)
128
152
  [ "$#" -eq 3 ] ||
129
- { echo "usage : bash core/scripts/versions.sh [--appliquer <paquet> <version> | --ticket-existant <paquet> <auteur>]" >&2; exit 2; }
153
+ { echo "usage : bash core/scripts/versions.sh [--installees | --appliquer <paquet> <version> | --ticket-existant <paquet> <auteur>]" >&2; exit 2; }
130
154
  appliquer "$2" "$3"
131
155
  ;;
132
156
  --ticket-existant)
133
157
  [ "$#" -eq 3 ] ||
134
- { echo "usage : bash core/scripts/versions.sh [--appliquer <paquet> <version> | --ticket-existant <paquet> <auteur>]" >&2; exit 2; }
158
+ { echo "usage : bash core/scripts/versions.sh [--installees | --appliquer <paquet> <version> | --ticket-existant <paquet> <auteur>]" >&2; exit 2; }
135
159
  ticket_existant "$2" "$3"
136
160
  ;;
137
- -h | --help) sed -n '2,11p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' ;;
161
+ -h | --help) sed -n '2,17p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' ;;
138
162
  *)
139
- echo "usage : bash core/scripts/versions.sh [--appliquer <paquet> <version> | --ticket-existant <paquet> <auteur>]" >&2
163
+ echo "usage : bash core/scripts/versions.sh [--installees | --appliquer <paquet> <version> | --ticket-existant <paquet> <auteur>]" >&2
140
164
  exit 2
141
165
  ;;
142
166
  esac
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devzone",
3
- "version": "0.8.2",
3
+ "version": "0.9.1",
4
4
  "description": "Zone de dev conteneurisée : Java, Node, Python, Docker, Kubernetes et outils repowarden, dans un devcontainer",
5
5
  "license": "GPL-3.0-only",
6
6
  "repository": {