repowarden 4.7.1 → 4.8.0-next.12
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 +5 -1
- package/bin/app +24 -10
- package/bin/bot +231 -0
- package/bin/bots +370 -0
- package/bin/migrer +205 -0
- package/bin/npm-publication +134 -5
- package/bin/proteger +126 -5
- package/bin/repowarden +7 -1
- package/bin/statut +12 -0
- package/bin/tickets +5 -7
- package/hooks/lib/i18n/en.sh +134 -2
- package/hooks/lib/i18n/fr.sh +134 -2
- package/install.sh +19 -1
- package/package.json +1 -1
package/bin/npm-publication
CHANGED
|
@@ -24,11 +24,13 @@ source "$ROOT/hooks/lib/common.sh"
|
|
|
24
24
|
REPO=""
|
|
25
25
|
WORKFLOW="release.yml"
|
|
26
26
|
ENVIRONMENT=""
|
|
27
|
+
DRY_RUN=false
|
|
27
28
|
while [ $# -gt 0 ]; do
|
|
28
29
|
case "$1" in
|
|
29
30
|
--repo) shift; REPO="${1:?--repo attend propriétaire/nom}" ;;
|
|
30
31
|
--workflow) shift; WORKFLOW="${1:?--workflow attend un fichier}" ;;
|
|
31
32
|
--environnement | --environment) shift; ENVIRONMENT="${1:?--environnement attend un nom}" ;;
|
|
33
|
+
--dry-run) DRY_RUN=true ;;
|
|
32
34
|
-h | --help) sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
|
33
35
|
*) err_t install.unknown_arg "$1"; exit 1 ;;
|
|
34
36
|
esac
|
|
@@ -50,6 +52,67 @@ name="$(node -p 'require("./package.json").name')"
|
|
|
50
52
|
# les doublons, y compris celui d'une tentative interrompue) ; tous révoqués à la fin
|
|
51
53
|
TOKEN_PREFIX="repowarden-ci-${REPO##*/}"
|
|
52
54
|
|
|
55
|
+
# Vérifie si une relation de confiance correspond aux paramètres attendus.
|
|
56
|
+
# Affiche l'écart si --dry-run ou pour confirmation.
|
|
57
|
+
# Retourne : 0 = match, 1 = pas de relation, 2 = relation différente
|
|
58
|
+
verifier_trust() {
|
|
59
|
+
local json attendu_repo="$REPO" attendu_file="$WORKFLOW" attendu_env="$ENVIRONMENT"
|
|
60
|
+
json="$(npm trust list "$name" --json 2>/dev/null || echo '[]')"
|
|
61
|
+
if [ "$json" = "[]" ] || [ -z "$json" ]; then
|
|
62
|
+
return 1
|
|
63
|
+
fi
|
|
64
|
+
local match=0 id repo file env allow_publish
|
|
65
|
+
while IFS=$'\t' read -r id repo file env allow_publish; do
|
|
66
|
+
[ -n "$id" ] || continue
|
|
67
|
+
if [ "$repo" = "$attendu_repo" ] && [ "$file" = "$attendu_file" ] && [ "$env" = "$attendu_env" ] && [ "$allow_publish" = "true" ]; then
|
|
68
|
+
match=1
|
|
69
|
+
break
|
|
70
|
+
fi
|
|
71
|
+
done < <(node -e "
|
|
72
|
+
const data = $json;
|
|
73
|
+
for (const t of data) {
|
|
74
|
+
const id = t.id || t.key;
|
|
75
|
+
const repo = t.repository || t.repo || '';
|
|
76
|
+
const file = t.file || t.workflow || '';
|
|
77
|
+
const env = t.environment || t.env || '';
|
|
78
|
+
const allowPublish = t.allowPublish === true || t['allow-publish'] === true;
|
|
79
|
+
console.log(id + '\t' + repo + '\t' + file + '\t' + env + '\t' + allowPublish);
|
|
80
|
+
}
|
|
81
|
+
")
|
|
82
|
+
if [ "$match" = 1 ]; then
|
|
83
|
+
return 0
|
|
84
|
+
fi
|
|
85
|
+
return 2
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Affiche les détails d'une relation de confiance pour diagnostic
|
|
89
|
+
afficher_trust() {
|
|
90
|
+
local json
|
|
91
|
+
json="$(npm trust list "$name" --json 2>/dev/null || echo '[]')"
|
|
92
|
+
if [ "$json" = "[]" ] || [ -z "$json" ]; then
|
|
93
|
+
echo " (aucune relation de confiance)"
|
|
94
|
+
return
|
|
95
|
+
fi
|
|
96
|
+
node -e "
|
|
97
|
+
const data = $json;
|
|
98
|
+
for (const t of data) {
|
|
99
|
+
const id = t.id || t.key;
|
|
100
|
+
const repo = t.repository || t.repo || '(inconnu)';
|
|
101
|
+
const file = t.file || t.workflow || '(inconnu)';
|
|
102
|
+
const env = t.environment || t.env || '(aucun)';
|
|
103
|
+
const allowPublish = t.allowPublish === true || t['allow-publish'] === true;
|
|
104
|
+
const allowStagePublish = t.allowStagePublish === true || t['allow-stage-publish'] === true;
|
|
105
|
+
console.log(' ID: ' + id);
|
|
106
|
+
console.log(' Dépôt: ' + repo);
|
|
107
|
+
console.log(' Workflow: ' + file);
|
|
108
|
+
console.log(' Environnement: ' + env);
|
|
109
|
+
console.log(' npm publish: ' + (allowPublish ? 'oui' : 'non'));
|
|
110
|
+
console.log(' npm stage publish: ' + (allowStagePublish ? 'oui' : 'non'));
|
|
111
|
+
console.log('');
|
|
112
|
+
}
|
|
113
|
+
"
|
|
114
|
+
}
|
|
115
|
+
|
|
53
116
|
brand "npm · $name · $REPO"
|
|
54
117
|
|
|
55
118
|
# 1. Connexion npm : entre toi et npm (navigateur ou mot de passe)
|
|
@@ -127,16 +190,82 @@ fi
|
|
|
127
190
|
|
|
128
191
|
# 3. Publication de confiance, puis plus aucun jeton
|
|
129
192
|
step_t npm.step_trust
|
|
130
|
-
|
|
193
|
+
verifier_trust
|
|
194
|
+
cas=$?
|
|
195
|
+
if [ "$cas" = 0 ]; then
|
|
131
196
|
ok_t npm.trust_exists
|
|
197
|
+
elif [ "$cas" = 1 ]; then
|
|
198
|
+
# Aucune relation : créer
|
|
199
|
+
if [ "$DRY_RUN" = true ]; then
|
|
200
|
+
info_t npm.trust_would_create "$REPO" "$WORKFLOW" "${ENVIRONMENT:-(aucun)}"
|
|
201
|
+
else
|
|
202
|
+
npm trust github "$name" --file "$WORKFLOW" --repo "$REPO" ${ENVIRONMENT:+--env "$ENVIRONMENT"} --allow-publish --yes
|
|
203
|
+
ok_t npm.trust_set "$REPO" "$WORKFLOW"
|
|
204
|
+
fi
|
|
132
205
|
else
|
|
133
|
-
|
|
134
|
-
|
|
206
|
+
# Relation différente : afficher l'écart, demander confirmation, corriger sans perte
|
|
207
|
+
attention_t npm.trust_mismatch
|
|
208
|
+
afficher_trust
|
|
209
|
+
echo " Attendu :"
|
|
210
|
+
echo " Dépôt: $REPO"
|
|
211
|
+
echo " Workflow: $WORKFLOW"
|
|
212
|
+
echo " Environnement: ${ENVIRONMENT:-(aucun)}"
|
|
213
|
+
echo " npm publish: oui"
|
|
214
|
+
echo ""
|
|
215
|
+
if [ "$DRY_RUN" = true ]; then
|
|
216
|
+
info_t npm.trust_would_fix
|
|
217
|
+
else
|
|
218
|
+
# Confirmation avant changement
|
|
219
|
+
if [ -t 0 ]; then
|
|
220
|
+
t npm.trust_confirm
|
|
221
|
+
read -r -p " $REPLY" rep
|
|
222
|
+
echo
|
|
223
|
+
[[ "$rep" =~ ^[OoYy]$ ]] || { err_t npm.trust_cancelled; exit 1; }
|
|
224
|
+
fi
|
|
225
|
+
# Créer la nouvelle relation AVANT de révoquer l'ancienne (pas de perte)
|
|
226
|
+
npm trust github "$name" --file "$WORKFLOW" --repo "$REPO" ${ENVIRONMENT:+--env "$ENVIRONMENT"} --allow-publish --yes
|
|
227
|
+
ok_t npm.trust_set "$REPO" "$WORKFLOW"
|
|
228
|
+
# Révoquer l'ancienne relation
|
|
229
|
+
json="$(npm trust list "$name" --json 2>/dev/null || echo '[]')"
|
|
230
|
+
old_id="$(node -e "
|
|
231
|
+
const data = $json;
|
|
232
|
+
for (const t of data) {
|
|
233
|
+
const id = t.id || t.key;
|
|
234
|
+
const repo = t.repository || t.repo || '';
|
|
235
|
+
const file = t.file || t.workflow || '';
|
|
236
|
+
const env = t.environment || t.env || '';
|
|
237
|
+
const allowPublish = t.allowPublish === true || t['allow-publish'] === true;
|
|
238
|
+
if (repo !== '$REPO' || file !== '$WORKFLOW' || env !== '$ENVIRONMENT' || allowPublish !== true) {
|
|
239
|
+
console.log(id);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
")"
|
|
243
|
+
for id in $old_id; do
|
|
244
|
+
[ -n "$id" ] && npm trust revoke "$name" --id "$id" --yes && ok_t npm.trust_revoked "$id"
|
|
245
|
+
done
|
|
246
|
+
fi
|
|
135
247
|
fi
|
|
136
248
|
gh variable set REPOWARDEN_NPM --repo "$REPO" --body true
|
|
137
249
|
if grep -q '^NPM_TOKEN' <<<"$(gh secret list --repo "$REPO")"; then
|
|
138
|
-
|
|
139
|
-
|
|
250
|
+
if [ "$cas" = 0 ] || [ "$cas" = 2 ]; then
|
|
251
|
+
# Relation de confiance OK (ou corrigée) : signaler le token et proposer suppression
|
|
252
|
+
attention_t npm.token_present
|
|
253
|
+
if [ "$DRY_RUN" = true ]; then
|
|
254
|
+
info_t npm.token_would_remove
|
|
255
|
+
elif [ -t 0 ]; then
|
|
256
|
+
t npm.token_remove_confirm
|
|
257
|
+
read -r -p " $REPLY" rep
|
|
258
|
+
echo
|
|
259
|
+
[[ "$rep" =~ ^[OoYy]$ ]] && gh secret delete NPM_TOKEN --repo "$REPO" && ok_t npm.token_removed
|
|
260
|
+
else
|
|
261
|
+
gh secret delete NPM_TOKEN --repo "$REPO"
|
|
262
|
+
ok_t npm.token_removed
|
|
263
|
+
fi
|
|
264
|
+
else
|
|
265
|
+
# Pas de relation de confiance : supprimer silencieusement (comportement existant)
|
|
266
|
+
gh secret delete NPM_TOKEN --repo "$REPO"
|
|
267
|
+
ok_t npm.token_removed
|
|
268
|
+
fi
|
|
140
269
|
fi
|
|
141
270
|
# Jetons temporaires révoqués sur npm (retrouvés par leur préfixe). npm peut
|
|
142
271
|
# demander un code 2FA : la commande garde le terminal (questions visibles)
|
package/bin/proteger
CHANGED
|
@@ -193,7 +193,15 @@ if [ -n "$integration" ]; then
|
|
|
193
193
|
# develop ne l'a pas reçu (retour main → develop vide après chaque
|
|
194
194
|
# release). Une livraison n'apporte que develop, vérifiée par la CI ; le
|
|
195
195
|
# retour reste fait quand main a un contenu propre (correctif direct).
|
|
196
|
+
# Garde-fou de livraison (statut posé par release-auto) : la livraison ne
|
|
197
|
+
# se merge que si elle peut aboutir (préversion publiée, protection en place)
|
|
198
|
+
contexts_branches="$contexts"
|
|
199
|
+
if grep -qs "release-auto.yml" "$GIT_TOPLEVEL"/.github/workflows/*.y*ml; then
|
|
200
|
+
contexts="${contexts:+$contexts,} {\"context\": \"livraison\", \"integration_id\": 15368}"
|
|
201
|
+
livraison_exigee=1
|
|
202
|
+
fi
|
|
196
203
|
[ -z "$others" ] || rulesets+=("$(branch_ruleset repowarden "$others" '"merge"' false "$livraison" "$last_push" "$deploiement")")
|
|
204
|
+
contexts="$contexts_branches"
|
|
197
205
|
# Branche d'intégration : squash seul (un commit par PR de travail, titre =
|
|
198
206
|
# message : les commits intermédiaires n'entrent jamais) ; plus de retour
|
|
199
207
|
# main → develop à merger, seuls develop et ses instantanés livraison/*
|
|
@@ -254,6 +262,7 @@ fi
|
|
|
254
262
|
echo_t ci.proteger.1 "$REPO"
|
|
255
263
|
echo_t ci.proteger.2 "$existing"
|
|
256
264
|
echo_t ci.proteger.3 "$CHECKS"
|
|
265
|
+
[ -z "${livraison_exigee:-}" ] || echo_t ci.proteger.livraison_check
|
|
257
266
|
echo_t ci.proteger.4 "$methods" "$delete_on_merge"
|
|
258
267
|
if [ -n "$integration" ] && [ "$DELIVERY" = deployment ]; then
|
|
259
268
|
echo_t ci.proteger.delivery_deploy "$ENVIRONMENT" "$auto_merge"
|
|
@@ -308,10 +317,76 @@ sig_attendue() {
|
|
|
308
317
|
"$(sed -n 's/.*"require_last_push_approval": \([a-z]*\).*/\1/p' <<<"$r")" \
|
|
309
318
|
"$(sed -n 's/.*"require_code_owner_review": \([a-z]*\).*/\1/p' <<<"$r")" "$deps" "$checks"
|
|
310
319
|
}
|
|
320
|
+
# Anciens rulesets : rulesets de branche du dépôt, sous un autre nom que ceux
|
|
321
|
+
# de repowarden, qui exigent encore la vérification « repogarde » (retirée en
|
|
322
|
+
# v4) ; posés à la main ou par une ancienne version. Laissés à côté, ils
|
|
323
|
+
# bloqueraient les branches pour toujours. Une ligne par ruleset dans ANCIENS :
|
|
324
|
+
# id, nom, branches couvertes (~DEFAULT_BRANCH résolu : la branche par défaut
|
|
325
|
+
# change ensuite dans le flux develop), séparés par des tabulations.
|
|
326
|
+
# shellcheck disable=SC2016 # expressions jq (gh --jq), pas du shell
|
|
327
|
+
anciens_rulesets() {
|
|
328
|
+
local ids id ligne defaut=""
|
|
329
|
+
ANCIENS=""
|
|
330
|
+
ids="$(gh api "repos/$REPO/rulesets" --jq '.[] | select(.target == "branch"
|
|
331
|
+
and (.source_type // "Repository") == "Repository"
|
|
332
|
+
and (.name | test("^(repowarden|repogarde)( \\(.*\\))?$") | not)) | .id')" || return 0
|
|
333
|
+
for id in $ids; do
|
|
334
|
+
ligne="$(gh api "repos/$REPO/rulesets/$id" --jq 'select([.rules[]? | select(.type == "required_status_checks")
|
|
335
|
+
| .parameters.required_status_checks[].context] | index("repogarde"))
|
|
336
|
+
| "\(.id)\t\(.name)\t\(.conditions.ref_name.include | join(" "))"')" || continue
|
|
337
|
+
[ -n "$ligne" ] || continue
|
|
338
|
+
if [[ "$ligne" == *"~DEFAULT_BRANCH"* ]]; then
|
|
339
|
+
[ -n "$defaut" ] || defaut="$(gh api "repos/$REPO" --jq .default_branch)"
|
|
340
|
+
ligne="${ligne//\~DEFAULT_BRANCH/refs/heads/$defaut}"
|
|
341
|
+
fi
|
|
342
|
+
ANCIENS="$ANCIENS$ligne"$'\n'
|
|
343
|
+
done
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
# Ancien ruleset (ligne de ANCIENS) couvrant une des branches du ruleset $2 (JSON)
|
|
347
|
+
couvre() {
|
|
348
|
+
local motifs m b
|
|
349
|
+
read -ra motifs <<<"$(cut -f3 <<<"$1")"
|
|
350
|
+
for m in ${motifs[@]+"${motifs[@]}"}; do
|
|
351
|
+
[ "$m" != "~ALL" ] || return 0
|
|
352
|
+
for b in $(grep -o '"refs/heads/[^"]*"' <<<"$2" | tr -d '"'); do
|
|
353
|
+
# shellcheck disable=SC2053 # motif de GitHub (refs/heads/release/*)
|
|
354
|
+
[[ "$b" != $m ]] || return 0
|
|
355
|
+
done
|
|
356
|
+
done
|
|
357
|
+
return 1
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
# Réponse d'erreur de GitHub (JSON) → « message : erreurs », lisible
|
|
361
|
+
erreur_github() {
|
|
362
|
+
local message="" erreurs="" re_message='"message": *"([^"]*)"' re_erreurs='"errors": *\[([^]]*)\]'
|
|
363
|
+
[[ ! "$1" =~ $re_message ]] || message="${BASH_REMATCH[1]}"
|
|
364
|
+
[[ ! "$1" =~ $re_erreurs ]] || erreurs="${BASH_REMATCH[1]//\"/}"
|
|
365
|
+
if [ -n "$message" ]; then
|
|
366
|
+
REPLY="$message${erreurs:+ : $erreurs}"
|
|
367
|
+
else
|
|
368
|
+
REPLY="$(tr '\n' ' ' <<<"$1")"
|
|
369
|
+
fi
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
# Rulesets indisponibles (dépôt privé d'un compte gratuit : GitHub les refuse
|
|
373
|
+
# en 403) : les réglages du dépôt restent appliqués, les rulesets sautés avec
|
|
374
|
+
# un message clair au lieu d'un arrêt sans explication
|
|
375
|
+
RULESETS_OK=1
|
|
376
|
+
if ! reponse="$(gh api "repos/$REPO/rulesets" 2>&1)" && [[ "$reponse" == *"403"* ]]; then
|
|
377
|
+
RULESETS_OK=""
|
|
378
|
+
fi
|
|
379
|
+
ANCIENS=""
|
|
380
|
+
[ -z "$RULESETS_OK" ] || anciens_rulesets
|
|
381
|
+
|
|
311
382
|
# shellcheck disable=SC2016 # expression jq (gh --jq), pas du shell
|
|
312
383
|
SIG_EN_LIGNE='(.rules | map(select(.type == "pull_request"))[0].parameters) as $p
|
|
313
384
|
| "approbations=\($p.required_approving_review_count) dernier_push=\($p.require_last_push_approval) codeowners=\($p.require_code_owner_review) deploiement=\([.rules[] | select(.type == "required_deployments") | .parameters.required_deployment_environments[]] | join(",")) verifications=\([.rules[] | select(.type == "required_status_checks") | .parameters.required_status_checks[].context] | sort | join(","))"'
|
|
314
385
|
|
|
386
|
+
if [ -n "$VERIFY" ] && [ -z "$RULESETS_OK" ]; then
|
|
387
|
+
err_t ci.proteger.rulesets_unavailable "$REPO"
|
|
388
|
+
exit 1
|
|
389
|
+
fi
|
|
315
390
|
if [ -n "$VERIFY" ]; then
|
|
316
391
|
ecarts=0
|
|
317
392
|
for ruleset in "${rulesets[@]}"; do
|
|
@@ -335,6 +410,11 @@ if [ -n "$VERIFY" ]; then
|
|
|
335
410
|
ecarts=$((ecarts + 1))
|
|
336
411
|
fi
|
|
337
412
|
done
|
|
413
|
+
while IFS=$'\t' read -r id name _; do
|
|
414
|
+
[ -n "$id" ] || continue
|
|
415
|
+
err_t ci.proteger.verify_legacy "$name" "$id"
|
|
416
|
+
ecarts=$((ecarts + 1))
|
|
417
|
+
done <<<"$ANCIENS"
|
|
338
418
|
[ "$ecarts" = 0 ] || { err_t ci.proteger.verify_fix; exit 1; }
|
|
339
419
|
ok_t ci.proteger.verify_ok
|
|
340
420
|
exit 0
|
|
@@ -348,6 +428,7 @@ if [ -n "$integration" ] && ! gh api "repos/$REPO/labels/urgent" --silent 2>/dev
|
|
|
348
428
|
fi
|
|
349
429
|
|
|
350
430
|
if [ -n "$DRY_RUN" ]; then
|
|
431
|
+
[ -n "$RULESETS_OK" ] || attention_t ci.proteger.rulesets_unavailable "$REPO"
|
|
351
432
|
printf '%s\n' "${rulesets[@]}"
|
|
352
433
|
[ -z "$env_json" ] || printf '%s\n' "$env_json"
|
|
353
434
|
exit 0
|
|
@@ -361,21 +442,60 @@ gh api -X PATCH "repos/$REPO" --silent "${settings[@]}"
|
|
|
361
442
|
gh api -X PUT "repos/$REPO/actions/permissions/workflow" --silent \
|
|
362
443
|
-f default_workflow_permissions=read -F can_approve_pull_request_reviews=true
|
|
363
444
|
|
|
364
|
-
|
|
445
|
+
echecs=0
|
|
446
|
+
[ -n "$RULESETS_OK" ] || { attention_t ci.proteger.rulesets_unavailable "$REPO"; rulesets=(); }
|
|
447
|
+
for ruleset in ${rulesets[@]+"${rulesets[@]}"}; do
|
|
365
448
|
name="$(sed -n 's/^ "name": "\(.*\)",$/\1/p' <<<"$ruleset")"
|
|
366
449
|
# Ruleset posé sous l'ancien nom (repogarde, v3) : repris et renommé, sinon
|
|
367
450
|
# il resterait à côté et exigerait une vérification « repogarde » disparue
|
|
368
451
|
old="${name/repowarden/repogarde}"
|
|
369
452
|
id="$(gh api "repos/$REPO/rulesets" \
|
|
370
453
|
--jq "([.[] | select(.name == \"$name\")] + [.[] | select(.name == \"$old\")]) | .[0].id // empty")"
|
|
454
|
+
# Sinon, un ancien ruleset sous un autre nom couvrant ses branches : repris
|
|
455
|
+
# (mis à jour en place, jamais un instant sans protection)
|
|
456
|
+
repris=""
|
|
457
|
+
if [ -z "$id" ] && grep -q '"target": "branch"' <<<"$ruleset"; then
|
|
458
|
+
while IFS= read -r ligne; do
|
|
459
|
+
{ [ -n "$ligne" ] && couvre "$ligne" "$ruleset"; } || continue
|
|
460
|
+
id="${ligne%%$'\t'*}"
|
|
461
|
+
repris="$(cut -f2 <<<"$ligne")"
|
|
462
|
+
ANCIENS="$(grep -v "^$id"$'\t' <<<"$ANCIENS" || true)"
|
|
463
|
+
break
|
|
464
|
+
done <<<"$ANCIENS"
|
|
465
|
+
fi
|
|
371
466
|
if [ -n "$id" ]; then
|
|
372
|
-
|
|
373
|
-
|
|
467
|
+
methode=PUT chemin="repos/$REPO/rulesets/$id"
|
|
468
|
+
else
|
|
469
|
+
methode=POST chemin="repos/$REPO/rulesets"
|
|
470
|
+
fi
|
|
471
|
+
# Réponse gardée : en cas de refus, le détail de GitHub est affiché
|
|
472
|
+
if reponse="$(gh api -X "$methode" "$chemin" --input - <<<"$ruleset" 2>&1)"; then
|
|
473
|
+
if [ -n "$repris" ]; then
|
|
474
|
+
ok_t ci.proteger.legacy_taken "$name" "$repris"
|
|
475
|
+
elif [ -n "$id" ]; then
|
|
476
|
+
ok_t ci.proteger.10 "$name"
|
|
477
|
+
else
|
|
478
|
+
ok_t ci.proteger.11 "$name"
|
|
479
|
+
fi
|
|
480
|
+
elif [ "$name" = "repowarden (tags)" ] && [ "$owner_type" = Organization ] &&
|
|
481
|
+
[[ "$reponse" == *"ruleset source or owner organization"* ]] &&
|
|
482
|
+
gh api -X "$methode" "$chemin" --input - <<<"$(tags_ruleset User)" >/dev/null 2>&1; then
|
|
483
|
+
# Exception GitHub Actions refusée (App non installée dans l'organisation) :
|
|
484
|
+
# règle des comptes personnels, tags ni déplacés ni supprimés
|
|
485
|
+
attention_t ci.proteger.tags_fallback
|
|
374
486
|
else
|
|
375
|
-
|
|
376
|
-
|
|
487
|
+
erreur_github "$reponse"
|
|
488
|
+
err_t ci.proteger.api_error "$name" "$REPLY"
|
|
489
|
+
echecs=$((echecs + 1))
|
|
377
490
|
fi
|
|
378
491
|
done
|
|
492
|
+
# Anciens rulesets non repris (plusieurs sur les mêmes branches) : jamais
|
|
493
|
+
# supprimés ici, la marche à suivre est donnée
|
|
494
|
+
while IFS=$'\t' read -r id name _; do
|
|
495
|
+
[ -n "$id" ] || continue
|
|
496
|
+
err_t ci.proteger.legacy_left "$name" "$id" "$REPO" "$id"
|
|
497
|
+
echecs=$((echecs + 1))
|
|
498
|
+
done <<<"$ANCIENS"
|
|
379
499
|
if [ -n "$env_json" ]; then
|
|
380
500
|
gh api -X PUT "repos/$REPO/environments/$ENVIRONMENT" --input - --silent <<<"$env_json"
|
|
381
501
|
policies="$(gh api "repos/$REPO/environments/$ENVIRONMENT/deployment-branch-policies" \
|
|
@@ -389,4 +509,5 @@ if [ -n "$env_json" ]; then
|
|
|
389
509
|
fi
|
|
390
510
|
[ -z "$urgent" ] || gh label create urgent -R "$REPO" --color B60205 \
|
|
391
511
|
--description "Livraison immédiate après merge" >/dev/null
|
|
512
|
+
[ "$echecs" = 0 ] || { err_t ci.proteger.incomplete; exit 1; }
|
|
392
513
|
ok_t ci.proteger.13
|
package/bin/repowarden
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# repowarden état du poste et étape suivante
|
|
4
4
|
# repowarden statut (idem)
|
|
5
5
|
# repowarden install [--global] [--lang fr|en] active les hooks (install.sh)
|
|
6
|
+
# repowarden bots bots du dépôt GitHub (CI, releases, tickets…)
|
|
6
7
|
# repowarden uninstall [--global] [--purge] les retire (avant npm uninstall -g)
|
|
7
8
|
# repowarden cc assistant de commit
|
|
8
9
|
# repowarden code-mort nouveau code mort de la branche
|
|
@@ -16,8 +17,10 @@
|
|
|
16
17
|
# repowarden run list [--workflow <nom>] liste les runs récents
|
|
17
18
|
# repowarden tickets init suivi des tickets (GitHub)
|
|
18
19
|
# repowarden proteger [options] protection des branches (GitHub)
|
|
20
|
+
# repowarden migrer [--pr] [--hooks] passage de repogarde à repowarden
|
|
19
21
|
# repowarden npm-publication publication npm automatique
|
|
20
22
|
# repowarden app init GitHub App des workflows (une fois)
|
|
23
|
+
# repowarden bot [init|rapport] bot d'organisation (dépôt de pilotage)
|
|
21
24
|
# repowarden --version
|
|
22
25
|
set -euo pipefail
|
|
23
26
|
|
|
@@ -35,7 +38,7 @@ source "$ROOT/hooks/lib/ui.sh"
|
|
|
35
38
|
# shellcheck source=../hooks/lib/i18n.sh
|
|
36
39
|
source "$ROOT/hooks/lib/i18n.sh"
|
|
37
40
|
|
|
38
|
-
aide() { sed -n '2,
|
|
41
|
+
aide() { sed -n '2,24p' "$ROOT/bin/repowarden" | sed 's/^# \{0,1\}//'; }
|
|
39
42
|
|
|
40
43
|
commande="${1:-}"
|
|
41
44
|
[ $# -eq 0 ] || shift
|
|
@@ -61,8 +64,11 @@ case "$commande" in
|
|
|
61
64
|
run-list) exec bash "$ROOT/bin/run-list" "$@" ;;
|
|
62
65
|
pr-checks) exec bash "$ROOT/bin/pr-checks" "$@" ;;
|
|
63
66
|
proteger | protect) exec bash "$ROOT/bin/proteger" "$@" ;;
|
|
67
|
+
migrer | migrate) exec bash "$ROOT/bin/migrer" "$@" ;;
|
|
64
68
|
npm-publication | npm-publish) exec bash "$ROOT/bin/npm-publication" "$@" ;;
|
|
65
69
|
app) exec bash "$ROOT/bin/app" "$@" ;;
|
|
70
|
+
bots) exec bash "$ROOT/bin/bots" "$@" ;;
|
|
71
|
+
bot) exec bash "$ROOT/bin/bot" "$@" ;;
|
|
66
72
|
-v | --version | version)
|
|
67
73
|
repowarden_version_r "$ROOT"
|
|
68
74
|
echo "$REPLY"
|
package/bin/statut
CHANGED
|
@@ -70,6 +70,18 @@ if [ -n "$GIT_TOPLEVEL" ]; then
|
|
|
70
70
|
attention_t st.repo_lefthook "$f"
|
|
71
71
|
break
|
|
72
72
|
done
|
|
73
|
+
# Anciens noms (configuration, workflows de l'ancien dépôt, que GitHub ne
|
|
74
|
+
# redirige plus) : la migration les remplace
|
|
75
|
+
if [ -e "$GIT_TOPLEVEL/.repogarde.conf" ] || [ -d "$GIT_TOPLEVEL/.repogarde" ] ||
|
|
76
|
+
grep -qs repogarde "$GIT_TOPLEVEL"/.github/workflows/*.y*ml; then
|
|
77
|
+
attention_t st.repo_migrate
|
|
78
|
+
suivant="${suivant:-repowarden migrer}"
|
|
79
|
+
fi
|
|
80
|
+
# Branche develop présente, flux non déclaré : traité comme « main seule »
|
|
81
|
+
cfg_r integrationBranch ""
|
|
82
|
+
if [ -z "$REPLY" ] && git rev-parse -q --verify refs/remotes/origin/develop >/dev/null; then
|
|
83
|
+
attention_t st.repo_develop_undeclared
|
|
84
|
+
fi
|
|
73
85
|
cfg_r version ""
|
|
74
86
|
if [ -n "$REPLY" ]; then
|
|
75
87
|
attendue="${REPLY#v}"
|
package/bin/tickets
CHANGED
|
@@ -141,13 +141,11 @@ GH_REPO="$REPO" AUTO_VALIDATE="${AUTO_VALIDATE:-maintainers}" "$ROOT/ci/tickets.
|
|
|
141
141
|
|
|
142
142
|
# Afficher l'état de ticketAutoCreate
|
|
143
143
|
echo
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
hint "$_T"
|
|
150
|
-
fi
|
|
144
|
+
cfg_r ticketAutoCreate false
|
|
145
|
+
case "$REPLY" in
|
|
146
|
+
true | oui | yes) dim_t tk.init_auto_create_on ;;
|
|
147
|
+
*) dim_t tk.init_auto_create_off ;;
|
|
148
|
+
esac
|
|
151
149
|
|
|
152
150
|
echo
|
|
153
151
|
ok_t tk.init_done
|
package/hooks/lib/i18n/en.sh
CHANGED
|
@@ -100,6 +100,7 @@ _msg_en() {
|
|
|
100
100
|
install.replaced) _M="core.hooksPath (%s) was '%s', replaced." ;;
|
|
101
101
|
install.enabled) _M="Hooks enabled (%s) → %s" ;;
|
|
102
102
|
install.local_wins) _M="A local core.hooksPath (e.g. husky) still takes precedence in that repository." ;;
|
|
103
|
+
install.bots_never) _M="Repository bots will no longer be offered (repowarden.bots = off); on demand: repowarden bots" ;;
|
|
103
104
|
install.lang_set) _M="Message language: English (change: %s --global --lang fr)" ;;
|
|
104
105
|
install.lang_invalid) _M="--lang: fr or en." ;;
|
|
105
106
|
install.keys_migrated) _M="repogarde.* settings (%s) renamed to repowarden.*" ;;
|
|
@@ -232,6 +233,7 @@ _msg_en() {
|
|
|
232
233
|
ci.check.16) _M="Target \"%s\" matches the flow." ;;
|
|
233
234
|
ci.check.17) _M="PR from \"%s\" to \"%s\": expected target %s (integrationBranch setting)." ;;
|
|
234
235
|
ci.check.18) _M=" Fix: change the PR base branch (Edit, next to the title), or gh pr edit --base %s" ;;
|
|
236
|
+
ci.check.develop_undeclared) _M="PR %s → %s: the develop branch exists but .repowarden.conf does not declare the develop → main flow. Add integrationBranch = develop (work then goes through develop), or delete develop if the project does not want it." ;;
|
|
235
237
|
ci.check.19) _M="gitleaks not installed: run ci/install-tool.sh gitleaks before this script." ;;
|
|
236
238
|
ci.check.20) _M="Working tree modified before the check: formatting cannot be verified." ;;
|
|
237
239
|
ci.check.21) _M="A formatter failed (syntax error, or tool / dependency unavailable): see the log above." ;;
|
|
@@ -296,16 +298,57 @@ _msg_en() {
|
|
|
296
298
|
ci.proteger.verify_ok) _M="Online rules up to date." ;;
|
|
297
299
|
ci.proteger.delivery) _M=" delivery into main: %s approval(s) required (moving to a new version); auto-merge of work PRs into develop: %s" ;;
|
|
298
300
|
ci.proteger.methods_flow) _M="main: merge commit; %s: squash or merge commit" ;;
|
|
301
|
+
ci.proteger.livraison_check) _M=" \"livraison\" check required on the main branch (prerelease published, protection in place)" ;;
|
|
299
302
|
ci.proteger.tags_org) _M="reserved for workflows" ;;
|
|
300
303
|
ci.proteger.tags_user) _M="neither moved nor deleted (personal account: creation allowed)" ;;
|
|
301
304
|
ci.proteger.tags_none) _M="not protected (--sans-tags)" ;;
|
|
302
305
|
ci.proteger.unknown_team) _M="Unknown or inaccessible team: %s (format @organisation/team)" ;;
|
|
303
306
|
ci.proteger.unknown_user) _M="Unknown user: %s" ;;
|
|
304
|
-
|
|
307
|
+
mig.no_major) _M="repowarden major version not found (%s): REPOWARDEN_MAJEURE=4 repowarden migrer." ;;
|
|
308
|
+
mig.dirty) _M="Uncommitted changes: commit or stash before repowarden migrer --pr." ;;
|
|
309
|
+
mig.pr_open) _M="Migration PR already open (%s): nothing to do." ;;
|
|
310
|
+
mig.both) _M="%s and %s both exist: keep the second, merge then delete the first by hand." ;;
|
|
311
|
+
mig.conf) _M=".repogarde.conf → .repowarden.conf ([repowarden] section, version updated)" ;;
|
|
312
|
+
mig.dir) _M=".repogarde/ → .repowarden/" ;;
|
|
313
|
+
mig.workflow) _M="%s: uses: to simdevWarden/repowarden, old names replaced" ;;
|
|
314
|
+
mig.renamed) _M="%s → %s" ;;
|
|
315
|
+
mig.tickets_events) _M="%s: ticket tracking events completed (push, review, assignment, closing): prefilled draft PR on the first push" ;;
|
|
316
|
+
mig.tickets_labels) _M="Tracking labels (type: feat, statuses…): repowarden tickets init (can be rerun, rewrites no file)" ;;
|
|
317
|
+
mig.hooks_moved) _M="Leftover lefthook hooks (%s) moved to %s" ;;
|
|
318
|
+
mig.hooks_left) _M="Leftover lefthook hooks in .git/hooks (%s), ignored: repowarden migrer --hooks to set them aside." ;;
|
|
319
|
+
mig.lefthook_conf) _M="%s: lefthook is no longer supported; move its commands to .repowarden/<hook>, then delete this file." ;;
|
|
320
|
+
mig.secrets) _M="Secrets or variables renamed in the workflows, to recreate under the new name (Settings → Secrets and variables):%s" ;;
|
|
321
|
+
mig.remaining) _M="Still mention repogarde (to review, not changed): %s" ;;
|
|
322
|
+
mig.nothing) _M="Nothing to migrate: the project already uses the repowarden names." ;;
|
|
323
|
+
mig.next) _M="Next: check the diff, then repowarden proteger (the required check is now called repowarden)." ;;
|
|
324
|
+
mig.commit_subject) _M="move from repogarde to repowarden v%s" ;;
|
|
325
|
+
mig.commit_body) _M="Old names and paths replaced by repowarden migrer (docs/migration-v4.md): GitHub no longer redirects the old repository's reusable workflows." ;;
|
|
326
|
+
mig.pr_body) _M="Migration from repogarde to repowarden, made by repowarden migrer (docs/migration-v4.md)." ;;
|
|
327
|
+
mig.pr_after) _M="After merging: run repowarden proteger (the required check is now called repowarden) and recreate any REPOGARDE_* secrets under their new name." ;;
|
|
328
|
+
mig.pr_created) _M="Migration PR opened (%s)." ;;
|
|
329
|
+
st.repo_migrate) _M="Old repogarde names in this project: repowarden migrer" ;;
|
|
330
|
+
st.repo_develop_undeclared) _M="The develop branch exists but the develop → main flow is not declared: add integrationBranch = develop to .repowarden.conf (otherwise work can go straight into main)." ;;
|
|
331
|
+
ci.proteger.legacy_taken) _M="Ruleset \"%s\": old ruleset \"%s\" taken over (repogarde check removed)." ;;
|
|
332
|
+
ci.proteger.legacy_left) _M="Old ruleset \"%s\" (id %s): still requires the repogarde check, removed in v4, and blocks its branches. Delete it: Settings → Rules → Rulesets, or gh api -X DELETE repos/%s/rulesets/%s." ;;
|
|
333
|
+
ci.proteger.verify_legacy) _M="%s (id %s): old ruleset, still requires the repogarde check (removed in v4)" ;;
|
|
334
|
+
ci.proteger.api_error) _M="Ruleset \"%s\" rejected by GitHub: %s" ;;
|
|
335
|
+
ci.proteger.incomplete) _M="Incomplete protection: see the errors above." ;;
|
|
336
|
+
ci.proteger.rulesets_unavailable) _M="Rulesets unavailable for %s: GitHub refuses them on a private repository of a free account. Make the repository public, or move to GitHub Pro / Team; the other settings are applied." ;;
|
|
337
|
+
ci.proteger.tags_fallback) _M="Tags ruleset: \"GitHub Actions\" bypass refused in this organization; tags protected as on a personal account (not moved or deleted, creation allowed)." ;;
|
|
338
|
+
ci.version.usage) _M="Usage: ci/version.sh next|notes|notes-livraison [ref]" ;;
|
|
305
339
|
ci.version.breaking) _M="Breaking changes" ;;
|
|
306
340
|
ci.version.features) _M="Features" ;;
|
|
307
341
|
ci.version.fixes) _M="Bug fixes" ;;
|
|
308
342
|
ci.version.maintenance) _M="Maintenance" ;;
|
|
343
|
+
ci.version.summary) _M="In short" ;;
|
|
344
|
+
ci.version.todo) _M="To do" ;;
|
|
345
|
+
ci.version.update) _M="Update" ;;
|
|
346
|
+
ci.version.tickets) _M="Delivered tickets" ;;
|
|
347
|
+
ci.livraison.protection) _M="Protection of the %s flow missing (merge commit, no deletion): run repowarden proteger" ;;
|
|
348
|
+
ci.livraison.maintenance) _M="Maintenance only: no version to publish" ;;
|
|
349
|
+
ci.livraison.non_exigee) _M="%s: prerelease not required" ;;
|
|
350
|
+
ci.livraison.ok) _M="%s: prerelease tested, deliverable" ;;
|
|
351
|
+
ci.livraison.preversion) _M="%s: no prerelease %s; wait for the evening one, or Actions → release → Run workflow on %s" ;;
|
|
309
352
|
ci.install_tool.os) _M="Unsupported system: %s" ;;
|
|
310
353
|
ci.install_tool.arch) _M="Unsupported architecture: %s" ;;
|
|
311
354
|
ci.install_tool.unknown) _M="Unknown tool: %s" ;;
|
|
@@ -360,7 +403,16 @@ _msg_en() {
|
|
|
360
403
|
npm.first_published) _M="%s@%s published by the pipeline." ;;
|
|
361
404
|
npm.step_trust) _M="3/3 Tokenless publishing (trusted publishing)" ;;
|
|
362
405
|
npm.trust_exists) _M="Trusted publishing already configured." ;;
|
|
406
|
+
npm.trust_mismatch) _M="Existing trust relationship does not match expected parameters:" ;;
|
|
407
|
+
npm.trust_confirm) _M="Confirm fix (new relationship created before revoking old)? [y/N] " ;;
|
|
408
|
+
npm.trust_cancelled) _M="Fix cancelled." ;;
|
|
409
|
+
npm.trust_would_create) _M="[dry-run] Trust relationship would be created: %s, workflow %s, env %s" ;;
|
|
410
|
+
npm.trust_would_fix) _M="[dry-run] Trust relationship would be fixed (new created, old revoked)" ;;
|
|
411
|
+
npm.trust_revoked) _M="Old trust relationship revoked: %s" ;;
|
|
363
412
|
npm.trust_set) _M="Trusted publishing: %s, workflow %s." ;;
|
|
413
|
+
npm.token_present) _M="NPM_TOKEN secret still present while trusted publishing works." ;;
|
|
414
|
+
npm.token_remove_confirm) _M="Remove NPM_TOKEN secret? [y/N] " ;;
|
|
415
|
+
npm.token_would_remove) _M="[dry-run] NPM_TOKEN secret would be removed" ;;
|
|
364
416
|
npm.token_removed) _M="NPM_TOKEN secret removed from the repository." ;;
|
|
365
417
|
npm.token_revoked) _M="Temporary token revoked on npm." ;;
|
|
366
418
|
npm.done) _M="Done: every release publishes %s to npm, without a token." ;;
|
|
@@ -406,13 +458,93 @@ _msg_en() {
|
|
|
406
458
|
app.server_failed) _M="Local page did not start." ;;
|
|
407
459
|
app.open) _M="Open %s then click GitHub's green button." ;;
|
|
408
460
|
app.no_code) _M="No answer from GitHub (creation cancelled, or 15 min timeout)." ;;
|
|
409
|
-
app.created) _M="App %s created; credentials stored (variable
|
|
461
|
+
app.created) _M="App %s created; credentials stored (variable %s, secret %s)." ;;
|
|
410
462
|
app.step_install) _M="Installing on the repository" ;;
|
|
411
463
|
app.installed) _M="App %s installed on %s." ;;
|
|
412
464
|
app.not_installed) _M="App %s not installed on %s yet: run repowarden app init again once installed." ;;
|
|
413
465
|
app.check_in_ci) _M="Installation checked by the first ticket tracking run (\"Jeton de l'App\" step); to install it: %s" ;;
|
|
414
466
|
app.done) _M="repowarden workflows now use the App: what they do triggers the other workflows." ;;
|
|
415
467
|
app.next) _M="Without the App (variable and secret missing), they fall back to the Actions token." ;;
|
|
468
|
+
app.bot_all_repos) _M="Organization bot: when installing, choose \"All repositories\" (new repositories are covered automatically; only those with a .repowarden.conf are managed)." ;;
|
|
469
|
+
bot.init_exists) _M="%s already exists: left unchanged." ;;
|
|
470
|
+
bot.init_done) _M="%s written: runs every night, and on demand (Actions → bot → Run workflow, dry-run box to see without changing anything)." ;;
|
|
471
|
+
bot.init_next) _M="Bot credentials in this repository: repowarden app init --bot (once, installed on \"All repositories\")." ;;
|
|
472
|
+
bot.no_report) _M="Report not found: %s" ;;
|
|
473
|
+
bot.report_updated) _M="Report published (issue #%s updated)." ;;
|
|
474
|
+
bot.report_created) _M="Report published (new issue)." ;;
|
|
475
|
+
bot.col_repo) _M="Repository" ;;
|
|
476
|
+
bot.col_mode) _M="Mode" ;;
|
|
477
|
+
bot.col_protection) _M="Protection" ;;
|
|
478
|
+
bot.col_migration) _M="Migration" ;;
|
|
479
|
+
bot.repo) _M="%s" ;;
|
|
480
|
+
bot.not_adopted) _M="not adopted (no .repowarden.conf)" ;;
|
|
481
|
+
bot.ignored) _M="ignored (bot = off)" ;;
|
|
482
|
+
bot.mode_invalid) _M="bot = %s: auto, pr or off expected" ;;
|
|
483
|
+
bot.clone_failed) _M="clone failed: %s" ;;
|
|
484
|
+
bot.prot_ok) _M="up to date" ;;
|
|
485
|
+
bot.prot_stale) _M="⚠ outdated: repowarden proteger" ;;
|
|
486
|
+
bot.prot_applied) _M="✔ applied" ;;
|
|
487
|
+
bot.error) _M="✖ %s" ;;
|
|
488
|
+
bot.mig_none) _M="nothing to migrate" ;;
|
|
489
|
+
bot.mig_open) _M="PR already open" ;;
|
|
490
|
+
bot.mig_todo) _M="⚠ to migrate: repowarden migrer" ;;
|
|
491
|
+
bot.mig_pr) _M="✔ PR opened" ;;
|
|
492
|
+
bot.report_head) _M="Run of %s." ;;
|
|
493
|
+
bot.report_dry) _M="Preview (dry-run): nothing was changed." ;;
|
|
494
|
+
bot.failed) _M="Run finished with %s error(s): see the report." ;;
|
|
495
|
+
bots.skip) _M="Repository bots not offered (%s): later, repowarden bots" ;;
|
|
496
|
+
bots.why_repo) _M="not in a Git repository" ;;
|
|
497
|
+
bots.why_github) _M="repository not on GitHub" ;;
|
|
498
|
+
bots.why_gh) _M="gh missing: https://cli.github.com" ;;
|
|
499
|
+
bots.why_gh_login) _M="gh not logged in: gh auth login" ;;
|
|
500
|
+
bots.why_admin) _M="repository admin rights needed" ;;
|
|
501
|
+
bots.why_tty) _M="no terminal to answer the questions" ;;
|
|
502
|
+
bots.ask_global) _M="Set up this repository's bots (CI, releases, tickets, protection…)? Nothing is done without your consent, bot by bot." ;;
|
|
503
|
+
bots.later) _M="No bot set up. Later: repowarden bots" ;;
|
|
504
|
+
bots.flow_question) _M="Branch flow:" ;;
|
|
505
|
+
bots.flow_main) _M="%s only: every PR is merged into it (squash)" ;;
|
|
506
|
+
bots.flow_develop) _M="develop → %s: work is integrated into develop (prereleases), only develop goes into %s (delivery)" ;;
|
|
507
|
+
bots.ask_create_develop) _M="The develop branch does not exist on GitHub: create it from the default branch?" ;;
|
|
508
|
+
bots.one_by_one) _M="One consent per bot (Enter: yes):" ;;
|
|
509
|
+
bots.app_present) _M="Workflows GitHub App already set up: used by the other bots." ;;
|
|
510
|
+
bots.desc_ci) _M=" CI: checks every PR (messages, branch, secrets, formatting, tests); writes .github/workflows/repowarden.yml" ;;
|
|
511
|
+
bots.desc_release) _M=" Releases: version, notes and tag computed from the commits; writes .github/workflows/release.yml" ;;
|
|
512
|
+
bots.desc_nettoyage) _M=" Cleanup: deletes merged branches, keeps long-lived branches; writes .github/workflows/nettoyage.yml" ;;
|
|
513
|
+
bots.desc_tickets) _M=" Tickets: ticket first, prefilled PR, statuses up to production; labels, ticket template, workflow (repowarden tickets init)" ;;
|
|
514
|
+
bots.desc_app) _M=" GitHub App: what the bots do triggers the other workflows; created in the browser (repowarden app init)" ;;
|
|
515
|
+
bots.desc_proteger) _M=" Protection: PR and checks required, no deletion or force push; changes GitHub settings (repowarden proteger)" ;;
|
|
516
|
+
bots.desc_npm) _M=" npm: publishes the package on every release, without a token (repowarden npm-publication)" ;;
|
|
517
|
+
bots.ask_ci) _M="CI?" ;;
|
|
518
|
+
bots.ask_release) _M="Releases?" ;;
|
|
519
|
+
bots.ask_nettoyage) _M="Branch cleanup?" ;;
|
|
520
|
+
bots.ask_tickets) _M="Ticket tracking?" ;;
|
|
521
|
+
bots.ask_app) _M="GitHub App?" ;;
|
|
522
|
+
bots.ask_proteger) _M="Branch protection?" ;;
|
|
523
|
+
bots.ask_npm) _M="npm publishing?" ;;
|
|
524
|
+
bots.preview) _M="Preview" ;;
|
|
525
|
+
bots.prev_develop) _M="branch %s created on GitHub from %s" ;;
|
|
526
|
+
bots.prev_conf) _M=".repowarden.conf: integrationBranch = %s, protected branches" ;;
|
|
527
|
+
bots.prev_review) _M=".repowarden.conf: delivery approved by reviewing its PR (no GitHub App)" ;;
|
|
528
|
+
bots.prev_kept) _M="%s exists: kept as is (difference with the template: %s line(s))" ;;
|
|
529
|
+
bots.prev_file) _M="%s: created" ;;
|
|
530
|
+
bots.prev_tickets) _M="tickets: labels and ticket template on GitHub, tickets.yml workflow" ;;
|
|
531
|
+
bots.prev_app) _M="GitHub App: created in the browser, credentials stored as repository variable and secret" ;;
|
|
532
|
+
bots.prev_proteger) _M="GitHub settings: branch and tag rulesets, merge methods" ;;
|
|
533
|
+
bots.prev_npm) _M="npm: trusted publishing of the package, REPOWARDEN_NPM variable" ;;
|
|
534
|
+
bots.ask_confirm) _M="Apply?" ;;
|
|
535
|
+
bots.run_tickets) _M="Ticket tracking" ;;
|
|
536
|
+
bots.run_app) _M="GitHub App" ;;
|
|
537
|
+
bots.run_proteger) _M="Branch protection" ;;
|
|
538
|
+
bots.run_npm) _M="npm publishing" ;;
|
|
539
|
+
bots.failed_one) _M="%s: failed, see above; the other bots are set up. Run again: repowarden bots" ;;
|
|
540
|
+
bots.develop_created) _M="Branch %s created from %s." ;;
|
|
541
|
+
bots.conf_written) _M="%s updated." ;;
|
|
542
|
+
bots.kept) _M="%s exists: kept as is." ;;
|
|
543
|
+
bots.written) _M="%s written." ;;
|
|
544
|
+
bots.done) _M="Bots set up." ;;
|
|
545
|
+
bots.done_errors) _M="Bots set up, %s failed (see above)." ;;
|
|
546
|
+
bots.commit_files) _M="Files to commit through a PR (workflows act once on the default branch): git status" ;;
|
|
547
|
+
bots.verify) _M="Then: repowarden proteger --verifier, and repowarden statut." ;;
|
|
416
548
|
tk.reopened) _M="Reopened: closed by GitHub when #%s was merged into \`%s\`, which is not production yet. In pre-production; it will be closed at the release." ;;
|
|
417
549
|
tk.sync.ready) _M="Ticket #%s assigned: local branch %s ready (repowarden ticket %s)." ;;
|
|
418
550
|
tk.sync.not_validated) _M="Ticket #%s assigned but not validated yet: no branch for now." ;;
|