From 5bf8bd280c3a24b4118c676f252277fa6d847fa9 Mon Sep 17 00:00:00 2001 From: Nicolas Cantu Date: Thu, 28 Aug 2025 11:41:55 +0200 Subject: [PATCH] [skip ci] chore: finalize local changes --- .cursor/rules/41-ssh-automation.mdc | 5 +++++ .cursor/rules/42-template-sync.mdc | 6 ++++++ AGENTS.md | 11 +++++++++++ docs/project/USAGE.md | 19 ++++++++++++++++++- scripts/local/install_hooks.sh | 18 ++++++++++++++++++ scripts/local/merge_branch.sh | 25 +++++++++++++++++++++++++ scripts/local/precommit.sh | 15 +++++++++++++++ scripts/local/prepush.sh | 20 ++++++++++++++++++++ scripts/local/release_local.sh | 20 ++++++++++++++++++++ 9 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 scripts/local/install_hooks.sh create mode 100644 scripts/local/merge_branch.sh create mode 100644 scripts/local/precommit.sh create mode 100644 scripts/local/prepush.sh create mode 100644 scripts/local/release_local.sh diff --git a/.cursor/rules/41-ssh-automation.mdc b/.cursor/rules/41-ssh-automation.mdc index 1a988d6..84da596 100644 --- a/.cursor/rules/41-ssh-automation.mdc +++ b/.cursor/rules/41-ssh-automation.mdc @@ -1,3 +1,8 @@ +# Règles SSH & Automatisation — Flux local + +- Interdiction de secrets en clair; secrets via `~/.4nk_template/.env` ou variables CI +- Scripts SSH conservés exécutables, journaux non sensibles +- Le flux local prime: agents exécutés avant merge/push/release; CI neutralisable via `CI_SKIP=true` et `[skip ci]` --- alwaysApply: true --- diff --git a/.cursor/rules/42-template-sync.mdc b/.cursor/rules/42-template-sync.mdc index c7cf051..386d4ec 100644 --- a/.cursor/rules/42-template-sync.mdc +++ b/.cursor/rules/42-template-sync.mdc @@ -25,6 +25,9 @@ Tous les projets issus de 4NK_project_template. Contrôle de l’alignement sur - Erreur bloquante si un path requis n’existe pas après sync. - Erreur bloquante si tests/CI signalent des scripts non exécutables ou des fichiers sensibles. +[note] +Les validations CI peuvent être remplacées par l’exécution locale des agents (AUTO_FIX/SCOPE) lorsque `CI_SKIP=true` est activé. Conserver une PR de synthèse et la traçabilité dans le changelog. + [artefacts concernés] - .4nk-sync.yml, TEMPLATE_VERSION, .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md, CHANGELOG.md. # Synchronisation de template (4NK) @@ -49,5 +52,8 @@ Tous les projets issus de 4NK_project_template. Contrôle de l’alignement sur - Erreur bloquante si un path requis n’existe pas après sync. - Erreur bloquante si tests/CI signalent des scripts non exécutables ou des fichiers sensibles. +[note] +Les validations CI peuvent être remplacées par l’exécution locale des agents (AUTO_FIX/SCOPE) lorsque `CI_SKIP=true` est activé. Conserver une PR de synthèse et la traçabilité dans le changelog. + [artefacts concernés] - .4nk-sync.yml, TEMPLATE_VERSION, .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md, CHANGELOG.md. diff --git a/AGENTS.md b/AGENTS.md index b3a855c..e770a8c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -399,3 +399,14 @@ Ce `AGENTS.md` mis à jour introduit l’**Agent Synchronisation de template** e La matrice de coordination formalise les validations obligatoires pour chaque type de changement, garantissant cohérence structurelle, qualité documentaire, sécurité, traçabilité. Ainsi que la stabilité à long terme sur tous les projets issus de `4NK_project_template`. + +--- + +## Exécution locale et neutralisation de la CI + +- Les contrôles CI peuvent être remplacés par l’exécution locale des agents: `scripts/agents/run.sh` avec `AUTO_FIX=1`, `SCOPE=changed|all`. +- La CI peut être neutralisée par défaut via `CI_SKIP=true` dans le workflow; ponctuellement via des commits `[skip ci]`. +- Des hooks sont fournis pour automatiser le flux local: + - `scripts/local/precommit.sh` et `scripts/local/prepush.sh` + - installation: `bash scripts/local/install_hooks.sh` +- Un conteneur unifié (runner+agents) permet une exécution reproductible: `docker-compose.ci.yml`. diff --git a/docs/project/USAGE.md b/docs/project/USAGE.md index 4dc2098..cfbc1b1 100644 --- a/docs/project/USAGE.md +++ b/docs/project/USAGE.md @@ -93,7 +93,24 @@ AUTO_FIX=1 SCOPE=all scripts/agents/run.sh bash scripts/security/audit.sh || true bash scripts/release/guard.sh || true ``` - - Agents utiles en premier passage: `documentation`, `quality-technique`, `open-source`, `securite`, `deploiement` + +Ou installez-les automatiquement: + +```bash +bash scripts/local/install_hooks.sh +``` + +- Agents utiles en premier passage: `documentation`, `quality-technique`, `open-source`, `securite`, `deploiement` + +### Script de merge local (main/develop) + +```bash +# Merge de la branche courante vers main (valide localement avant) +bash scripts/local/merge_branch.sh main + +# Merge vers develop +bash scripts/local/merge_branch.sh develop +``` ## 5. Qualité et CI diff --git a/scripts/local/install_hooks.sh b/scripts/local/install_hooks.sh new file mode 100644 index 0000000..caed4ea --- /dev/null +++ b/scripts/local/install_hooks.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"/.. +HOOKS_DIR="$REPO_ROOT/.git/hooks" + +mkdir -p "$HOOKS_DIR" +install_hook() { + local name="$1" src="$2" + cp -f "$src" "$HOOKS_DIR/$name" + chmod +x "$HOOKS_DIR/$name" + echo "Installed hook: $name" +} + +install_hook pre-commit "$REPO_ROOT/scripts/local/precommit.sh" +install_hook pre-push "$REPO_ROOT/scripts/local/prepush.sh" + +echo "Hooks installés." diff --git a/scripts/local/merge_branch.sh b/scripts/local/merge_branch.sh new file mode 100644 index 0000000..9275299 --- /dev/null +++ b/scripts/local/merge_branch.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +TARGET_BRANCH="${1:-main}" +SOURCE_BRANCH="${2:-}" + +if [[ -z "$SOURCE_BRANCH" ]]; then + SOURCE_BRANCH="$(git rev-parse --abbrev-ref HEAD)" +fi + +if [[ "$SOURCE_BRANCH" == "$TARGET_BRANCH" ]]; then + echo "Déjà sur $TARGET_BRANCH"; exit 0 +fi + +# Valider localement avant merge +AUTO_FIX="${AUTO_FIX:-1}" SCOPE="${SCOPE:-all}" scripts/agents/run.sh || true +if [ -f scripts/security/audit.sh ]; then bash scripts/security/audit.sh || true; fi + +git fetch origin --prune +git checkout "$TARGET_BRANCH" +git pull --ff-only origin "$TARGET_BRANCH" || true +git merge --no-ff "$SOURCE_BRANCH" -m "[skip ci] merge: $SOURCE_BRANCH -> $TARGET_BRANCH" +git push origin "$TARGET_BRANCH" + +echo "Merge effectué: $SOURCE_BRANCH → $TARGET_BRANCH" diff --git a/scripts/local/precommit.sh b/scripts/local/precommit.sh new file mode 100644 index 0000000..8c66efd --- /dev/null +++ b/scripts/local/precommit.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR/.." + +# Lint Markdown (best effort) +if command -v npx >/dev/null 2>&1; then + npx -y markdownlint-cli "**/*.md" --ignore "archive/**" || true +fi + +# Agents rapides sur fichiers modifiés +AUTO_FIX="${AUTO_FIX:-1}" SCOPE="${SCOPE:-changed}" scripts/agents/run.sh + +echo "[pre-commit] OK" diff --git a/scripts/local/prepush.sh b/scripts/local/prepush.sh new file mode 100644 index 0000000..2d3d93a --- /dev/null +++ b/scripts/local/prepush.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR/.." + +# Agents complets +AUTO_FIX="${AUTO_FIX:-1}" SCOPE="${SCOPE:-all}" scripts/agents/run.sh + +# Audit sécurité (best effort) +if [ -f scripts/security/audit.sh ]; then + bash scripts/security/audit.sh || true +fi + +# Release guard (dry-run logique) +if [ -f scripts/release/guard.sh ]; then + bash scripts/release/guard.sh || true +fi + +echo "[pre-push] OK" diff --git a/scripts/local/release_local.sh b/scripts/local/release_local.sh new file mode 100644 index 0000000..e3f48ed --- /dev/null +++ b/scripts/local/release_local.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +VERSION="${1:-}" +if [[ -z "$VERSION" ]]; then + echo "Usage: $0 vYYYY.MM.P" >&2 + exit 2 +fi + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR/.." + +echo "$VERSION" > TEMPLATE_VERSION +git add TEMPLATE_VERSION CHANGELOG.md 2>/dev/null || true +git commit -m "[skip ci] chore(release): $VERSION" || true +git tag -a "$VERSION" -m "release: $VERSION (latest)" +git push || true +git push origin "$VERSION" + +echo "Release locale préparée: $VERSION"