-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·217 lines (179 loc) · 9.33 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·217 lines (179 loc) · 9.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#!/bin/sh
# Installe pvecli depuis les releases GitHub.
#
# curl -fsSL https://raw.githubusercontent.com/dev-toolings/pvecli/main/install.sh | sh
#
# Variables :
# PVECLI_VERSION version précise (défaut : la dernière release)
# PREFIX racine d'installation (défaut : ~/.local → ~/.local/bin)
# PVECLI_NO_AGENT =1 pour ne pas installer l'agent Claude Code
# PVECLI_NO_SHELL_HOOK =1 pour ne pas câbler la notification de mise à
# jour dans le shell (voir « pvecli update install-hook »)
# PVECLI_ONLY_IF_NEWER =1 pour ne rien faire si la version visée est déjà
# installée — c'est ce qui rend ce script rejouable
# sans frais depuis un timer (voir scripts/autoupdate/).
#
# CE SCRIPT VÉRIFIE LA SOMME SHA-256 AVANT D'INSTALLER, ET S'ARRÊTE SI ELLE NE
# CORRESPOND PAS. Un installeur qu'on canalise dans un shell exécute du code
# arrivé par le réseau ; le minimum qu'il doive à celui qui le lance, c'est de
# prouver que l'octet posé sur son disque est bien celui qui a été publié.
# C'est la même exigence que l'épinglage TLS de la CLI elle-même : vérifier
# coûte peu et ne se rattrape pas après coup.
set -eu
REPO="dev-toolings/pvecli"
BINARY="pvecli"
PREFIX="${PREFIX:-$HOME/.local}"
BINDIR="$PREFIX/bin"
say() { printf '%s\n' "$*"; }
die() {
printf '\n✗ %s\n' "$*" >&2
exit 1
}
# ── Outils ────────────────────────────────────────────────────────────────────
have() { command -v "$1" >/dev/null 2>&1; }
# Les téléchargements échouent en silence : chaque appel est suivi d'un message
# qui nomme ce qui manque et pourquoi. Laisser en plus passer « curl: (22) The
# requested URL returned error: 404 » ne dit rien de plus et brouille le vrai.
if have curl; then
fetch() { curl -fsL "$1" -o "$2" 2>/dev/null; }
fetch_stdout() { curl -fsL "$1" 2>/dev/null; }
elif have wget; then
fetch() { wget -qO "$2" "$1" 2>/dev/null; }
fetch_stdout() { wget -qO- "$1" 2>/dev/null; }
else
die "ni curl ni wget — impossible de télécharger quoi que ce soit."
fi
# sha256sum sous Linux, shasum -a 256 sous macOS. Sans l'un des deux on
# n'installe pas : le contrôle n'est pas une option de confort.
if have sha256sum; then
sha256() { sha256sum "$1" | cut -d' ' -f1; }
elif have shasum; then
sha256() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
die "ni sha256sum ni shasum — la somme de contrôle ne peut pas être vérifiée,
et installer sans la vérifier n'est pas proposé par ce script."
fi
# ── Plateforme ────────────────────────────────────────────────────────────────
os="$(uname -s)"
arch="$(uname -m)"
case "$os/$arch" in
Linux/x86_64 | Linux/amd64) target="linux_amd64" ;;
Darwin/arm64 | Darwin/aarch64) target="darwin_arm64" ;;
*)
die "plateforme non publiée : $os/$arch
Les releases couvrent linux/amd64 et darwin/arm64. Pour tout le reste, la
compilation depuis les sources prend une commande :
git clone https://github.com/$REPO.git && cd $BINARY && make install"
;;
esac
# ── Version ───────────────────────────────────────────────────────────────────
version="${PVECLI_VERSION:-}"
if [ -z "$version" ]; then
say "→ recherche de la dernière release de $REPO"
# L'API renvoie du JSON ; on n'extrait qu'un champ, sans dépendre de jq.
version="$(fetch_stdout "https://api.github.com/repos/$REPO/releases/latest" |
sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -1)"
[ -n "$version" ] || die "aucune release trouvée pour $REPO.
Le dépôt n'en publie peut-être pas encore. Depuis les sources :
git clone https://github.com/$REPO.git && cd $BINARY && make install"
fi
asset="${BINARY}_${version}_${target}"
base="https://github.com/$REPO/releases/download/$version"
# Rejoué chaque jour par un timer, ce script téléchargerait 13 Mo pour réécrire
# le même octet. `pvecli --version` imprime « pvecli v0.1.0 (commit abc1234) » ;
# le premier champ suffit à trancher. On compare des chaînes, pas des numéros :
# on ne cherche pas « plus récent », seulement « autre chose que ce qui tourne ».
if [ "${PVECLI_ONLY_IF_NEWER:-}" = "1" ] && [ -x "$BINDIR/$BINARY" ]; then
installed="$("$BINDIR/$BINARY" --version 2>/dev/null | awk '{print $2}')"
if [ "$installed" = "$version" ]; then
say "→ pvecli $version déjà installé — rien à faire"
exit 0
fi
# Un binaire « dev » vient d'un `make install` : quelqu'un travaille dessus,
# et il contient presque toujours plus que la dernière release. Le remplacer
# depuis un timer, la nuit, sans que personne ne l'ait demandé, ferait
# disparaître ce travail — et la panne du lendemain serait cherchée partout
# sauf ici. On s'abstient, et on le dit.
if [ "$installed" = "dev" ]; then
say "→ pvecli compilé localement (dev) — laissé en place, $version non installée"
say " pour repasser sur la release publiée : PVECLI_ONLY_IF_NEWER= sh install.sh"
exit 0
fi
say "→ pvecli ${installed:-absent} → $version"
fi
say "→ pvecli $version ($target)"
# ── Téléchargement et vérification ────────────────────────────────────────────
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT INT TERM
say "→ téléchargement"
fetch "$base/$asset" "$tmp/$asset" ||
die "téléchargement impossible : $base/$asset
Cette version publie-t-elle bien un binaire pour $target ?"
fetch "$base/SHA256SUMS" "$tmp/SHA256SUMS" ||
die "SHA256SUMS introuvable pour $version — installation refusée.
Sans lui, rien ne distingue le binaire publié d'un fichier substitué en route."
expected="$(grep -F " $asset" "$tmp/SHA256SUMS" | cut -d' ' -f1 | head -1)"
[ -n "$expected" ] || die "$asset n'apparaît pas dans SHA256SUMS — installation refusée."
actual="$(sha256 "$tmp/$asset")"
if [ "$expected" != "$actual" ]; then
die "SOMME DE CONTRÔLE INVALIDE — rien n'a été installé.
attendue $expected
obtenue $actual
Soit le téléchargement a été corrompu, soit le fichier n'est pas celui qui a
été publié. Recommence ; si l'écart persiste, ne l'installe pas."
fi
say " ✓ SHA-256 vérifiée"
# ── Installation ──────────────────────────────────────────────────────────────
mkdir -p "$BINDIR"
chmod 0755 "$tmp/$asset"
# On écrit à côté puis on déplace : un binaire remplacé pendant qu'il tourne ne
# doit jamais être un fichier à moitié écrit.
mv "$tmp/$asset" "$BINDIR/$BINARY.new"
mv "$BINDIR/$BINARY.new" "$BINDIR/$BINARY"
say " ✓ $BINDIR/$BINARY"
# La preuve est l'exécution, pas la copie.
got="$("$BINDIR/$BINARY" --version)" || die "le binaire installé ne s'exécute pas."
say " ✓ $got"
# ── Notification de mise à jour ───────────────────────────────────────────────
#
# Câble la notification de mise à jour (PVX-090), désormais une fonctionnalité
# du binaire lui-même : ce script n'a jamais le dépôt sous la main, seulement
# le binaire qu'il vient de poser, et « pvecli update install-hook » embarque
# tout ce qu'il faut. Un échec ici n'est pas un échec d'installation : pvecli
# est installé, c'est l'essentiel — le hook n'est qu'un confort.
if [ "${PVECLI_NO_SHELL_HOOK:-}" != "1" ]; then
if hook_out="$("$BINDIR/$BINARY" update install-hook 2>/dev/null)"; then
say " · $(printf '%s' "$hook_out" | head -1)"
else
say " · notification non câblée — « pvecli update install-hook » à la main"
fi
fi
# ── Agent Claude Code ─────────────────────────────────────────────────────────
if [ "${PVECLI_NO_AGENT:-}" != "1" ]; then
# On rend le chemin que la commande a réellement écrit, pas celui qu'on
# suppose : CLAUDE_CONFIG_DIR peut déplacer la cible.
if agent_out="$("$BINDIR/$BINARY" ai install 2>/dev/null)"; then
say " ✓ $(printf '%s' "$agent_out" | head -1)"
else
# Un agent déjà personnalisé n'est pas un échec d'installation.
say " · agent non installé (déjà présent et modifié ?) — « pvecli ai status »"
fi
fi
# ── Suite ─────────────────────────────────────────────────────────────────────
case ":$PATH:" in
*":$BINDIR:"*) ;;
*)
say ""
say "⚠ $BINDIR n'est pas dans ton PATH. Ajoute :"
say ""
say " export PATH=\"\$PATH:$BINDIR\""
;;
esac
cat <<EOF
Installé. Ensuite :
pvecli config init --endpoint https://pve.example:8006 \\
--token-id 'automation@pve!pvectl' --node pve
pvecli config trust # épingle le certificat — plus fort que --insecure
pvecli doctor # réseau → TLS → auth → nœud → privilèges
L'agent s'invoque depuis Claude Code : « crée-moi une VM 4 vCPU 16 Go ».
EOF