repowarden 4.9.0 → 4.9.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/bin/bots +19 -4
- package/bin/npm-publication +18 -2
- package/bin/proteger +42 -11
- package/bin/tickets +1 -1
- package/ci/tickets/commun.sh +22 -3
- package/ci/tickets/pr.sh +3 -0
- package/hooks/lib/forge.sh +8 -0
- package/hooks/lib/i18n/en.sh +14 -1
- package/hooks/lib/i18n/fr.sh +14 -1
- package/hooks/lib/tickets.sh +8 -4
- package/hooks/post-checkout +4 -2
- package/package.json +1 -1
package/bin/bots
CHANGED
|
@@ -71,6 +71,13 @@ demander() {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
brand "bots · $REPO"
|
|
74
|
+
# Dépôt privé d'une offre gratuite : ni protection, ni rulesets, ni merge
|
|
75
|
+
# automatique ; dit avant toute question, pour décider en connaissance de cause
|
|
76
|
+
SANS_RULESETS=""
|
|
77
|
+
if github_sans_rulesets "$REPO"; then
|
|
78
|
+
SANS_RULESETS=1
|
|
79
|
+
attention_t bots.plan_limited "$REPO"
|
|
80
|
+
fi
|
|
74
81
|
demander bots.ask_global n || { info_t bots.later; exit 0; }
|
|
75
82
|
|
|
76
83
|
# --- Flux ------------------------------------------------------------------
|
|
@@ -125,6 +132,11 @@ done
|
|
|
125
132
|
choisi() { [[ " ${BOTS[*]+"${BOTS[*]}"} " == *" $1 "* ]]; }
|
|
126
133
|
AVEC_APP=""
|
|
127
134
|
{ [ -n "$APP_PRESENTE" ] || choisi app; } && AVEC_APP=1
|
|
135
|
+
# Livraison approuvée par l'environnement (« Approve and deploy ») : avec
|
|
136
|
+
# l'App, sauf sur un dépôt sans rulesets (ni règle de déploiement exigée, ni
|
|
137
|
+
# environnement avec approbation sur un dépôt privé gratuit) : revue de sa PR
|
|
138
|
+
LIVRAISON_ENV=""
|
|
139
|
+
[ -z "$AVEC_APP" ] || [ -n "$SANS_RULESETS" ] || LIVRAISON_ENV=1
|
|
128
140
|
|
|
129
141
|
# --- Livraison (flux develop, releases) : mode, rythme, préversion -----------
|
|
130
142
|
# Défauts : le release.yml d'aujourd'hui (approbation, regroupé, préversion
|
|
@@ -133,7 +145,10 @@ LIVRAISON_AUTO="" A_CHAQUE_TICKET="" PREVERSION_OBLIGATOIRE=1
|
|
|
133
145
|
if [ "$FLUX" = develop ] && choisi release; then
|
|
134
146
|
echo >&2
|
|
135
147
|
dim_t bots.desc_delivery
|
|
136
|
-
if
|
|
148
|
+
if [ -n "$SANS_RULESETS" ]; then
|
|
149
|
+
# Livraison automatique = merge automatique, ignoré par GitHub ici
|
|
150
|
+
info_t bots.no_delivery_auto
|
|
151
|
+
elif demander bots.ask_delivery_auto n; then
|
|
137
152
|
LIVRAISON_AUTO=1
|
|
138
153
|
# Le merge automatique passe par la GitHub App (jeton des Actions : pas de release)
|
|
139
154
|
[ -n "$AVEC_APP" ] || attention_t bots.auto_no_app
|
|
@@ -369,7 +384,7 @@ YAML
|
|
|
369
384
|
echo " preversion-obligatoire: false # version stable possible sans préversion"
|
|
370
385
|
if [ -n "$LIVRAISON_AUTO" ]; then
|
|
371
386
|
echo " delivery-auto: true # la GitHub App merge la livraison, vérifications vertes"
|
|
372
|
-
elif [ -n "$
|
|
387
|
+
elif [ -n "$LIVRAISON_ENV" ]; then
|
|
373
388
|
echo " delivery-environment: production # « Approve and deploy » valide la livraison"
|
|
374
389
|
fi
|
|
375
390
|
if [ -n "$AVEC_APP" ]; then
|
|
@@ -479,7 +494,7 @@ if [ "$FLUX" = develop ]; then
|
|
|
479
494
|
info_t bots.prev_conf "$INTEGRATION"
|
|
480
495
|
if [ -n "$LIVRAISON_AUTO" ]; then
|
|
481
496
|
info_t bots.prev_conf_auto
|
|
482
|
-
elif [ -z "$
|
|
497
|
+
elif [ -z "$LIVRAISON_ENV" ]; then
|
|
483
498
|
info_t bots.prev_review
|
|
484
499
|
fi
|
|
485
500
|
fi
|
|
@@ -545,7 +560,7 @@ if [ "$FLUX" = develop ]; then
|
|
|
545
560
|
# Choix explicite : remplace une approbation déjà réglée
|
|
546
561
|
[ "$(git config -f "$conf" --get repowarden.deliveryApproval || true)" = auto ] ||
|
|
547
562
|
git config -f "$conf" repowarden.deliveryApproval auto
|
|
548
|
-
elif [ -z "$
|
|
563
|
+
elif [ -z "$LIVRAISON_ENV" ]; then
|
|
549
564
|
git config -f "$conf" --get repowarden.deliveryApproval >/dev/null ||
|
|
550
565
|
git config -f "$conf" repowarden.deliveryApproval review
|
|
551
566
|
fi
|
package/bin/npm-publication
CHANGED
|
@@ -46,7 +46,14 @@ if ! node -e 'const [a,b]=process.argv[1].split(".").map(Number);process.exit(a>
|
|
|
46
46
|
fi
|
|
47
47
|
cd "$GIT_TOPLEVEL"
|
|
48
48
|
[ -f package.json ] || { err_t npm.no_package; exit 1; }
|
|
49
|
-
[ -
|
|
49
|
+
if [ -z "$REPO" ]; then
|
|
50
|
+
REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
|
|
51
|
+
else
|
|
52
|
+
# Dépôt vérifié avant toute action : une faute de frappe (« own/nom, »)
|
|
53
|
+
# serait sinon prise plus loin pour un dépôt sans release
|
|
54
|
+
[[ "$REPO" =~ ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ ]] || { err_t npm.bad_repo "$REPO"; exit 1; }
|
|
55
|
+
gh repo view "$REPO" --json nameWithOwner >/dev/null || { err_t npm.repo_unreachable "$REPO"; exit 1; }
|
|
56
|
+
fi
|
|
50
57
|
name="$(node -p 'require("./package.json").name')"
|
|
51
58
|
# Préfixe des jetons temporaires de l'ancien parcours, révoqués à la fin
|
|
52
59
|
TOKEN_PREFIX="repowarden-ci-${REPO##*/}"
|
|
@@ -133,8 +140,17 @@ publie() { [ -n "$(npm view "$name" name 2>/dev/null || true)" ]; }
|
|
|
133
140
|
# créé ni stocké, aucun mot de passe saisi par repowarden
|
|
134
141
|
if ! publie; then
|
|
135
142
|
step_t npm.step_first
|
|
136
|
-
|
|
143
|
+
# Seul « release not found » signifie « aucune release » ; toute autre
|
|
144
|
+
# erreur de gh (réseau, droits) est rapportée telle quelle
|
|
145
|
+
gh_err="$(mktemp "${TMPDIR:-/tmp}/repowarden-gh.XXXXXX")"
|
|
146
|
+
tag="$(gh release view --repo "$REPO" --json tagName -q .tagName 2>"$gh_err")" || tag=""
|
|
147
|
+
msg="$(cat "$gh_err")"
|
|
148
|
+
rm -f "$gh_err"
|
|
137
149
|
if [ -z "$tag" ]; then
|
|
150
|
+
if [ -n "$msg" ] && ! grep -qi 'release not found' <<<"$msg"; then
|
|
151
|
+
err_t npm.release_error "$REPO" "$msg"
|
|
152
|
+
exit 1
|
|
153
|
+
fi
|
|
138
154
|
attention_t npm.no_release "$name"
|
|
139
155
|
exit 0
|
|
140
156
|
fi
|
package/bin/proteger
CHANGED
|
@@ -404,9 +404,7 @@ erreur_github() {
|
|
|
404
404
|
# en 403) : les réglages du dépôt restent appliqués, les rulesets sautés avec
|
|
405
405
|
# un message clair au lieu d'un arrêt sans explication
|
|
406
406
|
RULESETS_OK=1
|
|
407
|
-
|
|
408
|
-
RULESETS_OK=""
|
|
409
|
-
fi
|
|
407
|
+
! github_sans_rulesets "$REPO" || RULESETS_OK=""
|
|
410
408
|
ANCIENS=""
|
|
411
409
|
[ -z "$RULESETS_OK" ] || anciens_rulesets
|
|
412
410
|
|
|
@@ -459,7 +457,11 @@ if [ -n "$integration" ] && ! gh api "repos/$REPO/labels/urgent" --silent 2>/dev
|
|
|
459
457
|
fi
|
|
460
458
|
|
|
461
459
|
if [ -n "$DRY_RUN" ]; then
|
|
462
|
-
[ -
|
|
460
|
+
if [ -z "$RULESETS_OK" ]; then
|
|
461
|
+
attention_t ci.proteger.rulesets_unavailable "$REPO"
|
|
462
|
+
# Même offre : merge automatique ignoré par GitHub (PATCH accepté)
|
|
463
|
+
[ "$auto_merge" = false ] || attention_t ci.proteger.automerge_unavailable
|
|
464
|
+
fi
|
|
463
465
|
printf '%s\n' "${rulesets[@]}"
|
|
464
466
|
[ -z "$env_json" ] || printf '%s\n' "$env_json"
|
|
465
467
|
exit 0
|
|
@@ -472,15 +474,42 @@ if [ -z "$RULESETS_OK" ] && [ -n "$integration" ]; then
|
|
|
472
474
|
squash=false
|
|
473
475
|
attention_t ci.proteger.no_squash
|
|
474
476
|
fi
|
|
477
|
+
echecs=0
|
|
478
|
+
# Appel de l'API dont le refus n'arrête pas le reste : $1 clé i18n de ce qui
|
|
479
|
+
# est réglé, puis la commande ; refus affiché avec le détail de GitHub (sans
|
|
480
|
+
# --silent, gh garde la réponse) et compté comme échec
|
|
481
|
+
appliquer() {
|
|
482
|
+
local quoi="$1" reponse detail
|
|
483
|
+
shift
|
|
484
|
+
reponse="$("$@" 2>&1)" && return 0
|
|
485
|
+
erreur_github "$reponse"
|
|
486
|
+
detail="$REPLY"
|
|
487
|
+
t "$quoi"
|
|
488
|
+
err_t ci.proteger.settings_error "$REPLY" "$detail"
|
|
489
|
+
echecs=$((echecs + 1))
|
|
490
|
+
return 1
|
|
491
|
+
}
|
|
475
492
|
settings=(-F allow_squash_merge="$squash" -F allow_merge_commit="$merge_commit" -F allow_rebase_merge=false
|
|
476
|
-
-F delete_branch_on_merge="$delete_on_merge" -F allow_auto_merge="$auto_merge"
|
|
477
|
-
|
|
493
|
+
-F delete_branch_on_merge="$delete_on_merge" -F allow_auto_merge="$auto_merge")
|
|
494
|
+
# Titre et corps du squash seulement si le squash est autorisé : envoyés avec
|
|
495
|
+
# allow_squash_merge=false (dépôt sans rulesets, flux develop), GitHub refuse
|
|
496
|
+
# tout le PATCH en 422 « Validation Failed »
|
|
497
|
+
[ "$squash" = false ] || settings+=(-f squash_merge_commit_title=PR_TITLE -f squash_merge_commit_message=PR_BODY)
|
|
478
498
|
[ -z "$integration" ] || settings+=(-f default_branch="$integration")
|
|
479
|
-
gh api -X PATCH "repos/$REPO"
|
|
480
|
-
|
|
481
|
-
|
|
499
|
+
if appliquer ci.proteger.what_repo gh api -X PATCH "repos/$REPO" "${settings[@]}" &&
|
|
500
|
+
[ "$auto_merge" = true ] &&
|
|
501
|
+
[ "$(gh api "repos/$REPO" --jq .allow_auto_merge 2>/dev/null || true)" != true ]; then
|
|
502
|
+
# Merge automatique demandé mais resté désactivé : GitHub l'ignore sans
|
|
503
|
+
# erreur (dépôt privé d'une offre gratuite)
|
|
504
|
+
attention_t ci.proteger.automerge_ignored "$REPO"
|
|
505
|
+
if [ -n "$integration" ] && [ "$DELIVERY" = auto ]; then
|
|
506
|
+
err_t ci.proteger.automerge_delivery
|
|
507
|
+
echecs=$((echecs + 1))
|
|
508
|
+
fi
|
|
509
|
+
fi
|
|
510
|
+
appliquer ci.proteger.what_workflow gh api -X PUT "repos/$REPO/actions/permissions/workflow" \
|
|
511
|
+
-f default_workflow_permissions=read -F can_approve_pull_request_reviews=true || true
|
|
482
512
|
|
|
483
|
-
echecs=0
|
|
484
513
|
[ -n "$RULESETS_OK" ] || { attention_t ci.proteger.rulesets_unavailable "$REPO"; rulesets=(); }
|
|
485
514
|
for ruleset in ${rulesets[@]+"${rulesets[@]}"}; do
|
|
486
515
|
name="$(sed -n 's/^ "name": "\(.*\)",$/\1/p' <<<"$ruleset")"
|
|
@@ -535,7 +564,9 @@ while IFS=$'\t' read -r id name _; do
|
|
|
535
564
|
echecs=$((echecs + 1))
|
|
536
565
|
done <<<"$ANCIENS"
|
|
537
566
|
if [ -n "$env_json" ]; then
|
|
538
|
-
gh api -X PUT "repos/$REPO/environments/$ENVIRONMENT" --input -
|
|
567
|
+
appliquer ci.proteger.what_environment gh api -X PUT "repos/$REPO/environments/$ENVIRONMENT" --input - <<<"$env_json" || env_json=""
|
|
568
|
+
fi
|
|
569
|
+
if [ -n "$env_json" ]; then
|
|
539
570
|
policies="$(gh api "repos/$REPO/environments/$ENVIRONMENT/deployment-branch-policies" \
|
|
540
571
|
--jq '.branch_policies[] | "\(.type):\(.name)"')"
|
|
541
572
|
for policy in $(for b in $existing; do echo "branch:$b"; done) "tag:v*"; do
|
package/bin/tickets
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Prépare le suivi des tickets d'un dépôt GitHub (relançable sans risque) :
|
|
3
3
|
# repowarden tickets init [--repo propriétaire/nom] [--sans-validation-auto]
|
|
4
4
|
# repowarden tickets sync branches locales des tickets qui me sont assignés
|
|
5
|
-
# (
|
|
5
|
+
# (automatique si réglage ticketSync = auto ; défaut manual)
|
|
6
6
|
# - étiquettes : « validé », les statuts (à valider, backlog, en cours,
|
|
7
7
|
# en relecture, préprod, done) et les types (type: feat, type: fix…), qui
|
|
8
8
|
# donnent le préfixe de la branche du ticket ;
|
package/ci/tickets/commun.sh
CHANGED
|
@@ -24,11 +24,30 @@ pr_tickets_r() {
|
|
|
24
24
|
REPLY="${found# }"
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
#
|
|
27
|
+
# Rang d'un statut dans le cycle (REPLY) : à valider 0 … done 5, -1 sinon
|
|
28
|
+
rang_statut_r() {
|
|
29
|
+
case "$1" in
|
|
30
|
+
"$S_AVALIDER") REPLY=0 ;; "$S_BACKLOG") REPLY=1 ;; "$S_ENCOURS") REPLY=2 ;;
|
|
31
|
+
"$S_RELECTURE") REPLY=3 ;; "$S_PREPROD") REPLY=4 ;; "$S_DONE") REPLY=5 ;;
|
|
32
|
+
*) REPLY=-1 ;;
|
|
33
|
+
esac
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Statut $2 sur le ticket $1 : remplace les autres étiquettes « statut: ».
|
|
37
|
+
# Monotone pour un travail livré : un ticket en préprod ou done ne recule
|
|
38
|
+
# jamais (événement en retard, branche réapparue, réassignation…), signalé.
|
|
28
39
|
statut() {
|
|
29
|
-
local n="$1" s="$2" l retirer=()
|
|
40
|
+
local n="$1" s="$2" l retirer=() cible
|
|
41
|
+
rang_statut_r "$s"
|
|
42
|
+
cible="$REPLY"
|
|
30
43
|
while IFS= read -r l; do
|
|
31
|
-
[[ "$l" == "statut: "* && "$l" != "$s" ]]
|
|
44
|
+
[[ "$l" == "statut: "* && "$l" != "$s" ]] || continue
|
|
45
|
+
rang_statut_r "$l"
|
|
46
|
+
if [ "$REPLY" -ge 4 ] && [ "$REPLY" -gt "$cible" ]; then
|
|
47
|
+
notice_t tk.status_kept "$n" "${l#statut: }" "${s#statut: }"
|
|
48
|
+
return 0
|
|
49
|
+
fi
|
|
50
|
+
retirer+=(--remove-label "$l")
|
|
32
51
|
done < <(gh issue view "$n" --json labels -q '.labels[].name' 2>/dev/null || true)
|
|
33
52
|
# ${a[@]+…} : tableau vide accepté sous set -u par le bash 3.2 de macOS
|
|
34
53
|
gh issue edit "$n" --add-label "$s" ${retirer[@]+"${retirer[@]}"} >/dev/null
|
package/ci/tickets/pr.sh
CHANGED
|
@@ -54,6 +54,9 @@ cmd_pr() {
|
|
|
54
54
|
done
|
|
55
55
|
return 0
|
|
56
56
|
fi
|
|
57
|
+
# PR déjà mergée, événement en retard (edited, synchronize…) : le ticket est
|
|
58
|
+
# livré, ni statut, ni vérification, ni merge automatique
|
|
59
|
+
[ "${MERGED:-false}" != true ] || return 0
|
|
57
60
|
|
|
58
61
|
# Aucun ticket : si auto-create activé, créé à partir de la PR, à valider,
|
|
59
62
|
# et relié à la PR ; sinon, échec de la vérification avec la marche à suivre.
|
package/hooks/lib/forge.sh
CHANGED
|
@@ -37,3 +37,11 @@ forge_init() {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
forge_init
|
|
40
|
+
|
|
41
|
+
# Dépôt GitHub $1 sans rulesets ni protection de branches (dépôt privé d'une
|
|
42
|
+
# offre gratuite : GitHub les refuse en 403, « Upgrade to GitHub Pro or make
|
|
43
|
+
# this repository public ») ; le merge automatique y est aussi ignoré
|
|
44
|
+
github_sans_rulesets() {
|
|
45
|
+
local reponse
|
|
46
|
+
! reponse="$(gh api "repos/$1/rulesets" 2>&1)" && [[ "$reponse" == *"403"* ]]
|
|
47
|
+
}
|
package/hooks/lib/i18n/en.sh
CHANGED
|
@@ -341,6 +341,13 @@ _msg_en() {
|
|
|
341
341
|
ci.proteger.incomplete) _M="Incomplete protection: see the errors above." ;;
|
|
342
342
|
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." ;;
|
|
343
343
|
ci.proteger.no_squash) _M="Without rulesets, the merge method cannot be enforced per branch: squash disabled (merge commit only), otherwise a squashed delivery would break the main branch history." ;;
|
|
344
|
+
ci.proteger.automerge_unavailable) _M="Auto-merge unavailable on this repository (GitHub ignores it on a private repository of a free account): work PRs and deliveries are merged by hand; automatic delivery impossible." ;;
|
|
345
|
+
ci.proteger.automerge_ignored) _M="Auto-merge requested but still disabled on %s: GitHub ignores it without an error (private repository of a free account). Work PRs and deliveries are merged by hand. Make the repository public, or move to GitHub Pro / Team, then run repowarden proteger again." ;;
|
|
346
|
+
ci.proteger.automerge_delivery) _M="deliveryApproval = auto cannot work without auto-merge: the delivery PR will not merge by itself." ;;
|
|
347
|
+
ci.proteger.settings_error) _M="%s: rejected by GitHub: %s" ;;
|
|
348
|
+
ci.proteger.what_repo) _M="Repository settings (merge methods, default branch)" ;;
|
|
349
|
+
ci.proteger.what_workflow) _M="Workflow permissions" ;;
|
|
350
|
+
ci.proteger.what_environment) _M="Deployment environment" ;;
|
|
344
351
|
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)." ;;
|
|
345
352
|
ci.version.usage) _M="Usage: ci/version.sh next|notes|notes-livraison [ref]" ;;
|
|
346
353
|
ci.version.breaking) _M="Breaking changes" ;;
|
|
@@ -393,6 +400,8 @@ _msg_en() {
|
|
|
393
400
|
npm.npx_global) _M="npx uses a temporary folder: global hooks would point to a deleted folder. Install the package first: npm install -g repowarden, then repowarden install --global." ;;
|
|
394
401
|
npm.no_npm) _M="npm required: https://nodejs.org" ;;
|
|
395
402
|
npm.no_package) _M="No package.json at the repository root." ;;
|
|
403
|
+
npm.bad_repo) _M="Invalid repository: \"%s\". Expected form: owner/name (e.g. simdevWarden/repowarden). Nothing was done." ;;
|
|
404
|
+
npm.repo_unreachable) _M="Repository %s not found or not accessible with gh (see above): nothing was done." ;;
|
|
396
405
|
npm.old_npm) _M="npm %s is too old: 11.15 or later required (npm install -g npm@11)." ;;
|
|
397
406
|
npm.step_login) _M="1/3 npm account" ;;
|
|
398
407
|
npm.logged) _M="Logged in to npm: %s" ;;
|
|
@@ -400,6 +409,7 @@ _msg_en() {
|
|
|
400
409
|
npm.hint_2fa) _M="Enable it: npm profile enable-2fa auth-and-writes (QR code for an authenticator app), or https://www.npmjs.com/settings/%s/tfa; then run this command again." ;;
|
|
401
410
|
npm.step_first) _M="2/3 First publication, from this machine (latest release)" ;;
|
|
402
411
|
npm.no_release) _M="No release yet: nothing is published. Run this command again after the first release of %s." ;;
|
|
412
|
+
npm.release_error) _M="Cannot read the releases of %s: %s. Nothing is published or configured; run this command again." ;;
|
|
403
413
|
npm.would_publish) _M="[dry-run] %s@%s would be published from release %s (npm publish, in this terminal)" ;;
|
|
404
414
|
npm.publishing) _M="Publishing %s@%s (release %s): npm may ask for a validation (browser or code)." ;;
|
|
405
415
|
npm.publish_failed) _M="Publication of %s refused (see above): nothing else was configured. Run this command again." ;;
|
|
@@ -446,6 +456,7 @@ _msg_en() {
|
|
|
446
456
|
tk.waiting) _M="Ticket %s awaiting validation: a maintainer adds the \"%s\" label to the ticket." ;;
|
|
447
457
|
tk.ok) _M="Ticket %s validated." ;;
|
|
448
458
|
tk.merged) _M="Merged by PR #%s into %s: in pre-production, available in the next pre-release." ;;
|
|
459
|
+
tk.status_kept) _M="Ticket #%s kept in %s: delivered work does not go back to %s." ;;
|
|
449
460
|
tk.branch_created) _M="Ticket validated: its branch \`%s\` is created from \`%s\`.\n\nTo work on it:\n\n\`\`\`bash\nrepowarden ticket %s\n\`\`\`\n\n(or \`git fetch && git switch %s\`). The first push opens the draft PR." ;;
|
|
450
461
|
tk.branch_notice) _M="Branch %s created for ticket #%s" ;;
|
|
451
462
|
tk.multi) _M="PR linked to several tickets (%s): one PR = one ticket, split it." ;;
|
|
@@ -533,6 +544,8 @@ _msg_en() {
|
|
|
533
544
|
bots.ask_npm) _M="npm publishing?" ;;
|
|
534
545
|
bots.desc_delivery) _M="develop → main delivery: automatic (the GitHub App merges the delivery PR as soon as the checks are green; human validation is the merge of each ticket) or human approval (default)" ;;
|
|
535
546
|
bots.ask_delivery_auto) _M="Automatic delivery? (no: human approval)" ;;
|
|
547
|
+
bots.plan_limited) _M="%s is a private repository on a free plan: GitHub offers neither branch protection, rulesets nor auto-merge there. So these will not work: required PRs and checks, work PRs merging by themselves, automatic delivery (PRs will be merged by hand). To get everything: make the repository public, or move to GitHub Pro / Team, then run repowarden bots again." ;;
|
|
548
|
+
bots.no_delivery_auto) _M="Automatic delivery not offered (no auto-merge on this repository): the delivery PR will be merged by hand." ;;
|
|
536
549
|
bots.auto_no_app) _M="Automatic delivery without a GitHub App: the automatic merge requires the App (repowarden app init); without it, the delivery PR has to be merged by hand." ;;
|
|
537
550
|
bots.desc_rythme) _M="Pace: on every ticket (prerelease and delivery request on every merge) or grouped (default: evening prerelease, Friday delivery window)" ;;
|
|
538
551
|
bots.ask_each_ticket) _M="On every ticket? (no: grouped)" ;;
|
|
@@ -540,7 +553,7 @@ _msg_en() {
|
|
|
540
553
|
bots.preview) _M="Preview" ;;
|
|
541
554
|
bots.prev_develop) _M="branch %s created on GitHub from %s" ;;
|
|
542
555
|
bots.prev_conf) _M=".repowarden.conf: integrationBranch = %s, protected branches" ;;
|
|
543
|
-
bots.prev_review) _M=".repowarden.conf: delivery approved by reviewing its PR (no GitHub App)" ;;
|
|
556
|
+
bots.prev_review) _M=".repowarden.conf: delivery approved by reviewing its PR (no GitHub App or approval environment)" ;;
|
|
544
557
|
bots.prev_conf_auto) _M=".repowarden.conf: deliveryApproval = auto (automatic delivery)" ;;
|
|
545
558
|
bots.prev_delivery_auto) _M="release.yml: automatic delivery (delivery-auto), the GitHub App merges the delivery PR as soon as the checks are green" ;;
|
|
546
559
|
bots.prev_delivery_approval) _M="release.yml: delivery approved by a person" ;;
|
package/hooks/lib/i18n/fr.sh
CHANGED
|
@@ -341,6 +341,13 @@ _msg_fr() {
|
|
|
341
341
|
ci.proteger.incomplete) _M="Protection incomplète : voir les erreurs ci-dessus." ;;
|
|
342
342
|
ci.proteger.rulesets_unavailable) _M="Rulesets indisponibles pour %s : GitHub les refuse sur un dépôt privé d'un compte gratuit. Rendre le dépôt public, ou passer à GitHub Pro / Team ; les autres réglages sont appliqués." ;;
|
|
343
343
|
ci.proteger.no_squash) _M="Sans rulesets, le mode de merge ne peut pas être imposé par branche : squash désactivé (merge commit seul), sinon une livraison squashée casserait l'historique de la branche principale." ;;
|
|
344
|
+
ci.proteger.automerge_unavailable) _M="Merge automatique indisponible sur ce dépôt (GitHub l'ignore sur un dépôt privé d'un compte gratuit) : PR de travail et livraison à merger à la main ; livraison automatique impossible." ;;
|
|
345
|
+
ci.proteger.automerge_ignored) _M="Merge automatique demandé mais resté désactivé sur %s : GitHub l'ignore sans erreur (dépôt privé d'un compte gratuit). PR de travail et livraison à merger à la main. Rendre le dépôt public, ou passer à GitHub Pro / Team, puis relancer repowarden proteger." ;;
|
|
346
|
+
ci.proteger.automerge_delivery) _M="deliveryApproval = auto ne peut pas fonctionner sans merge automatique : la PR de livraison ne se mergera pas seule." ;;
|
|
347
|
+
ci.proteger.settings_error) _M="%s : refusé par GitHub : %s" ;;
|
|
348
|
+
ci.proteger.what_repo) _M="Réglages du dépôt (modes de merge, branche par défaut)" ;;
|
|
349
|
+
ci.proteger.what_workflow) _M="Permissions des workflows" ;;
|
|
350
|
+
ci.proteger.what_environment) _M="Environnement de déploiement" ;;
|
|
344
351
|
ci.proteger.tags_fallback) _M="Ruleset des tags : exception « GitHub Actions » refusée dans cette organisation ; tags protégés comme sur un compte personnel (ni déplacés ni supprimés, création libre)." ;;
|
|
345
352
|
ci.version.usage) _M="Usage : ci/version.sh next|notes|notes-livraison [ref]" ;;
|
|
346
353
|
ci.version.breaking) _M="Changements incompatibles" ;;
|
|
@@ -393,6 +400,8 @@ _msg_fr() {
|
|
|
393
400
|
npm.npx_global) _M="npx utilise un dossier temporaire : des hooks globaux pointeraient vers un dossier effacé. Installe d'abord le paquet : npm install -g repowarden, puis repowarden install --global." ;;
|
|
394
401
|
npm.no_npm) _M="npm requis : https://nodejs.org" ;;
|
|
395
402
|
npm.no_package) _M="Aucun package.json à la racine du dépôt." ;;
|
|
403
|
+
npm.bad_repo) _M="Dépôt invalide : « %s ». Forme attendue : propriétaire/nom (ex. simdevWarden/repowarden). Rien n'a été fait." ;;
|
|
404
|
+
npm.repo_unreachable) _M="Dépôt %s introuvable ou inaccessible avec gh (voir ci-dessus) : rien n'a été fait." ;;
|
|
396
405
|
npm.old_npm) _M="npm %s trop ancien : 11.15 au minimum (npm install -g npm@11)." ;;
|
|
397
406
|
npm.step_login) _M="1/3 Compte npm" ;;
|
|
398
407
|
npm.logged) _M="Connecté à npm : %s" ;;
|
|
@@ -400,6 +409,7 @@ _msg_fr() {
|
|
|
400
409
|
npm.hint_2fa) _M="Activer : npm profile enable-2fa auth-and-writes (QR code pour une application d'authentification), ou https://www.npmjs.com/settings/%s/tfa ; puis relancer cette commande." ;;
|
|
401
410
|
npm.step_first) _M="2/3 Première publication, depuis ce poste (dernière release)" ;;
|
|
402
411
|
npm.no_release) _M="Aucune release encore : rien n'est publié. Relance cette commande après la première release de %s." ;;
|
|
412
|
+
npm.release_error) _M="Lecture des releases de %s impossible : %s. Rien n'est publié ni configuré ; relance cette commande." ;;
|
|
403
413
|
npm.would_publish) _M="[dry-run] %s@%s serait publié depuis la release %s (npm publish, dans ce terminal)" ;;
|
|
404
414
|
npm.publishing) _M="Publication de %s@%s (release %s) : npm peut demander une validation (navigateur ou code)." ;;
|
|
405
415
|
npm.publish_failed) _M="Publication de %s refusée (voir ci-dessus) : rien d'autre n'a été configuré. Relance cette commande." ;;
|
|
@@ -446,6 +456,7 @@ _msg_fr() {
|
|
|
446
456
|
tk.waiting) _M="Ticket %s à valider : un mainteneur pose l'étiquette « %s » sur le ticket." ;;
|
|
447
457
|
tk.ok) _M="Ticket %s validé." ;;
|
|
448
458
|
tk.merged) _M="Mergé par la PR #%s dans %s : en préprod, disponible dans la prochaine préversion." ;;
|
|
459
|
+
tk.status_kept) _M="Ticket #%s laissé en %s : un travail livré ne repasse pas en %s." ;;
|
|
449
460
|
tk.branch_created) _M="Ticket validé : sa branche \`%s\` est créée depuis \`%s\`.\n\nPour y travailler :\n\n\`\`\`bash\nrepowarden ticket %s\n\`\`\`\n\n(ou \`git fetch && git switch %s\`). Le premier push ouvre la PR en brouillon." ;;
|
|
450
461
|
tk.branch_notice) _M="Branche %s créée pour le ticket #%s" ;;
|
|
451
462
|
tk.multi) _M="PR liée à plusieurs tickets (%s) : une PR = un ticket, la découper." ;;
|
|
@@ -533,6 +544,8 @@ _msg_fr() {
|
|
|
533
544
|
bots.ask_npm) _M="Publication npm ?" ;;
|
|
534
545
|
bots.desc_delivery) _M="Livraison develop → main : automatique (la GitHub App merge la PR de livraison dès que les vérifications sont vertes ; la validation humaine est le merge de chaque ticket) ou approbation humaine (défaut)" ;;
|
|
535
546
|
bots.ask_delivery_auto) _M="Livraison automatique ? (non : approbation humaine)" ;;
|
|
547
|
+
bots.plan_limited) _M="%s est un dépôt privé d'une offre gratuite : GitHub n'y offre ni protection de branches, ni rulesets, ni merge automatique. Ne fonctionneront donc pas : les PR et vérifications exigées, la fusion seule des PR de travail, la livraison automatique (les PR seront à merger à la main). Pour tout avoir : rendre le dépôt public, ou passer à GitHub Pro / Team, puis relancer repowarden bots." ;;
|
|
548
|
+
bots.no_delivery_auto) _M="Livraison automatique non proposée (pas de merge automatique sur ce dépôt) : la PR de livraison sera mergée à la main." ;;
|
|
536
549
|
bots.auto_no_app) _M="Livraison automatique sans GitHub App : le merge automatique exige l'App (repowarden app init) ; sans elle, la PR de livraison reste à merger à la main." ;;
|
|
537
550
|
bots.desc_rythme) _M="Rythme : à chaque ticket (préversion et demande de livraison à chaque merge) ou regroupé (défaut : préversion le soir, fenêtre de livraison le vendredi)" ;;
|
|
538
551
|
bots.ask_each_ticket) _M="À chaque ticket ? (non : regroupé)" ;;
|
|
@@ -540,7 +553,7 @@ _msg_fr() {
|
|
|
540
553
|
bots.preview) _M="Aperçu" ;;
|
|
541
554
|
bots.prev_develop) _M="branche %s créée sur GitHub depuis %s" ;;
|
|
542
555
|
bots.prev_conf) _M=".repowarden.conf : integrationBranch = %s, branches protégées" ;;
|
|
543
|
-
bots.prev_review) _M=".repowarden.conf : livraison validée par la revue de sa PR (
|
|
556
|
+
bots.prev_review) _M=".repowarden.conf : livraison validée par la revue de sa PR (ni GitHub App, ni environnement d'approbation)" ;;
|
|
544
557
|
bots.prev_conf_auto) _M=".repowarden.conf : deliveryApproval = auto (livraison automatique)" ;;
|
|
545
558
|
bots.prev_delivery_auto) _M="release.yml : livraison automatique (delivery-auto), la GitHub App merge la PR de livraison dès que les vérifications sont vertes" ;;
|
|
546
559
|
bots.prev_delivery_approval) _M="release.yml : livraison approuvée par une personne" ;;
|
package/hooks/lib/tickets.sh
CHANGED
|
@@ -201,15 +201,17 @@ ticket_remote_branch_r() {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
# Branches locales des tickets qui me sont assignés (repowarden tickets sync ;
|
|
204
|
-
# hooks post-merge et post-checkout
|
|
204
|
+
# hooks post-merge et post-checkout seulement si ticketSync = auto est posé,
|
|
205
|
+
# au plus toutes les 15 min) :
|
|
205
206
|
# branche distante retrouvée, ou créée et liée au ticket (validé) ; branche
|
|
206
|
-
# locale de suivi créée sans changer la branche courante
|
|
207
|
+
# locale de suivi créée sans changer la branche courante (jamais pour un travail
|
|
208
|
+
# livré : préprod, done, ou en relecture sans branche). Ticket qui ne m'est
|
|
207
209
|
# plus assigné : signalé, sa branche locale conservée. Réglage ticketSync :
|
|
208
|
-
#
|
|
210
|
+
# manual (défaut : commande seulement, un pull ne touche à rien), auto, off. $1 = force (commande).
|
|
209
211
|
tickets_sync() {
|
|
210
212
|
local force="${1:-}" stamp now last base n titre etiquettes branche b qui etat
|
|
211
213
|
local miens=" "
|
|
212
|
-
cfg_r ticketSync
|
|
214
|
+
cfg_r ticketSync manual
|
|
213
215
|
[ "$REPLY" != off ] || return 0
|
|
214
216
|
if [ -z "$force" ]; then
|
|
215
217
|
[ "$REPLY" = auto ] && tickets_managed && command -v gh >/dev/null || return 0
|
|
@@ -231,6 +233,8 @@ tickets_sync() {
|
|
|
231
233
|
ticket_remote_branch_r "$n"
|
|
232
234
|
branche="$REPLY"
|
|
233
235
|
if [ -z "$branche" ]; then
|
|
236
|
+
# En relecture sans branche : PR mergée, branche supprimée ; jamais recréée
|
|
237
|
+
grep -qxF "$S_RELECTURE" <<<"$etiquettes" && continue
|
|
234
238
|
if tickets_managed && ! grep -qxF "$VALIDE" <<<"$etiquettes"; then
|
|
235
239
|
info_t tk.sync.not_validated "$n"
|
|
236
240
|
continue
|
package/hooks/post-checkout
CHANGED
|
@@ -21,6 +21,8 @@ if ! skipped branch-name && ! branch_name_valid "$BRANCH"; then
|
|
|
21
21
|
fi
|
|
22
22
|
# Branche de travail sans ticket : prévenu, jamais bloqué
|
|
23
23
|
ticket_hint "$BRANCH"
|
|
24
|
-
# Branches locales des tickets qui me sont assignés (au plus toutes les 15 min)
|
|
25
|
-
|
|
24
|
+
# Branches locales des tickets qui me sont assignés (au plus toutes les 15 min).
|
|
25
|
+
# Pas au clonage (ancienne référence nulle) : un clone ne touche ni GitHub ni
|
|
26
|
+
# les branches ; la synchronisation viendra au changement de branche suivant.
|
|
27
|
+
[[ "${1:-}" =~ ^0+$ ]] || tickets_sync || true
|
|
26
28
|
exit 0
|
package/package.json
CHANGED