repowarden 4.9.3 → 4.10.0-next.4
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/README.md +3 -2
- package/bin/agents +103 -0
- package/bin/app +2 -2
- package/bin/bot +1 -1
- package/bin/bots +3 -3
- package/bin/code-mort +5 -3
- package/bin/commit +12 -15
- package/bin/garde +237 -0
- package/bin/migrer +4 -1
- package/bin/npm-publication +1 -1
- package/bin/pr-checks +2 -8
- package/bin/pr-label +6 -12
- package/bin/proteger +1 -1
- package/bin/repowarden +78 -5
- package/bin/run-list +2 -13
- package/bin/run-rerun +2 -15
- package/bin/statut +3 -2
- package/bin/ticket +26 -4
- package/bin/ticket-comment +7 -10
- package/bin/ticket-label +7 -14
- package/bin/tickets +3 -4
- package/hooks/agents/repowarden-garde.js +16 -0
- package/hooks/lang/node.sh +14 -2
- package/hooks/lang/python.sh +14 -2
- package/hooks/lib/common.sh +3 -1
- package/hooks/lib/deadcode.sh +46 -9
- package/hooks/lib/forge.sh +21 -0
- package/hooks/lib/i18n/en.sh +48 -0
- package/hooks/lib/i18n/fr.sh +49 -0
- package/hooks/pre-push +22 -0
- package/install.sh +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
- **Formatage** : seul le contenu stagé, avec l'outil du projet ; le travail en cours est préservé.
|
|
23
23
|
- **Tests** : au push et en CI, seulement les projets touchés, sur le commit poussé.
|
|
24
24
|
- **Code mort** : seul le nouveau code mort est signalé, prouvé (bloquant) ou candidat (à vérifier) ; `repowarden code-mort` en local.
|
|
25
|
+
- **Agents IA** : Claude Code et opencode arrêtés avant de modifier une branche protégée, de travailler hors ticket ou de contourner les hooks, avec la commande à lancer ; `repowarden agents init`.
|
|
25
26
|
- **Tickets** : chaque PR est reliée à un ticket validé (créé automatiquement s'il manque), suivi de « à valider » à « done » à la release ; `repowarden tickets init`.
|
|
26
27
|
- **Versions et releases** : les commits étant conventionnels, la version suivante (semver) et le changelog se déduisent de l'historique ; un workflow réutilisable en fait des releases automatiques (PR de release validée par la CI puis mergée, tag, release), sans jeton ; dans le flux `develop` → `main`, un clic d'approbation par livraison.
|
|
27
28
|
|
|
@@ -95,7 +96,7 @@ Sans Node : `git clone https://github.com/simdevWarden/repowarden.git ~/repoward
|
|
|
95
96
|
> [!NOTE]
|
|
96
97
|
> **GitHub CLI (`gh`) : facultatif.**
|
|
97
98
|
> Sans `gh` : tous les hooks (commits, branches, secrets, formatage, tests), `git cc`, `repowarden code-mort`, `repowarden statut`, et la CI (GitHub ou GitLab), qui n'utilise jamais le `gh` du poste.
|
|
98
|
-
> Avec `gh` connecté (`gh auth login`), en plus : les tickets (`repowarden ticket`, `tickets`, branches de tes tickets créées en local) et la gestion du dépôt (`proteger`, `app init`, `npm-publication`, `pr-*`, `run-*`). Utile au mainteneur du dépôt GitHub ; chaque commande le signale s'il manque.
|
|
99
|
+
> Avec `gh` connecté (`gh auth login -s workflow` : le scope `workflow` autorise la modification de `.github/workflows/`), en plus : les tickets (`repowarden ticket`, `tickets`, branches de tes tickets créées en local) et la gestion du dépôt (`proteger`, `app init`, `npm-publication`, `pr-*`, `run-*`). Utile au mainteneur du dépôt GitHub ; chaque commande le signale s'il manque.
|
|
99
100
|
|
|
100
101
|
### 2. Dans un projet d'équipe : les mêmes règles pour tous
|
|
101
102
|
|
|
@@ -164,6 +165,6 @@ Les PR visent `develop` ; `main` ne reçoit que les livraisons, qui déclenchent
|
|
|
164
165
|
|
|
165
166
|
## Liens
|
|
166
167
|
|
|
167
|
-
[Démarrage rapide](https://simdevwarden.github.io/repowarden/demarrage/) · [Hooks et règles](https://simdevwarden.github.io/repowarden/hooks/) · [Technologies](https://simdevwarden.github.io/repowarden/technologies/) · [Configuration](https://simdevwarden.github.io/repowarden/configuration/) · [CI](https://simdevwarden.github.io/repowarden/ci/) · [Versions et releases](https://simdevwarden.github.io/repowarden/releases/) · [Validation humaine](https://simdevwarden.github.io/repowarden/validation/) · [Code mort](https://simdevwarden.github.io/repowarden/code-mort/) · [En organisation](https://simdevwarden.github.io/repowarden/industrialisation/) · [Sources internes (Nexus, Artifactory)](https://simdevwarden.github.io/repowarden/industrialisation/#8-sources-internes-reseau-ferme-nexus-artifactory) · [Désinstallation](https://simdevwarden.github.io/repowarden/desinstallation/) · [Sécurité](SECURITY.md) · [Contribuer](CONTRIBUTING.md) · [Changelog](CHANGELOG.md)
|
|
168
|
+
[Démarrage rapide](https://simdevwarden.github.io/repowarden/demarrage/) · [Hooks et règles](https://simdevwarden.github.io/repowarden/hooks/) · [Technologies](https://simdevwarden.github.io/repowarden/technologies/) · [Configuration](https://simdevwarden.github.io/repowarden/configuration/) · [CI](https://simdevwarden.github.io/repowarden/ci/) · [Versions et releases](https://simdevwarden.github.io/repowarden/releases/) · [Validation humaine](https://simdevwarden.github.io/repowarden/validation/) · [Code mort](https://simdevwarden.github.io/repowarden/code-mort/) · [Agents IA](https://simdevwarden.github.io/repowarden/agents/) · [En organisation](https://simdevwarden.github.io/repowarden/industrialisation/) · [Sources internes (Nexus, Artifactory)](https://simdevwarden.github.io/repowarden/industrialisation/#8-sources-internes-reseau-ferme-nexus-artifactory) · [Désinstallation](https://simdevwarden.github.io/repowarden/desinstallation/) · [Sécurité](SECURITY.md) · [Contribuer](CONTRIBUTING.md) · [Changelog](CHANGELOG.md)
|
|
168
169
|
|
|
169
170
|
Licence [GPL-3.0-only](LICENSE) : GNU General Public License version 3.
|
package/bin/agents
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Branche le garde-fou repowarden (repowarden garde) dans les agents IA :
|
|
3
|
+
# repowarden agents init [--claude] [--opencode] [--projet | --global]
|
|
4
|
+
# Claude Code hook PreToolUse dans .claude/settings.json
|
|
5
|
+
# opencode plugin .opencode/plugins/repowarden-garde.js
|
|
6
|
+
# Sans --claude ni --opencode : les deux. --projet (défaut) : fichiers du dépôt,
|
|
7
|
+
# à versionner ; --global : configuration de l'utilisateur. Relançable :
|
|
8
|
+
# fichiers existants complétés, jamais écrasés.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
12
|
+
# shellcheck source=../hooks/lib/common.sh
|
|
13
|
+
source "$ROOT/hooks/lib/common.sh"
|
|
14
|
+
|
|
15
|
+
aide() { _tr help.agents; printf '%b\n' "$_T"; }
|
|
16
|
+
|
|
17
|
+
MODELE_OPENCODE="$ROOT/hooks/agents/repowarden-garde.js"
|
|
18
|
+
COMMANDE_CLAUDE="repowarden garde --format claude"
|
|
19
|
+
MATCHER_CLAUDE="Edit|Write|MultiEdit|NotebookEdit|Bash"
|
|
20
|
+
|
|
21
|
+
case "${1:-}" in
|
|
22
|
+
init) shift ;;
|
|
23
|
+
"" | -h | --help) aide; exit 0 ;;
|
|
24
|
+
*) err_t install.unknown_arg "$1"; aide >&2; exit 1 ;;
|
|
25
|
+
esac
|
|
26
|
+
|
|
27
|
+
claude="" opencode="" portee=projet
|
|
28
|
+
while [ $# -gt 0 ]; do
|
|
29
|
+
case "$1" in
|
|
30
|
+
--claude) claude=1 ;;
|
|
31
|
+
--opencode) opencode=1 ;;
|
|
32
|
+
--projet | --project) portee=projet ;;
|
|
33
|
+
--global) portee=global ;;
|
|
34
|
+
-h | --help) aide; exit 0 ;;
|
|
35
|
+
*) err_t install.unknown_arg "$1"; aide >&2; exit 1 ;;
|
|
36
|
+
esac
|
|
37
|
+
shift
|
|
38
|
+
done
|
|
39
|
+
[ -n "$claude$opencode" ] || claude=1 opencode=1
|
|
40
|
+
|
|
41
|
+
if [ "$portee" = projet ]; then
|
|
42
|
+
[ -n "$GIT_TOPLEVEL" ] || { err_t install.not_repo; exit 1; }
|
|
43
|
+
base="$GIT_TOPLEVEL"
|
|
44
|
+
fichier_claude="$base/.claude/settings.json"
|
|
45
|
+
fichier_opencode="$base/.opencode/plugins/repowarden-garde.js"
|
|
46
|
+
else
|
|
47
|
+
fichier_claude="$HOME/.claude/settings.json"
|
|
48
|
+
fichier_opencode="$HOME/.config/opencode/plugins/repowarden-garde.js"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
ecrits=()
|
|
52
|
+
|
|
53
|
+
# Hook PreToolUse de Claude Code : ajouté au settings.json (créé au besoin),
|
|
54
|
+
# rien si une commande « repowarden garde » y est déjà
|
|
55
|
+
init_claude() {
|
|
56
|
+
local f="$fichier_claude" entree tmp
|
|
57
|
+
has jq || { err_t agents.no_jq "$f"; return 1; }
|
|
58
|
+
entree="$(jq -n --arg m "$MATCHER_CLAUDE" --arg c "$COMMANDE_CLAUDE" \
|
|
59
|
+
'{matcher: $m, hooks: [{type: "command", command: $c}]}')"
|
|
60
|
+
if [ -f "$f" ]; then
|
|
61
|
+
jq -e . "$f" >/dev/null 2>&1 || { err_t agents.bad_json "Claude Code" "$f"; return 1; }
|
|
62
|
+
if jq -e '[.hooks.PreToolUse[]?.hooks[]?.command // empty | select(test("repowarden garde"))] | length > 0' "$f" >/dev/null; then
|
|
63
|
+
ok_t agents.present "Claude Code" "$f"
|
|
64
|
+
return 0
|
|
65
|
+
fi
|
|
66
|
+
tmp="$(mktemp)"
|
|
67
|
+
jq --argjson e "$entree" '.hooks.PreToolUse = ((.hooks.PreToolUse // []) + [$e])' "$f" >"$tmp"
|
|
68
|
+
cat "$tmp" >"$f"
|
|
69
|
+
rm -f "$tmp"
|
|
70
|
+
else
|
|
71
|
+
mkdir -p "$(dirname "$f")"
|
|
72
|
+
jq -n --argjson e "$entree" '{hooks: {PreToolUse: [$e]}}' >"$f"
|
|
73
|
+
fi
|
|
74
|
+
ecrits+=("$f")
|
|
75
|
+
ok_t agents.added "Claude Code" "$f"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Plugin opencode : copie du modèle ; un fichier différent est gardé et signalé
|
|
79
|
+
init_opencode() {
|
|
80
|
+
local f="$fichier_opencode"
|
|
81
|
+
if [ -f "$f" ]; then
|
|
82
|
+
if cmp -s "$f" "$MODELE_OPENCODE"; then
|
|
83
|
+
ok_t agents.present opencode "$f"
|
|
84
|
+
else
|
|
85
|
+
attention_t agents.kept opencode "$f" "$MODELE_OPENCODE"
|
|
86
|
+
fi
|
|
87
|
+
return 0
|
|
88
|
+
fi
|
|
89
|
+
mkdir -p "$(dirname "$f")"
|
|
90
|
+
cp "$MODELE_OPENCODE" "$f"
|
|
91
|
+
ecrits+=("$f")
|
|
92
|
+
ok_t agents.added opencode "$f"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
statut=0
|
|
96
|
+
[ -z "$claude" ] || init_claude || statut=1
|
|
97
|
+
[ -z "$opencode" ] || init_opencode || statut=1
|
|
98
|
+
|
|
99
|
+
has repowarden || attention_t agents.no_repowarden
|
|
100
|
+
if [ "$portee" = projet ] && [ ${#ecrits[@]} -gt 0 ]; then
|
|
101
|
+
info_t agents.versionner "${ecrits[*]#"$base/"}"
|
|
102
|
+
fi
|
|
103
|
+
exit "$statut"
|
package/bin/app
CHANGED
|
@@ -23,7 +23,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
|
23
23
|
# shellcheck source=../hooks/lib/common.sh
|
|
24
24
|
source "$ROOT/hooks/lib/common.sh"
|
|
25
25
|
|
|
26
|
-
aide() {
|
|
26
|
+
aide() { _tr help.app; printf '%b\n' "$_T" >&2; }
|
|
27
27
|
|
|
28
28
|
commande="${1:-}"
|
|
29
29
|
[ $# -eq 0 ] || shift
|
|
@@ -45,7 +45,7 @@ if [ "$commande" != init ]; then
|
|
|
45
45
|
exit
|
|
46
46
|
fi
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
gh_ready || exit 1
|
|
49
49
|
command -v node >/dev/null || { err_t app.no_node; exit 1; }
|
|
50
50
|
[ -n "$REPO" ] || REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
|
|
51
51
|
owner="${REPO%%/*}"
|
package/bin/bot
CHANGED
|
@@ -16,7 +16,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
|
16
16
|
# shellcheck source=../hooks/lib/common.sh
|
|
17
17
|
source "$ROOT/hooks/lib/common.sh"
|
|
18
18
|
|
|
19
|
-
aide() {
|
|
19
|
+
aide() { _tr help.bot; printf '%b\n' "$_T" >&2; }
|
|
20
20
|
|
|
21
21
|
# Scripts appelés (remplaçables dans les tests) et origine des clones
|
|
22
22
|
BIN="${REPOWARDEN_BIN:-$ROOT/bin}"
|
package/bin/bots
CHANGED
|
@@ -20,7 +20,7 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
20
20
|
# shellcheck source=../hooks/lib/lang.sh
|
|
21
21
|
source "$ROOT/hooks/lib/lang.sh"
|
|
22
22
|
|
|
23
|
-
aide() {
|
|
23
|
+
aide() { _tr help.bots; printf '%b\n' "$_T" >&2; }
|
|
24
24
|
|
|
25
25
|
# Commandes enchaînées (remplaçables dans les tests)
|
|
26
26
|
BIN="${REPOWARDEN_BIN:-$ROOT/bin}"
|
|
@@ -48,8 +48,8 @@ fi
|
|
|
48
48
|
[ -n "$GIT_TOPLEVEL" ] || pas_maintenant bots.why_repo
|
|
49
49
|
cd "$GIT_TOPLEVEL"
|
|
50
50
|
[ "$FORGE" = github ] || pas_maintenant bots.why_github
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
gh_present || pas_maintenant bots.why_gh
|
|
52
|
+
gh_connected || pas_maintenant bots.why_gh_login
|
|
53
53
|
REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || true)"
|
|
54
54
|
[ -n "$REPO" ] || pas_maintenant bots.why_github
|
|
55
55
|
[ "$(gh api "repos/$REPO" --jq .permissions.admin 2>/dev/null || true)" = true ] || pas_maintenant bots.why_admin
|
package/bin/code-mort
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# Usage : repowarden code-mort [base]
|
|
3
|
+
#
|
|
4
|
+
# Code mort introduit par ta branche, comme en CI : seules les lignes ajoutées
|
|
5
|
+
# ou modifiées depuis la base comptent (commits, modifications en cours,
|
|
6
|
+
# nouveaux fichiers). Défaut : point de départ de la branche depuis origin/main.
|
|
5
7
|
# Voir docs/code-mort.md : ce qui est prouvé (bloquant) et ce qui est candidat.
|
|
6
8
|
set -euo pipefail
|
|
7
9
|
|
package/bin/commit
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# Les réponses sont lues sur l'entrée standard (terminal avec édition de
|
|
15
|
-
# ligne, ou fichier/tube pour les tests). Le commit passe ensuite par les
|
|
16
|
-
# hooks habituels. Couleurs désactivables : NO_COLOR=1.
|
|
2
|
+
# Usage : repowarden cc [options de git commit] (alias : git cc, installé par install.sh)
|
|
3
|
+
# repowarden cc -m "description" [--type T] [--scope S] [--breaking NOTE] [--body TEXTE] [--refs "Ticket : #12"]
|
|
4
|
+
# repowarden cc --dry-run
|
|
5
|
+
#
|
|
6
|
+
# Assistant de commit conventionnel : guide l'en-tête, le corps et le pied,
|
|
7
|
+
# puis commit via les hooks habituels. Sans question (-m : scripts, agents) :
|
|
8
|
+
# mêmes contrôles, type et scope déduits de la branche s'ils sont omis.
|
|
9
|
+
# --strict une réponse refusée arrête tout (rien n'est commité)
|
|
10
|
+
# --dry-run affiche le message sans commiter
|
|
11
|
+
# Les réponses sont lues sur l'entrée standard (terminal avec édition de ligne,
|
|
12
|
+
# ou fichier/tube pour les tests). Le commit passe ensuite par les hooks
|
|
13
|
+
# habituels. Couleurs désactivables : NO_COLOR=1.
|
|
17
14
|
set -euo pipefail
|
|
18
15
|
|
|
19
16
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
package/bin/garde
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Garde-fou des agents IA : reçoit sur l'entrée standard une action d'agent
|
|
3
|
+
# (JSON) et dit si elle est permise dans ce dépôt, avant qu'elle ne s'exécute.
|
|
4
|
+
# repowarden garde [--format claude|opencode]
|
|
5
|
+
# claude hook PreToolUse de Claude Code : tool_name, tool_input, cwd
|
|
6
|
+
# opencode plugin opencode (tool.execute.before) : tool, args, cwd (défaut)
|
|
7
|
+
# Code 0 : permis. Code 2 : refusé, raison et commande à lancer sur la sortie
|
|
8
|
+
# d'erreur (Claude Code bloque l'appel et transmet le message à l'agent ; le
|
|
9
|
+
# plugin opencode lève une erreur). Tout autre code (jq absent, JSON illisible)
|
|
10
|
+
# n'empêche rien : une panne du garde-fou ne bloque jamais un agent.
|
|
11
|
+
# Seulement dans un dépôt repowarden ; ailleurs tout est permis. Mêmes réglages
|
|
12
|
+
# que les hooks (protectedBranches, integrationBranch, suivi des tickets).
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
|
|
15
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
16
|
+
# shellcheck source=../hooks/lib/common.sh
|
|
17
|
+
source "$ROOT/hooks/lib/common.sh"
|
|
18
|
+
# shellcheck source=../hooks/lib/tickets.sh
|
|
19
|
+
source "$ROOT/hooks/lib/tickets.sh"
|
|
20
|
+
|
|
21
|
+
aide() { _tr help.garde; printf '%b\n' "$_T"; }
|
|
22
|
+
|
|
23
|
+
format=opencode
|
|
24
|
+
while [ $# -gt 0 ]; do
|
|
25
|
+
case "$1" in
|
|
26
|
+
-h | --help) aide; exit 0 ;;
|
|
27
|
+
--format) shift; format="${1:-}" ;;
|
|
28
|
+
--format=*) format="${1#--format=}" ;;
|
|
29
|
+
*) err_t install.unknown_arg "$1"; aide >&2; exit 1 ;;
|
|
30
|
+
esac
|
|
31
|
+
shift
|
|
32
|
+
done
|
|
33
|
+
case "$format" in claude | opencode) ;; *) err_t garde.format "$format"; exit 1 ;; esac
|
|
34
|
+
|
|
35
|
+
has jq || { attention_t garde.no_jq; exit 1; }
|
|
36
|
+
entree="$(cat)"
|
|
37
|
+
if [ "$format" = claude ]; then o=tool_name a=tool_input; else o=tool a=args; fi
|
|
38
|
+
outil="$(jq -r ".$o // \"\"" <<<"$entree" 2>/dev/null)" || { attention_t garde.json; exit 1; }
|
|
39
|
+
cwd="$(jq -r '.cwd // ""' <<<"$entree")"
|
|
40
|
+
args="$(jq -c ".$a // {}" <<<"$entree")"
|
|
41
|
+
[ -n "$cwd" ] && [ -d "$cwd" ] || cwd="$PWD"
|
|
42
|
+
|
|
43
|
+
# Refus : raison et commande à lancer, puis code 2
|
|
44
|
+
refuser() {
|
|
45
|
+
_tr "$@"
|
|
46
|
+
printf '✖ repowarden : %b\n' "$_T" >&2
|
|
47
|
+
exit 2
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# REPLY = dossier existant le plus proche du chemin $1 (absolu, ou relatif à $cwd)
|
|
51
|
+
dossier_r() {
|
|
52
|
+
local p="$1"
|
|
53
|
+
case "$p" in /*) ;; *) p="$cwd/$p" ;; esac
|
|
54
|
+
while [ ! -d "$p" ] && [ "$p" != / ] && [ -n "$p" ]; do p="$(dirname "$p")"; done
|
|
55
|
+
REPLY="$p"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Vrai si le dossier courant est dans un dépôt repowarden : .repowarden.conf,
|
|
59
|
+
# réglage repowarden.*, ou hooks repowarden actifs. Charge sa configuration.
|
|
60
|
+
depot_repowarden() {
|
|
61
|
+
local hp
|
|
62
|
+
git rev-parse --show-toplevel >/dev/null 2>&1 || return 1
|
|
63
|
+
cfg_load
|
|
64
|
+
i18n_init
|
|
65
|
+
# shellcheck disable=SC2034 # cache de tickets_managed (tickets.sh), propre à ce dépôt
|
|
66
|
+
TICKETS_MANAGED=""
|
|
67
|
+
[ -n "$CFG_FILE$CFG_GIT" ] && return 0
|
|
68
|
+
hp="$(git config --get core.hooksPath 2>/dev/null || true)"
|
|
69
|
+
[ -n "$hp" ] && [ -f "$hp/lib/tickets.sh" ] && [ -f "$hp/lib/common.sh" ]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Branche protégée : protectedBranches (défaut main master) ou branche d'intégration
|
|
73
|
+
protegee() {
|
|
74
|
+
cfg_r protectedBranches "main master"
|
|
75
|
+
[[ " $REPLY " == *" $1 "* ]] && return 0
|
|
76
|
+
cfg_r integrationBranch ""
|
|
77
|
+
[ -n "$REPLY" ] && [ "$REPLY" = "$1" ]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Modification du fichier $1 : seulement sur une branche de travail (de ticket,
|
|
81
|
+
# si le dépôt suit ses tickets)
|
|
82
|
+
verifier_fichier() {
|
|
83
|
+
dossier_r "$1"
|
|
84
|
+
local d="$REPLY"
|
|
85
|
+
(
|
|
86
|
+
cd "$d" 2>/dev/null || exit 0
|
|
87
|
+
depot_repowarden || exit 0
|
|
88
|
+
# Fichiers internes de git (.git/…) : hors du travail de l'agent
|
|
89
|
+
case "$(pwd -P)/" in "$(cd "$(git rev-parse --git-dir)" && pwd -P)"/*) exit 0 ;; esac
|
|
90
|
+
branche="$(git symbolic-ref -q --short HEAD 2>/dev/null || true)"
|
|
91
|
+
[ -n "$branche" ] || refuser garde.detache "$GIT_TOPLEVEL"
|
|
92
|
+
if protegee "$branche"; then
|
|
93
|
+
tickets_managed && refuser garde.protegee "$branche"
|
|
94
|
+
refuser garde.protegee_libre "$branche"
|
|
95
|
+
fi
|
|
96
|
+
if tickets_managed; then
|
|
97
|
+
branch_ticket_r "$branche"
|
|
98
|
+
[ -n "$REPLY" ] || refuser garde.hors_ticket "$branche"
|
|
99
|
+
fi
|
|
100
|
+
exit 0
|
|
101
|
+
) || exit $?
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Commande git (mots $@, sans « git ») lancée depuis le dossier $dir
|
|
105
|
+
verifier_git() {
|
|
106
|
+
local mot sous="" args_git=() repertoire="$dir"
|
|
107
|
+
# Options globales : -C <dossier> (cumulées), -c <clé=valeur>, autres
|
|
108
|
+
while [ $# -gt 0 ]; do
|
|
109
|
+
case "$1" in
|
|
110
|
+
-C) shift; case "${1:-}" in /*) repertoire="$1" ;; *) repertoire="$repertoire/${1:-}" ;; esac ;;
|
|
111
|
+
-c) shift ;;
|
|
112
|
+
-*) ;;
|
|
113
|
+
*) sous="$1"; shift; break ;;
|
|
114
|
+
esac
|
|
115
|
+
shift
|
|
116
|
+
done
|
|
117
|
+
[ -n "$sous" ] || return 0
|
|
118
|
+
args_git=("$@")
|
|
119
|
+
dossier_r "$repertoire"
|
|
120
|
+
repertoire="$REPLY"
|
|
121
|
+
(
|
|
122
|
+
cd "$repertoire" 2>/dev/null || exit 0
|
|
123
|
+
depot_repowarden || exit 0
|
|
124
|
+
ligne="git $sous${args_git[*]+ ${args_git[*]}}"
|
|
125
|
+
for mot in ${args_git[@]+"${args_git[@]}"}; do
|
|
126
|
+
[ "$mot" != --no-verify ] || refuser garde.no_verify "$ligne"
|
|
127
|
+
done
|
|
128
|
+
case "$sous" in
|
|
129
|
+
commit)
|
|
130
|
+
amend="" noedit=""
|
|
131
|
+
for mot in ${args_git[@]+"${args_git[@]}"}; do
|
|
132
|
+
case "$mot" in
|
|
133
|
+
--amend) amend=1 ;;
|
|
134
|
+
--no-edit) noedit=1 ;;
|
|
135
|
+
# Options courtes groupées : -n est --no-verify (-nm, -an…)
|
|
136
|
+
-[!-]*) [[ "$mot" != *n* ]] || refuser garde.no_verify "$ligne" ;;
|
|
137
|
+
esac
|
|
138
|
+
done
|
|
139
|
+
[ -n "$amend" ] && [ -n "$noedit" ] && exit 0
|
|
140
|
+
refuser garde.commit "$ligne"
|
|
141
|
+
;;
|
|
142
|
+
add)
|
|
143
|
+
for mot in ${args_git[@]+"${args_git[@]}"}; do
|
|
144
|
+
case "$mot" in
|
|
145
|
+
. | ./ | --all | :/) refuser garde.add_tout "$ligne" ;;
|
|
146
|
+
-[!-]*) [[ "$mot" != *A* ]] || refuser garde.add_tout "$ligne" ;;
|
|
147
|
+
esac
|
|
148
|
+
done
|
|
149
|
+
;;
|
|
150
|
+
checkout | switch | branch | worktree)
|
|
151
|
+
tickets_managed || exit 0
|
|
152
|
+
cree=""
|
|
153
|
+
case "$sous" in
|
|
154
|
+
checkout) for mot in ${args_git[@]+"${args_git[@]}"}; do case "$mot" in -b | -B | --orphan) cree=1 ;; esac; done ;;
|
|
155
|
+
switch) for mot in ${args_git[@]+"${args_git[@]}"}; do case "$mot" in -c | -C | --create | --force-create | --orphan | --create=* | --force-create=*) cree=1 ;; esac; done ;;
|
|
156
|
+
worktree)
|
|
157
|
+
[ "${args_git[0]:-}" = add ] || exit 0
|
|
158
|
+
for mot in ${args_git[@]+"${args_git[@]}"}; do case "$mot" in -b | -B) cree=1 ;; esac; done
|
|
159
|
+
;;
|
|
160
|
+
branch)
|
|
161
|
+
nom=""
|
|
162
|
+
for mot in ${args_git[@]+"${args_git[@]}"}; do
|
|
163
|
+
case "$mot" in
|
|
164
|
+
-d | -D | --delete | -m | -M | --move | -c | -C | --copy | -l | --list | -a | --all | -r | --remotes | \
|
|
165
|
+
-v | -vv | --verbose | --show-current | --contains | --no-contains | --merged | --no-merged | \
|
|
166
|
+
-u | --set-upstream-to | --set-upstream-to=* | --unset-upstream | --edit-description | --points-at) exit 0 ;;
|
|
167
|
+
-*) ;;
|
|
168
|
+
*) nom="$mot" ;;
|
|
169
|
+
esac
|
|
170
|
+
done
|
|
171
|
+
[ -z "$nom" ] || cree=1
|
|
172
|
+
;;
|
|
173
|
+
esac
|
|
174
|
+
[ -z "$cree" ] || refuser garde.branche "$ligne"
|
|
175
|
+
;;
|
|
176
|
+
esac
|
|
177
|
+
exit 0
|
|
178
|
+
) || exit $?
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# Ligne de commande shell : chaque commande (&&, ||, ;, |, retour à la ligne),
|
|
182
|
+
# « cd » suivi, variables d'environnement en tête ignorées
|
|
183
|
+
verifier_shell() {
|
|
184
|
+
local commande="$1" segment mots m nl=$'\n' lignes
|
|
185
|
+
dir="$cwd"
|
|
186
|
+
# Une commande par ligne. Découpage hors de <( … ) : bash 3.2 (macOS) y
|
|
187
|
+
# lit mal ces motifs (« bad substitution ») et ne vérifierait plus rien
|
|
188
|
+
lignes="${commande//&&/$nl}"
|
|
189
|
+
lignes="${lignes//||/$nl}"
|
|
190
|
+
lignes="${lignes//;/$nl}"
|
|
191
|
+
lignes="${lignes//|/$nl}"
|
|
192
|
+
lignes="${lignes//&/$nl}"
|
|
193
|
+
while IFS= read -r segment; do
|
|
194
|
+
# shellcheck disable=SC2162 # les antislashs restent tels quels, comme dans la commande
|
|
195
|
+
read -a mots <<<"$segment" || true
|
|
196
|
+
set -- ${mots[@]+"${mots[@]}"}
|
|
197
|
+
while [ $# -gt 0 ]; do
|
|
198
|
+
case "$1" in
|
|
199
|
+
[A-Za-z_]*=* | '(' | '{' | '!' | command | exec | env | sudo | time | nohup) shift ;;
|
|
200
|
+
*) break ;;
|
|
201
|
+
esac
|
|
202
|
+
done
|
|
203
|
+
[ $# -gt 0 ] || continue
|
|
204
|
+
m="${1//[\"\']/}"
|
|
205
|
+
case "$m" in
|
|
206
|
+
cd)
|
|
207
|
+
case "${2:-}" in
|
|
208
|
+
"" | \~) dir="$HOME" ;;
|
|
209
|
+
/*) dir="${2//[\"\']/}" ;;
|
|
210
|
+
\~/*) dir="$HOME/${2#\~/}" ;;
|
|
211
|
+
*) dir="$dir/${2//[\"\']/}" ;;
|
|
212
|
+
esac
|
|
213
|
+
;;
|
|
214
|
+
git | */git)
|
|
215
|
+
shift
|
|
216
|
+
verifier_git "${@//[\"\']/}"
|
|
217
|
+
;;
|
|
218
|
+
esac
|
|
219
|
+
done <<<"$lignes"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
case "$outil" in
|
|
223
|
+
Edit | Write | MultiEdit | NotebookEdit | edit | write | multiedit)
|
|
224
|
+
chemin="$(jq -r '.file_path // .filePath // .notebook_path // empty' <<<"$args" 2>/dev/null)"
|
|
225
|
+
[ -z "$chemin" ] || verifier_fichier "$chemin"
|
|
226
|
+
;;
|
|
227
|
+
apply_patch)
|
|
228
|
+
while IFS= read -r chemin; do
|
|
229
|
+
[ -z "$chemin" ] || verifier_fichier "$chemin"
|
|
230
|
+
done < <(jq -r '.patchText // empty' <<<"$args" 2>/dev/null |
|
|
231
|
+
sed -nE -e 's/^\*\*\* (Add|Update|Delete) File: //p' -e 's/^\*\*\* Move to: //p')
|
|
232
|
+
;;
|
|
233
|
+
Bash | bash)
|
|
234
|
+
verifier_shell "$(jq -r '.command // empty' <<<"$args" 2>/dev/null)"
|
|
235
|
+
;;
|
|
236
|
+
esac
|
|
237
|
+
exit 0
|
package/bin/migrer
CHANGED
|
@@ -14,7 +14,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
|
14
14
|
# shellcheck source=../hooks/lib/common.sh
|
|
15
15
|
source "$ROOT/hooks/lib/common.sh"
|
|
16
16
|
|
|
17
|
-
aide() {
|
|
17
|
+
aide() { _tr help.migrer; printf '%b\n' "$_T" >&2; }
|
|
18
18
|
|
|
19
19
|
PR="" HOOKS_LEFTHOOK=""
|
|
20
20
|
while [ $# -gt 0 ]; do
|
|
@@ -35,6 +35,8 @@ majeure_r() {
|
|
|
35
35
|
local v
|
|
36
36
|
repowarden_version_r "$ROOT"
|
|
37
37
|
v="$REPLY"
|
|
38
|
+
# 0.0.0-dev : version inconnue (clone sans tags), rien à déduire
|
|
39
|
+
if [ "$v" = 0.0.0-dev ]; then REPLY=""; return; fi
|
|
38
40
|
REPLY="${v%%.*}"
|
|
39
41
|
REPLY="${REPLY%%-*}"
|
|
40
42
|
[[ "$v" != *.0.0-* ]] || REPLY=$((REPLY - 1))
|
|
@@ -45,6 +47,7 @@ else
|
|
|
45
47
|
majeure_r
|
|
46
48
|
MAJEURE="$REPLY"
|
|
47
49
|
fi
|
|
50
|
+
[ -n "$MAJEURE" ] || { err_t mig.unknown_version "$ROOT"; exit 1; }
|
|
48
51
|
[[ "$MAJEURE" =~ ^[1-9][0-9]*$ ]] || { err_t mig.no_major "$MAJEURE"; exit 1; }
|
|
49
52
|
BRANCHE="chore/migration-repowarden-v$MAJEURE"
|
|
50
53
|
|
package/bin/npm-publication
CHANGED
|
@@ -31,7 +31,7 @@ while [ $# -gt 0 ]; do
|
|
|
31
31
|
--workflow) shift; WORKFLOW="${1:?--workflow attend un fichier}" ;;
|
|
32
32
|
--environnement | --environment) shift; ENVIRONMENT="${1:?--environnement attend un nom}" ;;
|
|
33
33
|
--dry-run) DRY_RUN=true ;;
|
|
34
|
-
-h | --help)
|
|
34
|
+
-h | --help) _tr help.npm-publication; printf '%b\n' "$_T"; exit 0 ;;
|
|
35
35
|
*) err_t install.unknown_arg "$1"; exit 1 ;;
|
|
36
36
|
esac
|
|
37
37
|
shift
|
package/bin/pr-checks
CHANGED
|
@@ -10,14 +10,8 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
10
10
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
11
11
|
|
|
12
12
|
aide() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Affiche l'état des checks de la PR #<n>.
|
|
17
|
-
|
|
18
|
-
Exemple:
|
|
19
|
-
repowarden pr checks 123
|
|
20
|
-
EOF
|
|
13
|
+
_tr help.pr
|
|
14
|
+
printf '%b\n' "$_T"
|
|
21
15
|
}
|
|
22
16
|
|
|
23
17
|
[ $# -eq 1 ] || { aide >&2; exit 1; }
|
package/bin/pr-label
CHANGED
|
@@ -10,20 +10,14 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
10
10
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
11
11
|
|
|
12
12
|
aide() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Ajoute ou retire un label sur la PR #<n>.
|
|
17
|
-
|
|
18
|
-
Options:
|
|
19
|
-
--remove Retire le label au lieu de l'ajouter
|
|
20
|
-
|
|
21
|
-
Exemples:
|
|
22
|
-
repowarden pr label 123 "ready-for-review"
|
|
23
|
-
repowarden pr label 123 "needs-changes" --remove
|
|
24
|
-
EOF
|
|
13
|
+
_tr help.pr
|
|
14
|
+
printf '%b\n' "$_T"
|
|
25
15
|
}
|
|
26
16
|
|
|
17
|
+
case "${1:-}" in
|
|
18
|
+
-h | --help) aide; exit 0 ;;
|
|
19
|
+
esac
|
|
20
|
+
|
|
27
21
|
[ $# -ge 2 ] || { aide >&2; exit 1; }
|
|
28
22
|
command -v gh >/dev/null || { err_t bot.no_gh; exit 1; }
|
|
29
23
|
|
package/bin/proteger
CHANGED
|
@@ -56,7 +56,7 @@ while [ $# -gt 0 ]; do
|
|
|
56
56
|
--sans-tags) NO_TAGS=1 ;;
|
|
57
57
|
--dry-run) DRY_RUN=1 ;;
|
|
58
58
|
--verifier) VERIFY=1 ;;
|
|
59
|
-
-h | --help)
|
|
59
|
+
-h | --help) _tr help.proteger; printf '%b\n' "$_T"; exit 0 ;;
|
|
60
60
|
*) err_t install.unknown_arg "$1"; exit 1 ;;
|
|
61
61
|
esac
|
|
62
62
|
shift
|