devzone 0.9.0 → 0.9.2
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.
- package/.devcontainer/devzone +84 -6
- package/.devcontainer/post-create.sh +6 -3
- package/README.md +1 -0
- package/core/devzone +8 -1
- package/core/scripts/desinstaller.sh +5 -0
- package/core/scripts/docker.sh +39 -0
- package/core/scripts/lancer.sh +5 -0
- package/core/scripts/versions.sh +7 -8
- package/package.json +1 -1
package/.devcontainer/devzone
CHANGED
|
@@ -12,12 +12,20 @@ set -euo pipefail
|
|
|
12
12
|
ETAT="${DEVZONE_ETAT:-$HOME/.config/devzone/modules}"
|
|
13
13
|
ICI="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
|
14
14
|
VERSIONS="$ICI/../core/scripts/versions.sh"
|
|
15
|
+
# Dossier de devzone (/workspaces/devzone) ; DEVZONE_RACINE pour les tests
|
|
16
|
+
RACINE="${DEVZONE_RACINE:-$(dirname "$ICI")}"
|
|
15
17
|
MODULES=(ia kubernetes)
|
|
16
18
|
|
|
17
19
|
# Assistants IA, versions figées : mettre à jour ici, puis devzone appliquer
|
|
18
|
-
# (ou Rebuild Container)
|
|
19
|
-
|
|
20
|
-
|
|
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%@*}")
|
|
21
29
|
|
|
22
30
|
description() {
|
|
23
31
|
case "$1" in
|
|
@@ -98,9 +106,51 @@ config_opencode() {
|
|
|
98
106
|
fi
|
|
99
107
|
}
|
|
100
108
|
|
|
109
|
+
# Lance une commande longue en écrivant « toujours en cours » toutes les
|
|
110
|
+
# DEVZONE_PROGRESSION s sur stderr : une installation muette semble bloquée (#195)
|
|
111
|
+
avec_progression() {
|
|
112
|
+
local pas="${DEVZONE_PROGRESSION:-30}" ecoule=0 pid code=0
|
|
113
|
+
"$@" &
|
|
114
|
+
pid=$!
|
|
115
|
+
while kill -0 "$pid" 2>/dev/null; do
|
|
116
|
+
sleep 1
|
|
117
|
+
ecoule=$((ecoule + 1))
|
|
118
|
+
if [ $((ecoule % pas)) -eq 0 ] && kill -0 "$pid" 2>/dev/null; then
|
|
119
|
+
echo "devzone : … toujours en cours (${ecoule} s)" >&2
|
|
120
|
+
fi
|
|
121
|
+
done
|
|
122
|
+
wait "$pid" || code=$?
|
|
123
|
+
return "$code"
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Fichier qui marque un module actif en échec (contenu : où regarder) ; à côté
|
|
127
|
+
# de l'état, dans son volume : l'état l'affiche à chaque démarrage
|
|
128
|
+
fichier_echec() {
|
|
129
|
+
echo "$ETAT-echec-$1"
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Journal du dernier npm (son chemin est à donner en cas d'échec), ou son
|
|
133
|
+
# dossier ; noms horodatés : le dernier dans l'ordre du glob est le plus récent
|
|
134
|
+
dernier_journal_npm() {
|
|
135
|
+
local journal="" f
|
|
136
|
+
for f in "$HOME"/.npm/_logs/*-debug-0.log; do
|
|
137
|
+
if [ -f "$f" ]; then journal="$f"; fi
|
|
138
|
+
done
|
|
139
|
+
echo "${journal:-$HOME/.npm/_logs}"
|
|
140
|
+
}
|
|
141
|
+
|
|
101
142
|
appliquer_ia() {
|
|
143
|
+
local journal
|
|
102
144
|
if [ "$1" = on ]; then
|
|
103
|
-
|
|
145
|
+
echo "devzone : installation de Claude Code et opencode (quelques minutes)…"
|
|
146
|
+
if ! avec_progression npm install -g --no-fund --no-audit --loglevel=error "${IA_PAQUETS[@]}" >/dev/null; then
|
|
147
|
+
journal="$(dernier_journal_npm)"
|
|
148
|
+
echo "journal npm : $journal" >"$(fichier_echec ia)"
|
|
149
|
+
echo "devzone : échec de l'installation de ${IA_PAQUETS[*]} (npm install -g) ; journal npm : $journal ; réessayer : devzone appliquer" >&2
|
|
150
|
+
return 1
|
|
151
|
+
fi
|
|
152
|
+
rm -f "$(fichier_echec ia)"
|
|
153
|
+
echo "devzone : Claude Code et opencode installés"
|
|
104
154
|
# Garde-fou repowarden (hook PreToolUse de Claude Code, plugin opencode) :
|
|
105
155
|
# agent arrêté avant de modifier main/develop, de commiter sans
|
|
106
156
|
# repowarden cc ou de contourner les hooks. Global, dans les volumes
|
|
@@ -114,6 +164,7 @@ appliquer_ia() {
|
|
|
114
164
|
echo "devzone : ia actif : claude (puis /login), opencode auth login"
|
|
115
165
|
else
|
|
116
166
|
npm uninstall -g "${IA_NOMS[@]}" >/dev/null 2>&1 || true
|
|
167
|
+
rm -f "$(fichier_echec ia)"
|
|
117
168
|
echo "devzone : ia désactivé (connexions gardées dans leurs volumes)"
|
|
118
169
|
fi
|
|
119
170
|
}
|
|
@@ -142,15 +193,36 @@ appliquer_repowarden() {
|
|
|
142
193
|
ligne="$(bash "$VERSIONS" --installees 2>/dev/null | awk '$1 == "repowarden"' || true)"
|
|
143
194
|
[ -n "$ligne" ] || return 0
|
|
144
195
|
read -r _ figee installee <<<"$ligne"
|
|
196
|
+
echo "devzone : installation de repowarden $figee…"
|
|
145
197
|
npm install -g "repowarden@$figee" >/dev/null
|
|
146
198
|
repowarden install --global --lang fr
|
|
147
199
|
echo "devzone : repowarden $installee → $figee"
|
|
148
200
|
}
|
|
149
201
|
|
|
202
|
+
# Chemins des worktrees du dépôt devzone et des dépôts du workspace absents
|
|
203
|
+
# ici : créés de l'autre côté (hôte), un git worktree prune les casserait.
|
|
204
|
+
# Lecture seule : rien n'est supprimé ni réparé.
|
|
205
|
+
worktrees_absents() {
|
|
206
|
+
local depot ligne chemin
|
|
207
|
+
{
|
|
208
|
+
[ -e "$RACINE/.git" ] && echo "$RACINE"
|
|
209
|
+
find "$RACINE/workspace" -mindepth 2 -maxdepth 3 -name .git -type d 2>/dev/null | sed 's|/\.git$||'
|
|
210
|
+
} | while IFS= read -r depot; do
|
|
211
|
+
{ git -C "$depot" worktree list --porcelain 2>/dev/null || true; } | while IFS= read -r ligne; do
|
|
212
|
+
case "$ligne" in
|
|
213
|
+
"worktree "*)
|
|
214
|
+
chemin="${ligne#worktree }"
|
|
215
|
+
[ -d "$chemin" ] || echo "$chemin"
|
|
216
|
+
;;
|
|
217
|
+
esac
|
|
218
|
+
done
|
|
219
|
+
done || true
|
|
220
|
+
}
|
|
221
|
+
|
|
150
222
|
# État complet : ✔ prêt, ✖ nécessaire, ○ facultatif, ⚠ à corriger ; chaque
|
|
151
223
|
# point à faire avec sa commande (affiché à chaque démarrage)
|
|
152
224
|
etat() {
|
|
153
|
-
local nom email statut m retards
|
|
225
|
+
local nom email statut m retards chemin
|
|
154
226
|
echo "devzone : état (devzone pour le réafficher)"
|
|
155
227
|
nom="$(git config --get user.name || true)"
|
|
156
228
|
email="$(git config --get user.email || true)"
|
|
@@ -177,8 +249,14 @@ etat() {
|
|
|
177
249
|
done <<<"$retards"
|
|
178
250
|
fi
|
|
179
251
|
fi
|
|
252
|
+
while IFS= read -r chemin; do
|
|
253
|
+
[ -n "$chemin" ] || continue
|
|
254
|
+
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)"
|
|
255
|
+
done < <(worktrees_absents)
|
|
180
256
|
for m in "${MODULES[@]}"; do
|
|
181
|
-
if [ "$(valeur "$m")" = on ]; then
|
|
257
|
+
if [ "$(valeur "$m")" = on ] && [ -f "$(fichier_echec "$m")" ]; then
|
|
258
|
+
printf ' ✖ module %-10s en échec : installation incomplète (%s) : devzone appliquer\n' "$m" "$(cat "$(fichier_echec "$m")")"
|
|
259
|
+
elif [ "$(valeur "$m")" = on ]; then
|
|
182
260
|
printf ' ✔ module %-10s actif : %s\n' "$m" "$(description "$m")"
|
|
183
261
|
else
|
|
184
262
|
printf ' ○ module %-10s facultatif, %s : devzone activer %s\n' "$m" "$(description "$m")" "$m"
|
|
@@ -46,13 +46,16 @@ 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
|
-
|
|
49
|
+
echo "devzone : installation de repowarden…"
|
|
50
|
+
npm install -g repowarden@4.12.1
|
|
50
51
|
repowarden install --global --lang fr
|
|
51
52
|
|
|
52
53
|
# Modules facultatifs (assistants IA, Kubernetes) : commande devzone, état
|
|
53
|
-
# gardé dans le volume devzone-config ; installe ce qui est actif
|
|
54
|
+
# gardé dans le volume devzone-config ; installe ce qui est actif. Un module
|
|
55
|
+
# en échec n'arrête pas la création : le conteneur reste utilisable et l'état
|
|
56
|
+
# (devzone, à chaque démarrage) le montre « en échec »
|
|
54
57
|
sudo ln -sf /workspaces/devzone/.devcontainer/devzone /usr/local/bin/devzone
|
|
55
|
-
devzone appliquer
|
|
58
|
+
devzone appliquer || echo "devzone : modules incomplets (détail ci-dessus), réessayer : devzone appliquer" >&2
|
|
56
59
|
|
|
57
60
|
# Ce qui reste à faire (identité git, GitHub, modules) : récapitulatif de
|
|
58
61
|
# devzone, affiché à chaque démarrage (demarrage.sh)
|
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
|
+
}
|
package/core/scripts/lancer.sh
CHANGED
|
@@ -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"
|
package/core/scripts/versions.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Versions figées du conteneur : compare repowarden (post-create.sh) et les
|
|
3
|
-
# assistants IA (
|
|
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
|
|
@@ -17,18 +17,17 @@ ICI="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
|
17
17
|
POST_CREATE="$ICI/.devcontainer/post-create.sh"
|
|
18
18
|
DEVZONE="$ICI/.devcontainer/devzone"
|
|
19
19
|
|
|
20
|
-
# 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
|
|
21
22
|
figees() {
|
|
22
23
|
local ligne element
|
|
23
24
|
ligne="$(sed -nE 's/.*npm install -g (repowarden)@([^[:space:]]+).*/\1 \2/p' "$POST_CREATE" | head -1)"
|
|
24
25
|
[ -z "$ligne" ] || echo "$ligne"
|
|
25
|
-
|
|
26
|
-
[ -n "$ligne" ] || return 0
|
|
27
|
-
for element in $ligne; do
|
|
26
|
+
while read -r element; do
|
|
28
27
|
case "$element" in
|
|
29
|
-
|
|
28
|
+
?*@*) echo "${element%@*} ${element##*@}" ;;
|
|
30
29
|
esac
|
|
31
|
-
done
|
|
30
|
+
done < <(sed -nE 's/^IA_[A-Z0-9_]+=([^[:space:]()"]+)$/\1/p' "$DEVZONE")
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
# Vrai si la version $1 est plus récente que $2 (composants numériques)
|
|
@@ -140,7 +139,7 @@ appliquer() {
|
|
|
140
139
|
{ echo "versions : paquet inconnu : $paquet" >&2; exit 1; }
|
|
141
140
|
motif="$(echapper "$paquet")"
|
|
142
141
|
tmp="$(mktemp)"
|
|
143
|
-
sed -E "s
|
|
142
|
+
sed -E "s|^(IA_[A-Z0-9_]+=${motif}@)[^[:space:]]+$|\1${version}|" "$fichier" >"$tmp"
|
|
144
143
|
fi
|
|
145
144
|
cat "$tmp" >"$fichier"
|
|
146
145
|
rm -f "$tmp"
|
package/package.json
CHANGED