repowarden 4.4.0-next.4 → 4.4.0-next.7

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.
@@ -24,7 +24,7 @@ accepter() {
24
24
  body="$(gh pr view "$pr" --json body -q .body)"
25
25
  pr_tickets_r "$body" "$head"
26
26
  [[ " $REPLY " == *" $n "* ]] || continue
27
- if verifier "$pr" "$sha" "$REPLY"; then
27
+ if verifier "$pr" "$sha" "$REPLY" "$head"; then
28
28
  merge_auto "$pr" "$base" "$brouillon"
29
29
  fi
30
30
  done < <(gh pr list --state open --json number,headRefName,headRefOid,baseRefName,isDraft \
package/ci/tickets/pr.sh CHANGED
@@ -27,7 +27,7 @@ cmd_pr() {
27
27
  # Bots de dépendances, PR de release, livraisons et retours : pas de ticket
28
28
  # exigé. Les PR ouvertes par le suivi des tickets lui-même (jeton des
29
29
  # Actions, github-actions[bot]) citent leur ticket : suivies normalement.
30
- if [[ "${AUTHOR:-}" =~ ^(dependabot|renovate)(\[bot\])?$ || "$HEAD" == release-please--* ||
30
+ if [[ "${AUTHOR:-}" =~ ^(dependabot|renovate)(\[bot\])?$ || "$HEAD" == release-please--* || "$HEAD" == livraison/* ||
31
31
  "$HEAD" == "${INTEGRATION:-develop}" || "$HEAD" == "${MAIN:-main}" ]]; then
32
32
  gh api "repos/$GH_REPO/statuses/$HEAD_SHA" -f state=success -f context=ticket \
33
33
  -f description="Sans ticket (bot, release ou livraison)" >/dev/null
@@ -64,7 +64,7 @@ cmd_pr() {
64
64
  done
65
65
  # Le blocage est porté par le statut « ticket » (exigé par la protection) :
66
66
  # le job reste vert, un rouge signale une vraie panne
67
- if verifier "$PR" "$HEAD_SHA" "$tickets"; then
67
+ if verifier "$PR" "$HEAD_SHA" "$tickets" "$HEAD"; then
68
68
  merge_auto "$PR" "${BASE:-}" "${DRAFT:-false}"
69
69
  fi
70
70
  }
@@ -32,7 +32,7 @@ cmd_push() {
32
32
  [ -z "${PUSHER:-}" ] || gh issue edit "$n" --add-assignee "$PUSHER" >/dev/null || true
33
33
  est_valide "$n" && statut "$n" "$S_ENCOURS"
34
34
  notice_t tk.draft_opened "${url##*/}" "$n"
35
- verifier "${url##*/}" "$SHA" "$n" || true
35
+ verifier "${url##*/}" "$SHA" "$n" "$PUSH_BRANCH" || true
36
36
  }
37
37
 
38
38
  # Revue : corrections demandées → le ticket repasse en cours
@@ -4,14 +4,47 @@
4
4
  # Chargé par ci/tickets.sh (après hooks/lib/common.sh et hooks/lib/tickets.sh).
5
5
  # shellcheck disable=SC2154 # statuts, réglages et compteurs définis dans les autres modules
6
6
 
7
- # Vérification « ticket » (statut de commit) de la PR $1, commit $2
7
+ # Vrai si le ticket $1 porte une conception écrite par un mainteneur (commentaire
8
+ # « Conception retenue ») : le code suit une conception relue, pas l'inverse
9
+ conception_ecrite() {
10
+ local corps
11
+ corps="$(gh issue view "$1" --json comments -q '.comments[]
12
+ | select(.authorAssociation == "OWNER" or .authorAssociation == "MEMBER" or .authorAssociation == "COLLABORATOR")
13
+ | .body' 2>/dev/null || true)"
14
+ grep -qi "conception retenue" <<<"$corps"
15
+ }
16
+
17
+ # REPLY = premier autre ticket que $2 cité par un commit de la PR $1 (« Ticket : #M »)
18
+ autre_ticket_r() {
19
+ local cites n
20
+ cites="$(gh pr view "$1" --json commits -q '.commits[].messageBody' 2>/dev/null || true)"
21
+ REPLY=""
22
+ for n in $(grep -oiE '^[[:space:]]*tickets?[[:space:]]*:[[:space:]]*#[0-9]+' <<<"$cites" | grep -oE '[0-9]+' || true); do
23
+ if [ "$n" != "$2" ]; then REPLY="$n"; return 0; fi
24
+ done
25
+ return 1
26
+ }
27
+
28
+ # Vérification « ticket » (statut de commit) de la PR $1, commit $2, tickets
29
+ # $3, branche $4. Contrôles (pas des consignes) : un seul ticket, validé,
30
+ # porté par la branche (type/N-sujet), avec sa conception écrite ; aucun
31
+ # commit d'un autre ticket.
8
32
  verifier() {
9
- local pr="$1" sha="$2" tickets="$3" n attente="" liste
33
+ local pr="$1" sha="$2" tickets="$3" head="${4:-}" n attente="" liste
10
34
  for n in $tickets; do est_valide "$n" || attente="$attente #$n"; done
35
+ [ -z "$head" ] || branch_ticket_r "$head"
11
36
  if [ -z "$tickets" ]; then
12
37
  _tr tk.none; etat=failure
38
+ elif [ "$(wc -w <<<"$tickets")" -gt 1 ]; then
39
+ _tr tk.multi "#${tickets// /, #}"; etat=failure
13
40
  elif [ -n "$attente" ]; then
14
41
  _tr tk.waiting "${attente# }" "$VALIDE"; etat=failure
42
+ elif [ -n "$head" ] && [ -z "$REPLY" ]; then
43
+ _tr tk.bad_branch "$head" "$tickets"; etat=failure
44
+ elif [ "${REQUIRE_DESIGN:-true}" = true ] && ! conception_ecrite "$tickets"; then
45
+ _tr tk.no_design "$tickets"; etat=failure
46
+ elif autre_ticket_r "$pr" "$tickets"; then
47
+ _tr tk.other_ticket "$REPLY" "$tickets"; etat=failure
15
48
  else
16
49
  liste=""
17
50
  for n in $tickets; do liste="$liste #$n"; done
@@ -120,6 +120,8 @@ types_help() {
120
120
  branch_name_valid() {
121
121
  local branch="$1" allowed pat
122
122
  [ -z "$branch" ] && return 0 # HEAD détachée
123
+ # Instantané de develop créé par la demande de livraison : toujours admis
124
+ [[ "$branch" != livraison/* ]] || return 0
123
125
  cfg_r allowedBranches "$DEFAULT_ALLOWED_BRANCHES"
124
126
  allowed="$REPLY"
125
127
  set -f # pas d'expansion de "release/*" sur le disque
@@ -143,10 +145,11 @@ pr_targets_r() {
143
145
  integration="$REPLY"
144
146
  [ -n "$integration" ] || return 0
145
147
  cfg_r mainBranch main
146
- # Seule la branche d'intégration entre dans la branche principale : tout
147
- # le reste (correctifs urgents compris) passe par elle et ses préversions
148
+ # Seule la branche d'intégration entre dans la branche principale (ou son
149
+ # instantané livraison/vX.Y.Z, figé à la demande de livraison) : tout le
150
+ # reste (correctifs urgents compris) passe par elle et ses préversions
148
151
  case "$1" in
149
- "$integration" | release-please--*) ;;
152
+ "$integration" | livraison/* | release-please--*) ;;
150
153
  *) REPLY="$integration" ;;
151
154
  esac
152
155
  }
@@ -374,6 +374,10 @@ _msg_en() {
374
374
  tk.merged) _M="Merged by PR #%s into %s: in pre-production, available in the next pre-release." ;;
375
375
  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." ;;
376
376
  tk.branch_notice) _M="Branch %s created for ticket #%s" ;;
377
+ tk.multi) _M="PR linked to several tickets (%s): one PR = one ticket, split it." ;;
378
+ tk.bad_branch) _M="Branch \"%s\": it must carry the ticket number (type/%s-topic); repowarden ticket <n> creates it." ;;
379
+ tk.no_design) _M="Design missing on #%s: write it as a ticket comment (\"Conception retenue\") before the code." ;;
380
+ tk.other_ticket) _M="A commit references ticket #%s while the PR handles #%s: one PR = one ticket." ;;
377
381
  tk.automerge_armed) _M="PR #%s: auto-merge armed (squash), as soon as the checks are green." ;;
378
382
  tk.automerge_no_app) _M="PR #%s: auto-merge not armed, no GitHub App (repowarden app init): with the Actions token, the merge would trigger no workflow." ;;
379
383
  tk.automerge_failed) _M="PR #%s: auto-merge not armed (auto-merge not allowed on the repository: repowarden proteger)." ;;
@@ -374,6 +374,10 @@ _msg_fr() {
374
374
  tk.merged) _M="Mergé par la PR #%s dans %s : en préprod, disponible dans la prochaine préversion." ;;
375
375
  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." ;;
376
376
  tk.branch_notice) _M="Branche %s créée pour le ticket #%s" ;;
377
+ tk.multi) _M="PR liée à plusieurs tickets (%s) : une PR = un ticket, la découper." ;;
378
+ tk.bad_branch) _M="Branche « %s » : elle doit porter le numéro du ticket (type/%s-sujet) ; repowarden ticket <n> la crée." ;;
379
+ tk.no_design) _M="Conception absente sur #%s : l'écrire en commentaire du ticket (« Conception retenue ») avant le code." ;;
380
+ tk.other_ticket) _M="Un commit cite le ticket #%s alors que la PR traite #%s : une PR = un ticket." ;;
377
381
  tk.automerge_armed) _M="PR #%s : merge automatique armé (squash), dès que les vérifications sont vertes." ;;
378
382
  tk.automerge_no_app) _M="PR #%s : merge automatique non armé, pas de GitHub App (repowarden app init) : avec le jeton des Actions, le merge ne déclencherait aucun workflow." ;;
379
383
  tk.automerge_failed) _M="PR #%s : merge automatique non armé (dépôt sans merge automatique autorisé : repowarden proteger)." ;;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowarden",
3
- "version": "4.4.0-next.4",
3
+ "version": "4.4.0-next.7",
4
4
  "description": "Hooks git et CI multi-langages : messages de commit, nommage des branches, secrets, formatage, tests ciblés, code mort, releases.",
5
5
  "keywords": [
6
6
  "git-hooks",