devzone 0.0.0-stage → 0.5.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.
- package/.devcontainer/Dockerfile +72 -0
- package/.devcontainer/demarrage.sh +10 -0
- package/.devcontainer/devcontainer-lock.json +34 -0
- package/.devcontainer/devcontainer.json +91 -0
- package/.devcontainer/devzone +138 -0
- package/.devcontainer/git-identite.sh +28 -0
- package/.devcontainer/kube-config.sh +80 -0
- package/.devcontainer/metrics-server.sh +61 -0
- package/.devcontainer/post-create.sh +57 -0
- package/.gitattributes +5 -0
- package/LICENSE +674 -0
- package/Makefile +39 -0
- package/README.md +274 -2
- package/bin/devzone +82 -0
- package/desinstaller.sh +132 -0
- package/package.json +29 -4
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Image de base de devzone : outils sans feature officielle, versions figées.
|
|
2
|
+
# Java, Node, Python, Docker, kubectl, helm et gh sont ajoutés par les features
|
|
3
|
+
# de devcontainer.json, par-dessus cette image.
|
|
4
|
+
|
|
5
|
+
# uv : binaire de l'image officielle (pas de script curl | sh)
|
|
6
|
+
ARG UV_VERSION=0.13.1
|
|
7
|
+
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv
|
|
8
|
+
|
|
9
|
+
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
|
|
10
|
+
|
|
11
|
+
# Versions : pour mettre à jour, changer la version ET l'empreinte sha256,
|
|
12
|
+
# puis Rebuild Container
|
|
13
|
+
ARG K9S_VERSION=0.51.0
|
|
14
|
+
ARG ACTIONLINT_VERSION=1.7.12
|
|
15
|
+
ARG GITLEAKS_VERSION=8.30.1
|
|
16
|
+
ARG KIND_VERSION=0.33.0
|
|
17
|
+
ARG RUFF_VERSION=0.17.0
|
|
18
|
+
ARG VULTURE_VERSION=2.16
|
|
19
|
+
# pytest : même version que la CI de repowarden (ci/requirements/e2e-python.in)
|
|
20
|
+
ARG PYTEST_VERSION=9.1.1
|
|
21
|
+
|
|
22
|
+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
23
|
+
|
|
24
|
+
# Contrôles shell de repowarden
|
|
25
|
+
RUN apt-get update \
|
|
26
|
+
&& apt-get install -y --no-install-recommends shellcheck bats \
|
|
27
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
28
|
+
|
|
29
|
+
# k9s, actionlint (mêmes versions que la CI de repowarden), gitleaks, kind :
|
|
30
|
+
# installer <nom> <url> <sha256> : empreinte vérifiée avant d'installer quoi que ce soit dans /usr/local/bin
|
|
31
|
+
# (kind est un binaire seul, sans archive : installé à part, même vérification)
|
|
32
|
+
RUN set -eu; \
|
|
33
|
+
arch="$(dpkg --print-architecture)"; \
|
|
34
|
+
case "$arch" in \
|
|
35
|
+
arm64) gl_arch=arm64; \
|
|
36
|
+
k9s_sha=3ee05c82e5f9198928a4e86133608ba6a2c10a2244d6a7789e820f78319d640c; \
|
|
37
|
+
al_sha=325e971b6ba9bfa504672e29be93c24981eeb1c07576d730e9f7c8805afff0c6; \
|
|
38
|
+
gl_sha=e4a487ee7ccd7d3a7f7ec08657610aa3606637dab924210b3aee62570fb4b080; \
|
|
39
|
+
kind_sha=20022bee6cfcd5086cb7234d218e3454e6090022f2a8f55d1fa7fcf42c3867a2 ;; \
|
|
40
|
+
amd64) gl_arch=x64; \
|
|
41
|
+
k9s_sha=c3752ad51a5a4015a113819c4eeb6e55a4d0e4b8e652494797532f6fc8161dd7; \
|
|
42
|
+
al_sha=8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8; \
|
|
43
|
+
gl_sha=551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb; \
|
|
44
|
+
kind_sha=aee6151561422756b764a4ae28e7f44cda5af5a9eead3cc9985112b1de8d8e0d ;; \
|
|
45
|
+
*) echo "Architecture non prise en charge : $arch" >&2; exit 1 ;; \
|
|
46
|
+
esac; \
|
|
47
|
+
installer() { \
|
|
48
|
+
tmp="$(mktemp -d)"; \
|
|
49
|
+
curl -fsSL "$2" -o "$tmp/a.tar.gz"; \
|
|
50
|
+
echo "$3 $tmp/a.tar.gz" | sha256sum -c --quiet; \
|
|
51
|
+
tar -xzf "$tmp/a.tar.gz" -C "$tmp" "$1"; \
|
|
52
|
+
install -m 0755 "$tmp/$1" /usr/local/bin/"$1"; \
|
|
53
|
+
rm -rf "$tmp"; \
|
|
54
|
+
}; \
|
|
55
|
+
installer k9s "https://github.com/derailed/k9s/releases/download/v${K9S_VERSION}/k9s_Linux_${arch}.tar.gz" "$k9s_sha"; \
|
|
56
|
+
installer actionlint "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_${arch}.tar.gz" "$al_sha"; \
|
|
57
|
+
installer gitleaks "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_${gl_arch}.tar.gz" "$gl_sha"; \
|
|
58
|
+
curl -fsSL "https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-linux-${arch}" -o /tmp/kind; \
|
|
59
|
+
echo "$kind_sha /tmp/kind" | sha256sum -c --quiet; \
|
|
60
|
+
install -m 0755 /tmp/kind /usr/local/bin/kind; \
|
|
61
|
+
rm -f /tmp/kind
|
|
62
|
+
|
|
63
|
+
COPY --from=uv /uv /uvx /usr/local/bin/
|
|
64
|
+
|
|
65
|
+
# ruff, vulture (repowarden code-mort a besoin des deux) et pytest, installés pour
|
|
66
|
+
# tous les utilisateurs, avec un Python géré par uv hors du home
|
|
67
|
+
# (variables limitées au build : uv tool install reste dans ~/.local pour vscode)
|
|
68
|
+
RUN export UV_TOOL_DIR=/opt/uv/tools UV_TOOL_BIN_DIR=/usr/local/bin \
|
|
69
|
+
UV_PYTHON_INSTALL_DIR=/opt/uv/python \
|
|
70
|
+
&& uv tool install "ruff==${RUFF_VERSION}" \
|
|
71
|
+
&& uv tool install "vulture==${VULTURE_VERSION}" \
|
|
72
|
+
&& uv tool install "pytest==${PYTEST_VERSION}"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# À chaque démarrage, dans l'ordre : identité git (déduite du compte gh),
|
|
3
|
+
# clusters Kubernetes, puis récapitulatif de ce qui reste à faire (devzone).
|
|
4
|
+
# Séquentiel : le récapitulatif voit l'identité tout juste posée ; l'échec
|
|
5
|
+
# d'une étape n'empêche pas les suivantes.
|
|
6
|
+
ICI="$(dirname "$0")"
|
|
7
|
+
bash "$ICI/git-identite.sh" || echo "démarrage : identité git non traitée (bash $ICI/git-identite.sh)"
|
|
8
|
+
bash "$ICI/kube-config.sh" || echo "démarrage : clusters non traités (bash $ICI/kube-config.sh)"
|
|
9
|
+
echo
|
|
10
|
+
bash "$ICI/devzone"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"features": {
|
|
3
|
+
"ghcr.io/devcontainers/features/docker-in-docker:2": {
|
|
4
|
+
"version": "2.17.0",
|
|
5
|
+
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
|
|
6
|
+
"integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
|
|
7
|
+
},
|
|
8
|
+
"ghcr.io/devcontainers/features/github-cli:1": {
|
|
9
|
+
"version": "1.1.3",
|
|
10
|
+
"resolved": "ghcr.io/devcontainers/features/github-cli@sha256:bd7ab48a832228f633239277552c30b353867fef2e5b037e064b4e64f0b843f2",
|
|
11
|
+
"integrity": "sha256:bd7ab48a832228f633239277552c30b353867fef2e5b037e064b4e64f0b843f2"
|
|
12
|
+
},
|
|
13
|
+
"ghcr.io/devcontainers/features/java:1": {
|
|
14
|
+
"version": "1.8.3",
|
|
15
|
+
"resolved": "ghcr.io/devcontainers/features/java@sha256:61a839211feda1e2a1f10646648a948e733e4d98d770f3a4b6698a3c5fc92abe",
|
|
16
|
+
"integrity": "sha256:61a839211feda1e2a1f10646648a948e733e4d98d770f3a4b6698a3c5fc92abe"
|
|
17
|
+
},
|
|
18
|
+
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {
|
|
19
|
+
"version": "1.3.1",
|
|
20
|
+
"resolved": "ghcr.io/devcontainers/features/kubectl-helm-minikube@sha256:bbe8adf6b37fff8c67412ab0a4579f4c2f30bbaba1d9a5cebd9e38bade54025b",
|
|
21
|
+
"integrity": "sha256:bbe8adf6b37fff8c67412ab0a4579f4c2f30bbaba1d9a5cebd9e38bade54025b"
|
|
22
|
+
},
|
|
23
|
+
"ghcr.io/devcontainers/features/node:1": {
|
|
24
|
+
"version": "1.7.1",
|
|
25
|
+
"resolved": "ghcr.io/devcontainers/features/node@sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6",
|
|
26
|
+
"integrity": "sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6"
|
|
27
|
+
},
|
|
28
|
+
"ghcr.io/devcontainers/features/python:1": {
|
|
29
|
+
"version": "1.8.0",
|
|
30
|
+
"resolved": "ghcr.io/devcontainers/features/python@sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511",
|
|
31
|
+
"integrity": "sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devzone",
|
|
3
|
+
// Image de base + outils figés (k9s, uv, actionlint, gitleaks…) : voir Dockerfile
|
|
4
|
+
"build": { "dockerfile": "Dockerfile" },
|
|
5
|
+
|
|
6
|
+
"features": {
|
|
7
|
+
"ghcr.io/devcontainers/features/java:1": {
|
|
8
|
+
"version": "21",
|
|
9
|
+
"jdkDistro": "tem",
|
|
10
|
+
"installMaven": true
|
|
11
|
+
},
|
|
12
|
+
"ghcr.io/devcontainers/features/node:1": {
|
|
13
|
+
"version": "lts",
|
|
14
|
+
"pnpmVersion": "latest"
|
|
15
|
+
},
|
|
16
|
+
"ghcr.io/devcontainers/features/python:1": {
|
|
17
|
+
"version": "3.12",
|
|
18
|
+
// Pas d'outils pipx : leur lanceur « python -E » ignore PYTHONPATH et
|
|
19
|
+
// PYTHONPYCACHEPREFIX, dont repowarden a besoin pour lancer les tests
|
|
20
|
+
// (ruff, vulture et pytest viennent du Dockerfile, par uv)
|
|
21
|
+
"installTools": false
|
|
22
|
+
},
|
|
23
|
+
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
|
|
24
|
+
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {
|
|
25
|
+
"minikube": "none"
|
|
26
|
+
},
|
|
27
|
+
// gh : tickets, PR, protection (repowarden)
|
|
28
|
+
"ghcr.io/devcontainers/features/github-cli:1": {}
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// Toujours /workspaces/devzone, quel que soit le nom du dossier sur l'hôte
|
|
32
|
+
// (npx devzone <dossier>) : scripts et chemins du conteneur en dépendent
|
|
33
|
+
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/devzone,type=bind,consistency=cached",
|
|
34
|
+
"workspaceFolder": "/workspaces/devzone",
|
|
35
|
+
|
|
36
|
+
// Caches persistants : survivent aux rebuilds du conteneur. Préfixe des
|
|
37
|
+
// volumes : devzone, ou DEVZONE_VOLUMES (tests fonctionnels, isolés)
|
|
38
|
+
"mounts": [
|
|
39
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-m2,target=/home/vscode/.m2,type=volume",
|
|
40
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-pnpm,target=/home/vscode/.local/share/pnpm,type=volume",
|
|
41
|
+
// Assistants IA : connexion et réglages gardés d'un rebuild à l'autre
|
|
42
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-claude,target=/home/vscode/.claude,type=volume",
|
|
43
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-opencode-config,target=/home/vscode/.config/opencode,type=volume",
|
|
44
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-opencode-data,target=/home/vscode/.local/share/opencode,type=volume",
|
|
45
|
+
// Connexion gh et identité git (~/.config/git/config, lu par git comme
|
|
46
|
+
// config globale) : le conteneur reconstruit peut commiter et pousser
|
|
47
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-gh,target=/home/vscode/.config/gh,type=volume",
|
|
48
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-git,target=/home/vscode/.config/git,type=volume",
|
|
49
|
+
// Modules activés (devzone activer|desactiver), propres à chaque utilisateur
|
|
50
|
+
"source=${localEnv:DEVZONE_VOLUMES:devzone}-config,target=/home/vscode/.config/devzone,type=volume"
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
"runArgs": [
|
|
54
|
+
// Cluster Kubernetes de l'hôte : sa config en lecture seule, adaptée au
|
|
55
|
+
// conteneur par kube-config.sh. HOME (Mac, Linux) ou USERPROFILE (Windows) ;
|
|
56
|
+
// -v plutôt que mounts : crée ~/.kube s'il manque au lieu d'échouer
|
|
57
|
+
"-v", "${localEnv:HOME}${localEnv:USERPROFILE}/.kube:/home/vscode/.kube-host:ro",
|
|
58
|
+
// host.docker.internal existe d'office avec Docker Desktop, pas sous Linux
|
|
59
|
+
"--add-host=host.docker.internal:host-gateway"
|
|
60
|
+
],
|
|
61
|
+
|
|
62
|
+
"postCreateCommand": "bash .devcontainer/post-create.sh",
|
|
63
|
+
// Identité git, clusters, puis récapitulatif de ce qui reste à faire
|
|
64
|
+
"postStartCommand": "bash .devcontainer/demarrage.sh",
|
|
65
|
+
// Clusters kind du conteneur (config) + cluster de l'hôte (hote.config,
|
|
66
|
+
// refait à chaque démarrage par kube-config.sh)
|
|
67
|
+
"remoteEnv": {
|
|
68
|
+
"KUBECONFIG": "/home/vscode/.kube/config:/home/vscode/.kube/hote.config",
|
|
69
|
+
// Claude Code range aussi .claude.json (connexion, réglages) dans ce
|
|
70
|
+
// dossier, donc dans son volume, au lieu de ~/.claude.json
|
|
71
|
+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude"
|
|
72
|
+
},
|
|
73
|
+
"remoteUser": "vscode",
|
|
74
|
+
|
|
75
|
+
"customizations": {
|
|
76
|
+
"vscode": {
|
|
77
|
+
"extensions": [
|
|
78
|
+
"vscjava.vscode-java-pack",
|
|
79
|
+
"vmware.vscode-boot-dev-pack",
|
|
80
|
+
"dbaeumer.vscode-eslint",
|
|
81
|
+
"esbenp.prettier-vscode",
|
|
82
|
+
"bradlc.vscode-tailwindcss",
|
|
83
|
+
"ms-python.python",
|
|
84
|
+
"charliermarsh.ruff",
|
|
85
|
+
"ms-azuretools.vscode-docker",
|
|
86
|
+
"ms-kubernetes-tools.vscode-kubernetes-tools",
|
|
87
|
+
"redhat.vscode-yaml"
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Modules facultatifs de devzone, activés à la demande, sans rebuild :
|
|
3
|
+
# devzone état des modules
|
|
4
|
+
# devzone activer <module> active et applique tout de suite
|
|
5
|
+
# devzone desactiver <module> désactive et applique tout de suite
|
|
6
|
+
# devzone appliquer installe ce qui est actif (post-create.sh)
|
|
7
|
+
# devzone actif <module> code 0 si actif (scripts de démarrage)
|
|
8
|
+
# État propre à chaque utilisateur : ~/.config/devzone/modules (volume
|
|
9
|
+
# devzone-config, survit aux rebuilds), une ligne « module=on|off ».
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
ETAT="${DEVZONE_ETAT:-$HOME/.config/devzone/modules}"
|
|
13
|
+
ICI="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
|
14
|
+
MODULES=(ia kubernetes)
|
|
15
|
+
|
|
16
|
+
# 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
|
+
|
|
21
|
+
description() {
|
|
22
|
+
case "$1" in
|
|
23
|
+
ia) echo "assistants IA : Claude Code, opencode" ;;
|
|
24
|
+
kubernetes) echo "connexion au cluster de l'hôte et metrics-server au démarrage" ;;
|
|
25
|
+
esac
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
connu() {
|
|
29
|
+
local m
|
|
30
|
+
for m in "${MODULES[@]}"; do [ "$m" = "$1" ] && return 0; done
|
|
31
|
+
return 1
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Premier démarrage (aucun état) : tout désactivé, sauf ia si une connexion
|
|
35
|
+
# existe déjà dans les volumes (pas de régression pour qui s'en servait)
|
|
36
|
+
initialiser() {
|
|
37
|
+
[ -f "$ETAT" ] && return 0
|
|
38
|
+
mkdir -p "$(dirname "$ETAT")"
|
|
39
|
+
local ia=off
|
|
40
|
+
if [ -f "$HOME/.claude/.credentials.json" ] || [ -f "$HOME/.local/share/opencode/auth.json" ]; then
|
|
41
|
+
ia=on
|
|
42
|
+
# stderr : initialiser est aussi appelé dans $(valeur …)
|
|
43
|
+
echo "devzone : connexion d'un assistant IA trouvée, module ia activé (devzone desactiver ia pour le retirer)" >&2
|
|
44
|
+
fi
|
|
45
|
+
printf 'ia=%s\nkubernetes=off\n' "$ia" >"$ETAT"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
valeur() {
|
|
49
|
+
initialiser
|
|
50
|
+
local v
|
|
51
|
+
v="$(grep -E "^$1=" "$ETAT" | tail -1 | cut -d= -f2 || true)"
|
|
52
|
+
[ "$v" = on ] && echo on || echo off
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
ecrire() {
|
|
56
|
+
initialiser
|
|
57
|
+
local tmp
|
|
58
|
+
tmp="$(mktemp)"
|
|
59
|
+
grep -vE "^$1=" "$ETAT" >"$tmp" || true
|
|
60
|
+
echo "$1=$2" >>"$tmp"
|
|
61
|
+
mv "$tmp" "$ETAT"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
appliquer_ia() {
|
|
65
|
+
if [ "$1" = on ]; then
|
|
66
|
+
npm install -g --no-fund --no-audit --loglevel=error "${IA_PAQUETS[@]}" >/dev/null
|
|
67
|
+
echo "devzone : ia actif : claude (puis /login), opencode auth login"
|
|
68
|
+
else
|
|
69
|
+
npm uninstall -g "${IA_NOMS[@]}" >/dev/null 2>&1 || true
|
|
70
|
+
echo "devzone : ia désactivé (connexions gardées dans leurs volumes)"
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
appliquer_kubernetes() {
|
|
75
|
+
if [ "$1" = on ]; then
|
|
76
|
+
bash "$ICI/kube-config.sh"
|
|
77
|
+
else
|
|
78
|
+
rm -f "$HOME/.kube/hote.config"
|
|
79
|
+
echo "devzone : kubernetes désactivé (metrics-server reste installé sur les clusters où il l'a été)"
|
|
80
|
+
fi
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# État complet : ✔ prêt, ✖ nécessaire, ○ facultatif, ⚠ à corriger ; chaque
|
|
84
|
+
# point à faire avec sa commande (affiché à chaque démarrage)
|
|
85
|
+
etat() {
|
|
86
|
+
local nom email statut m
|
|
87
|
+
echo "devzone : état (devzone pour le réafficher)"
|
|
88
|
+
nom="$(git config --get user.name || true)"
|
|
89
|
+
email="$(git config --get user.email || true)"
|
|
90
|
+
if [ -n "$nom" ] && [ -n "$email" ]; then
|
|
91
|
+
echo " ✔ identité git $nom <$email>"
|
|
92
|
+
else
|
|
93
|
+
echo " ✖ identité git nécessaire pour commiter : gh auth login -s workflow (automatique),"
|
|
94
|
+
echo " ou git config --file ~/.config/git/config user.name \"<nom>\" et user.email \"<email>\""
|
|
95
|
+
fi
|
|
96
|
+
if ! statut="$(gh auth status 2>&1)"; then
|
|
97
|
+
echo " ○ GitHub facultatif (push et PR, tickets repowarden) : gh auth login -s workflow"
|
|
98
|
+
elif grep -q "Token scopes:" <<<"$statut" && ! grep -q "'workflow'" <<<"$statut"; then
|
|
99
|
+
echo " ⚠ GitHub connecté, sans permission workflow (push de .github/workflows/ refusé) : gh auth refresh -h github.com -s workflow"
|
|
100
|
+
else
|
|
101
|
+
echo " ✔ GitHub connecté"
|
|
102
|
+
fi
|
|
103
|
+
for m in "${MODULES[@]}"; do
|
|
104
|
+
if [ "$(valeur "$m")" = on ]; then
|
|
105
|
+
printf ' ✔ module %-10s actif : %s\n' "$m" "$(description "$m")"
|
|
106
|
+
else
|
|
107
|
+
printf ' ○ module %-10s facultatif, %s : devzone activer %s\n' "$m" "$(description "$m")" "$m"
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
changer() {
|
|
113
|
+
local m="${2:-}"
|
|
114
|
+
if [ -z "$m" ] || ! connu "$m"; then
|
|
115
|
+
echo "devzone : module inconnu : ${m:-(aucun)} ; modules : ${MODULES[*]}" >&2
|
|
116
|
+
exit 1
|
|
117
|
+
fi
|
|
118
|
+
ecrire "$m" "$1"
|
|
119
|
+
"appliquer_$m" "$1"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
case "${1:-}" in
|
|
123
|
+
"" | etat | modules) etat ;;
|
|
124
|
+
activer) changer on "${2:-}" ;;
|
|
125
|
+
desactiver) changer off "${2:-}" ;;
|
|
126
|
+
appliquer)
|
|
127
|
+
[ "$(valeur ia)" = off ] || appliquer_ia on
|
|
128
|
+
;;
|
|
129
|
+
actif)
|
|
130
|
+
connu "${2:-}" || { echo "devzone : module inconnu : ${2:-(aucun)}" >&2; exit 2; }
|
|
131
|
+
[ "$(valeur "$2")" = on ]
|
|
132
|
+
;;
|
|
133
|
+
-h | --help | aide) sed -n '2,8p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' ;;
|
|
134
|
+
*)
|
|
135
|
+
echo "devzone : commande inconnue : $1 (devzone --help)" >&2
|
|
136
|
+
exit 1
|
|
137
|
+
;;
|
|
138
|
+
esac
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Identité git, à chaque démarrage tant qu'elle manque : déduite du compte gh
|
|
3
|
+
# (propre à chaque utilisateur, connexion gardée dans son volume) et écrite dans
|
|
4
|
+
# ~/.config/git/config (volume devzone-git, survit aux rebuilds).
|
|
5
|
+
# Une identité déjà définie (à la main, ou recopiée par VS Code dans
|
|
6
|
+
# ~/.gitconfig) n'est jamais remplacée. Email noreply de GitHub : les commits
|
|
7
|
+
# sont rattachés au compte sans exposer l'email personnel.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
CONFIG="$HOME/.config/git/config"
|
|
11
|
+
nom_git="$(git config --get user.name || true)"
|
|
12
|
+
email_git="$(git config --get user.email || true)"
|
|
13
|
+
|
|
14
|
+
[ -n "$nom_git" ] && [ -n "$email_git" ] && exit 0
|
|
15
|
+
|
|
16
|
+
# Sans gh : rien à déduire ; le récapitulatif de devzone le signale
|
|
17
|
+
gh auth status >/dev/null 2>&1 || exit 0
|
|
18
|
+
|
|
19
|
+
id="" login="" nom=""
|
|
20
|
+
IFS=$'\t' read -r id login nom < <(gh api user --jq '[.id, .login, (.name // "")] | @tsv' 2>/dev/null || true)
|
|
21
|
+
if [ -z "$id" ] || [ -z "$login" ]; then
|
|
22
|
+
echo "git-identite : compte GitHub illisible (réseau ?) ; relancer : bash .devcontainer/git-identite.sh"
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
[ -n "$nom_git" ] || git config --file "$CONFIG" user.name "${nom:-$login}"
|
|
27
|
+
[ -n "$email_git" ] || git config --file "$CONFIG" user.email "${id}+${login}@users.noreply.github.com"
|
|
28
|
+
echo "git-identite : $(git config --get user.name) <$(git config --get user.email)>"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Clusters Kubernetes du conteneur, à chaque démarrage (le port du cluster de
|
|
3
|
+
# l'hôte peut changer) :
|
|
4
|
+
# - ~/.kube/hote.config : copie du ~/.kube de l'hôte (monté en lecture seule) où
|
|
5
|
+
# 127.0.0.1/localhost deviennent host.docker.internal, l'hôte vu du conteneur ;
|
|
6
|
+
# tls-server-name garde le nom attendu par le certificat
|
|
7
|
+
# - ~/.kube/config : clusters kind du conteneur, jamais touché ici
|
|
8
|
+
# KUBECONFIG (devcontainer.json) combine les deux.
|
|
9
|
+
# Module kubernetes (devzone activer kubernetes) : connexion au cluster de
|
|
10
|
+
# l'hôte et metrics-server seulement s'il est actif ; les contextes kind sont
|
|
11
|
+
# toujours remis (un cluster créé à la main reste utilisable).
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
ICI="$(dirname "$0")"
|
|
15
|
+
module=off
|
|
16
|
+
bash "$ICI/devzone" actif kubernetes && module=on
|
|
17
|
+
|
|
18
|
+
# DEVZONE_KUBE_SOURCE : tests fonctionnels (jamais le cluster de l'hôte)
|
|
19
|
+
SOURCE="${DEVZONE_KUBE_SOURCE:-$HOME/.kube-host/config}"
|
|
20
|
+
HOTE="$HOME/.kube/hote.config"
|
|
21
|
+
|
|
22
|
+
mkdir -p "$HOME/.kube"
|
|
23
|
+
rm -f "$HOTE"
|
|
24
|
+
# Doit exister : sinon kind écrit dans hote.config, effacé au prochain démarrage
|
|
25
|
+
[ -f "$HOME/.kube/config" ] || install -m 600 /dev/null "$HOME/.kube/config"
|
|
26
|
+
|
|
27
|
+
if [ "$module" = on ] && [ -f "$SOURCE" ]; then
|
|
28
|
+
install -m 600 "$SOURCE" "$HOTE"
|
|
29
|
+
KUBECONFIG="$HOTE" kubectl config view \
|
|
30
|
+
-o jsonpath='{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}' |
|
|
31
|
+
while IFS=$'\t' read -r nom serveur; do
|
|
32
|
+
case "$serveur" in
|
|
33
|
+
https://127.0.0.1:* | https://localhost:*) ;;
|
|
34
|
+
*) continue ;;
|
|
35
|
+
esac
|
|
36
|
+
hote="${serveur#https://}"
|
|
37
|
+
hote="${hote%%:*}"
|
|
38
|
+
KUBECONFIG="$HOTE" kubectl config set-cluster "$nom" \
|
|
39
|
+
--server="https://host.docker.internal:${serveur##*:}" \
|
|
40
|
+
--tls-server-name="$hote" >/dev/null
|
|
41
|
+
done
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Clusters kind qui ont survécu au redémarrage : contexte remis dans ~/.kube/config
|
|
45
|
+
# (le Docker interne peut mettre quelques secondes à démarrer)
|
|
46
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do docker info >/dev/null 2>&1 && break; sleep 1; done
|
|
47
|
+
choix="$(KUBECONFIG="$HOME/.kube/config" kubectl config current-context 2>/dev/null || true)"
|
|
48
|
+
for cluster in $(kind get clusters 2>/dev/null); do
|
|
49
|
+
kind export kubeconfig --name "$cluster" --kubeconfig "$HOME/.kube/config" >/dev/null 2>&1 || true
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
# Cluster actif : celui choisi avant (kubectl config use-context), sinon celui
|
|
53
|
+
# de l'hôte s'il en a un (current-context de hote.config), sinon kind
|
|
54
|
+
export KUBECONFIG="$HOME/.kube/config:$HOTE"
|
|
55
|
+
if [ -n "$choix" ] && kubectl config use-context "$choix" >/dev/null 2>&1; then
|
|
56
|
+
:
|
|
57
|
+
elif [ -f "$HOTE" ] && [ -n "$(KUBECONFIG="$HOTE" kubectl config current-context 2>/dev/null)" ]; then
|
|
58
|
+
KUBECONFIG="$HOME/.kube/config" kubectl config unset current-context >/dev/null
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Clusters joignables, parmi ceux de l'hôte et ceux de kind
|
|
62
|
+
joignables=0
|
|
63
|
+
for contexte in $(kubectl config get-contexts -o name 2>/dev/null); do
|
|
64
|
+
if kubectl --context "$contexte" --request-timeout=3s get --raw /readyz >/dev/null 2>&1; then
|
|
65
|
+
echo "kube-config : cluster joignable : $contexte"
|
|
66
|
+
joignables=$((joignables + 1))
|
|
67
|
+
elif [[ "$contexte" == kind-* ]]; then
|
|
68
|
+
echo "kube-config : cluster kind en cours de démarrage : $contexte"
|
|
69
|
+
joignables=$((joignables + 1))
|
|
70
|
+
fi
|
|
71
|
+
done
|
|
72
|
+
# Module désactivé : le récapitulatif de devzone le signale
|
|
73
|
+
[ "$module" = on ] || exit 0
|
|
74
|
+
echo "kube-config : cluster actif : $(kubectl config current-context 2>/dev/null || echo aucun)"
|
|
75
|
+
if [ "$joignables" -eq 0 ]; then
|
|
76
|
+
echo "kube-config : aucun cluster joignable ; en créer un dans le conteneur : kind create cluster"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# CPU/RAM dans k9s : metrics-server sur les clusters joignables qui ne l'ont pas
|
|
80
|
+
bash "$ICI/metrics-server.sh" || true
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Installe metrics-server (CPU/RAM dans k9s, kubectl top) sur les clusters qui
|
|
3
|
+
# n'ont pas d'API Metrics. Docker Desktop et kind ne l'ont pas d'office.
|
|
4
|
+
# Usage : metrics-server.sh [contexte...] (défaut : clusters locaux joignables)
|
|
5
|
+
# --kubelet-insecure-tls : le kubelet de Docker Desktop et de kind a un
|
|
6
|
+
# certificat auto-signé, sans cette option le pod ne devient jamais Ready.
|
|
7
|
+
# Sortie en erreur si un contexte demandé est inconnu ou injoignable, ou si
|
|
8
|
+
# une installation échoue (kube-config.sh l'appelle avec || true).
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
VERSION=v0.9.0
|
|
12
|
+
MANIFESTE="https://github.com/kubernetes-sigs/metrics-server/releases/download/${VERSION}/components.yaml"
|
|
13
|
+
|
|
14
|
+
mapfile -t connus < <(kubectl config get-contexts -o name 2>/dev/null || true)
|
|
15
|
+
demandes=$#
|
|
16
|
+
if [ "$demandes" -eq 0 ]; then
|
|
17
|
+
# Clusters locaux seulement : jamais d'install automatique sur un cluster
|
|
18
|
+
# distant de l'hôte (prod, staging…) ; pour un autre, le nommer en argument
|
|
19
|
+
mapfile -t contextes < <(printf '%s\n' ${connus[@]+"${connus[@]}"} |
|
|
20
|
+
grep -E '^(kind-.*|docker-desktop|rancher-desktop|orbstack|minikube)$' || true)
|
|
21
|
+
set -- ${contextes[@]+"${contextes[@]}"}
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
code=0
|
|
25
|
+
joignables=0
|
|
26
|
+
for contexte in "$@"; do
|
|
27
|
+
if [ "$demandes" -gt 0 ] && ! printf '%s\n' ${connus[@]+"${connus[@]}"} | grep -qxF -- "$contexte"; then
|
|
28
|
+
echo "metrics-server : contexte inconnu : $contexte (voir kubectl config get-contexts)" >&2
|
|
29
|
+
code=1
|
|
30
|
+
continue
|
|
31
|
+
fi
|
|
32
|
+
k=(kubectl --context "$contexte" --request-timeout=5s)
|
|
33
|
+
if ! "${k[@]}" get --raw /readyz >/dev/null 2>&1; then
|
|
34
|
+
# Sans argument : kind peut être en cours de démarrage, ignoré
|
|
35
|
+
if [ "$demandes" -gt 0 ]; then
|
|
36
|
+
echo "metrics-server : cluster injoignable : $contexte" >&2
|
|
37
|
+
code=1
|
|
38
|
+
fi
|
|
39
|
+
continue
|
|
40
|
+
fi
|
|
41
|
+
joignables=$((joignables + 1))
|
|
42
|
+
if "${k[@]}" get apiservice v1beta1.metrics.k8s.io >/dev/null 2>&1; then
|
|
43
|
+
echo "metrics-server : déjà présent : $contexte"
|
|
44
|
+
continue
|
|
45
|
+
fi
|
|
46
|
+
if "${k[@]}" apply -f "$MANIFESTE" >/dev/null &&
|
|
47
|
+
"${k[@]}" -n kube-system patch deployment metrics-server --type=json \
|
|
48
|
+
-p '[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]' >/dev/null &&
|
|
49
|
+
# Marque : make desinstaller ne retire que ce que devzone a installé
|
|
50
|
+
"${k[@]}" -n kube-system label deployment metrics-server devzone=installe --overwrite >/dev/null; then
|
|
51
|
+
echo "metrics-server : installé ($VERSION) : $contexte (métriques dans ~1 min)"
|
|
52
|
+
else
|
|
53
|
+
echo "metrics-server : échec de l'installation : $contexte" >&2
|
|
54
|
+
code=1
|
|
55
|
+
fi
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
if [ "$demandes" -eq 0 ] && [ "$joignables" -eq 0 ]; then
|
|
59
|
+
echo "metrics-server : aucun cluster local joignable ; après kind create cluster : bash .devcontainer/metrics-server.sh"
|
|
60
|
+
fi
|
|
61
|
+
exit "$code"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Étapes qui ne peuvent pas être dans l'image (Dockerfile) :
|
|
3
|
+
# - volumes montés au démarrage seulement
|
|
4
|
+
# - npm fourni par la feature node, ajoutée après le Dockerfile
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
# Volumes nommés créés en root → rendre au user vscode
|
|
8
|
+
# (et ~/.config, créé par Docker pour monter ~/.config/opencode)
|
|
9
|
+
sudo chown -R vscode:vscode /home/vscode/.m2 /home/vscode/.local /home/vscode/.claude \
|
|
10
|
+
/home/vscode/.config/opencode /home/vscode/.config/gh /home/vscode/.config/git \
|
|
11
|
+
/home/vscode/.config/devzone
|
|
12
|
+
sudo chown vscode:vscode /home/vscode/.config
|
|
13
|
+
|
|
14
|
+
# Git : dépôts du conteneur déclarés sûrs (leur propriétaire peut différer de
|
|
15
|
+
# l'utilisateur qui lance git : volumes, Docker Desktop, outils lancés à part),
|
|
16
|
+
# et accès à GitHub par le jeton de gh, conservé dans son volume (https, même
|
|
17
|
+
# pour les remotes en git@github.com:, sans clé ssh à recopier)
|
|
18
|
+
# Réglages de la machine dans ~/.gitconfig du conteneur (recréé à chaque
|
|
19
|
+
# rebuild) : sans ce fichier, git config --global (et repowarden install)
|
|
20
|
+
# écriraient dans ~/.config/git/config, le volume de l'identité, où ils
|
|
21
|
+
# s'accumuleraient d'un rebuild à l'autre
|
|
22
|
+
touch "$HOME/.gitconfig"
|
|
23
|
+
# Volume touché par une version antérieure : seuls ces réglages en sont
|
|
24
|
+
# retirés, l'identité et tout autre réglage sont conservés
|
|
25
|
+
volume="$HOME/.config/git/config"
|
|
26
|
+
if [ -f "$volume" ]; then
|
|
27
|
+
retirer() { git config --file "$volume" --unset-all "$@" 2>/dev/null || true; }
|
|
28
|
+
retirer safe.directory '^/workspaces/devzone'
|
|
29
|
+
retirer credential.https://github.com.helper
|
|
30
|
+
retirer url.https://github.com/.insteadOf
|
|
31
|
+
retirer core.hooksPath 'repowarden'
|
|
32
|
+
retirer alias.cc 'repowarden'
|
|
33
|
+
retirer repowarden.lang
|
|
34
|
+
fi
|
|
35
|
+
git config --global --add safe.directory /workspaces/devzone
|
|
36
|
+
git config --global --add safe.directory '/workspaces/devzone/workspace/*'
|
|
37
|
+
git config --global --replace-all credential.https://github.com.helper ''
|
|
38
|
+
git config --global --add credential.https://github.com.helper '!gh auth git-credential'
|
|
39
|
+
git config --global url.https://github.com/.insteadOf git@github.com:
|
|
40
|
+
|
|
41
|
+
# repowarden, version figée (il installe des hooks git globaux) ; mettre à jour
|
|
42
|
+
# en changeant la version ici, puis Rebuild Container
|
|
43
|
+
npm install -g repowarden@4.9.1
|
|
44
|
+
repowarden install --global --lang fr
|
|
45
|
+
|
|
46
|
+
# Modules facultatifs (assistants IA, Kubernetes) : commande devzone, état
|
|
47
|
+
# gardé dans le volume devzone-config ; installe ce qui est actif
|
|
48
|
+
sudo ln -sf /workspaces/devzone/.devcontainer/devzone /usr/local/bin/devzone
|
|
49
|
+
devzone appliquer
|
|
50
|
+
|
|
51
|
+
# Ce qui reste à faire (identité git, GitHub, modules) : récapitulatif de
|
|
52
|
+
# devzone, affiché à chaque démarrage (demarrage.sh)
|
|
53
|
+
|
|
54
|
+
recap="java $(java -version 2>&1 | head -1 | cut -d'"' -f2), node $(node -v), python $(python3 --version | cut -d' ' -f2), repowarden $(repowarden --version)"
|
|
55
|
+
! command -v claude >/dev/null || recap+=", claude $(claude --version | cut -d' ' -f1)"
|
|
56
|
+
! command -v opencode >/dev/null || recap+=", opencode $(opencode --version)"
|
|
57
|
+
echo "devzone prêt : $recap"
|