From 140b3bd16fadb19ecbe25f71213426fdfe939d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 20:04:35 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20cadence=207=E2=80=9313=20min=20jitter;?= =?UTF-8?q?=20commit=20often,=20push=20only=20at=20end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Soft range instead of fixed 9m; helper defaults to no push. --- scripts/git-cadence-commit-push.sh | 107 ++++++++++++------ .../taler-monitoring/GIT-AUTOMATION-NOTES.md | 42 ++++--- 2 files changed, 94 insertions(+), 55 deletions(-) diff --git a/scripts/git-cadence-commit-push.sh b/scripts/git-cadence-commit-push.sh index 1276fc1..9775bef 100755 --- a/scripts/git-cadence-commit-push.sh +++ b/scripts/git-cadence-commit-push.sh @@ -1,22 +1,24 @@ #!/usr/bin/env bash -# git-cadence-commit-push.sh — optional WIP commit + push on the historical cadence +# git-cadence-commit.sh — optional local WIP commit on a soft cadence # -# Model (from koopa-admin-log / francpaysan-admin-log histories, 2026-07): -# - message: area: short description (monitoring: … / landings: … / docs: …) -# - size: small logical steps, not giant dumps -# - interval: about **7–11 minutes** while work is in progress (sometimes denser) -# - push: after each commit when the remote accepts credentials +# Model (koopa-admin-log / francpaysan-admin-log histories + ops preference): +# - message: area: short description +# - size: small logical steps; **prefer more commits over few** +# - interval: soft range **7–13 minutes** while work is open (not a strict timer; +# denser bursts of 0–2 min are fine for tiny follow-ups) +# - push: **only at the end of a work session** (CADENCE_PUSH=1), never by default # # Usage: -# ./scripts/git-cadence-commit-push.sh # this repo +# ./scripts/git-cadence-commit-push.sh # commit only if dirty # ./scripts/git-cadence-commit-push.sh /path/to/repo # CADENCE_MSG='monitoring: wip ladder' ./scripts/git-cadence-commit-push.sh -# CADENCE_DRY=1 ./scripts/git-cadence-commit-push.sh # show only +# CADENCE_DRY=1 ./scripts/git-cadence-commit-push.sh +# CADENCE_PUSH=1 ./scripts/git-cadence-commit-push.sh # explicit push (end of work) +# CADENCE_MIN_AGE_S=420 # skip if last commit younger than this (default 0) # -# Cron / agent every ~9 min: -# */9 * * * * $HOME/src/koopa/koopa-admin-log/scripts/git-cadence-commit-push.sh -# */9 * * * * $HOME/src/koopa/koopa-admin-log/scripts/git-cadence-commit-push.sh \ -# $HOME/taler/src/francpaysan-admin-log +# Soft timer (7–13 min, not fixed): fire often, skip until age ∈ [7,13] min target. +# # agent/cron every 7m — script enforces random target in range when CADENCE_JITTER=1 +# CADENCE_JITTER=1 ./scripts/git-cadence-commit-push.sh # set -euo pipefail @@ -28,7 +30,14 @@ REPO="$(cd "$REPO" && pwd)" cd "$REPO" CADENCE_DRY="${CADENCE_DRY:-0}" -# Never auto-add secrets +# Push only when explicitly requested (end of session) — default OFF +CADENCE_PUSH="${CADENCE_PUSH:-0}" +# Soft range 7–13 minutes (seconds) +CADENCE_RANGE_MIN_S="${CADENCE_RANGE_MIN_S:-420}" # 7 min +CADENCE_RANGE_MAX_S="${CADENCE_RANGE_MAX_S:-780}" # 13 min +CADENCE_JITTER="${CADENCE_JITTER:-0}" +CADENCE_MIN_AGE_S="${CADENCE_MIN_AGE_S:-0}" + SKIP_GLOBS=( 'secrets.env' '**/secrets.env' @@ -47,29 +56,66 @@ branch=$(git rev-parse --abbrev-ref HEAD) remote=$(git remote 2>/dev/null | head -1 || true) : "${remote:=origin}" -# Dirty? (tracked + untracked, ignoring unreadable) +# Jitter: only proceed if last commit is at least a random target in [7,13] min +if [ "$CADENCE_JITTER" = "1" ]; then + last=$(git log -1 --format=%ct 2>/dev/null || echo 0) + now=$(date +%s) + age=$((now - last)) + # stable-ish target per hour so repeated 7m fires don't all commit + target=$(python3 -c " +import random, time +random.seed(int(time.time()) // 60) # changes every minute +print(random.randint(${CADENCE_RANGE_MIN_S}, ${CADENCE_RANGE_MAX_S})) +" 2>/dev/null || echo 600) + if [ "$age" -lt "$target" ]; then + echo "jitter wait · age=${age}s < target=${target}s (range ${CADENCE_RANGE_MIN_S}-${CADENCE_RANGE_MAX_S}s) · $REPO" + exit 0 + fi +elif [ "${CADENCE_MIN_AGE_S}" -gt 0 ] 2>/dev/null; then + last=$(git log -1 --format=%ct 2>/dev/null || echo 0) + now=$(date +%s) + age=$((now - last)) + if [ "$age" -lt "$CADENCE_MIN_AGE_S" ]; then + echo "min-age wait · age=${age}s < ${CADENCE_MIN_AGE_S}s · $REPO" + exit 0 + fi +fi + +do_push() { + local ahead + ahead=$(git rev-list --count "${remote}/${branch}..HEAD" 2>/dev/null || echo 0) + if [ "${ahead:-0}" -le 0 ]; then + echo "nothing to push · $REPO · $branch" + return 0 + fi + echo "ahead of ${remote}/${branch} by $ahead" + if [ "$CADENCE_DRY" = "1" ]; then + echo "DRY: git push $remote $branch" + return 0 + fi + if [ "$CADENCE_PUSH" != "1" ]; then + echo "skip push (CADENCE_PUSH!=1 — push only at end of work)" + return 0 + fi + git push "$remote" "$branch" || { + echo "WARN: push failed for $REPO ($remote $branch)" >&2 + return 0 + } + echo "pushed · $remote $branch" +} + +# Clean working tree → maybe push only if git diff --quiet && git diff --cached --quiet \ && [ -z "$(git ls-files --others --exclude-standard)" ]; then echo "clean · $REPO · $branch (nothing to commit)" - # still try push if ahead - ahead=$(git rev-list --count "${remote}/${branch}..HEAD" 2>/dev/null || echo 0) - if [ "${ahead:-0}" -gt 0 ]; then - echo "ahead of ${remote}/${branch} by $ahead — push" - if [ "$CADENCE_DRY" = "1" ]; then - echo "DRY: git push $remote $branch" - else - git push "$remote" "$branch" || echo "WARN: push failed (auth?)" >&2 - fi - fi + do_push exit 0 fi -# Stage safe paths only git add -A for g in "${SKIP_GLOBS[@]}"; do git reset -q -- "$g" 2>/dev/null || true done -# unstage anything still matching secret names while IFS= read -r f; do case "$f" in *secret*|*password*|*token*|secrets.env) @@ -83,7 +129,6 @@ if git diff --cached --quiet; then exit 0 fi -# Message from paths (historical area: style) msg="${CADENCE_MSG:-}" if [ -z "$msg" ]; then files=$(git diff --cached --name-only | head -20) @@ -103,14 +148,10 @@ fi if [ "$CADENCE_DRY" = "1" ]; then echo "DRY commit: $msg" git diff --cached --stat - echo "DRY push: $remote $branch" + [ "$CADENCE_PUSH" = "1" ] && echo "DRY push: $remote $branch" || echo "DRY: no push" exit 0 fi git commit -m "$msg" echo "committed · $msg" -if ! git push "$remote" "$branch"; then - echo "WARN: push failed for $REPO ($remote $branch) — commit is local" >&2 - exit 0 -fi -echo "pushed · $remote $branch" +do_push diff --git a/scripts/taler-monitoring/GIT-AUTOMATION-NOTES.md b/scripts/taler-monitoring/GIT-AUTOMATION-NOTES.md index fe6fd1c..c4f11db 100644 --- a/scripts/taler-monitoring/GIT-AUTOMATION-NOTES.md +++ b/scripts/taler-monitoring/GIT-AUTOMATION-NOTES.md @@ -9,49 +9,47 @@ default ops laptop yet. ## Git commit / push cadence (existing model) -Observed in `koopa-admin-log` and `francpaysan-admin-log` histories -(active work on 2026-07-17): +Observed in `koopa-admin-log` / `francpaysan-admin-log` histories, plus ops preference: | Rule | Practice | |------|----------| -| **Interval** | About **7–11 minutes** between publishable steps while a topic is open (bursts of 0–2 min are fine for tiny follow-ups) | -| **Message** | `area: short description` — e.g. `monitoring: …`, `landings: …`, `docs: …`, `scripts: …`, `todo: …` | -| **Size** | One logical change (or a tight bundle), not end-of-day megacommits | -| **Push** | After each commit when the remote accepts auth (`git push origin …`) | +| **Commits** | **Prefer frequent** small commits over rare large ones | +| **Interval** | Soft range **7–13 minutes** while a topic is open — **not** a fixed 9‑minute metronome; denser 0–2 min bursts for tiny follow-ups are fine | +| **Message** | `area: short description` — e.g. `monitoring: …`, `landings: …`, `docs: …` | +| **Push** | **Only at the end of a work session** (`CADENCE_PUSH=1` or manual `git push`) — not after every commit | ### Agent / human workflow -1. Finish a small slice of work. -2. `git status` / diff → commit with the area-prefix style. -3. `git push` (or run the helper below). -4. Continue; next commit window ~**7–11 min** later (or sooner if the next slice is ready). +1. Finish a small slice → commit (`area: …`). Repeat often. +2. Do **not** push after each commit. +3. When the topic/session is done → one `git push` (or `CADENCE_PUSH=1`). +4. Soft next-commit window: about **7–13 min** (jitter), sooner if the next slice is ready. ### Helper script -From the admin-log root: - ```bash # dry-run CADENCE_DRY=1 ./scripts/git-cadence-commit-push.sh -# commit + push this repo if dirty (skips secrets.env / *password* / *token*) +# commit only if dirty (default: no push; skips secrets) ./scripts/git-cadence-commit-push.sh - -# other checkout ./scripts/git-cadence-commit-push.sh ~/taler/src/francpaysan-admin-log + +# end of session — push commits that are already local +CADENCE_PUSH=1 ./scripts/git-cadence-commit-push.sh + +# soft timer: only commit if last commit age ≥ random target in 7–13 min +CADENCE_JITTER=1 ./scripts/git-cadence-commit-push.sh ``` -Optional timer (every 9 min ≈ mid of 7–11): +Optional user cron (check every 7 min; **jitter** keeps effective gaps in **7–13 min**): ```bash -# user crontab example -*/9 * * * * $HOME/src/koopa/koopa-admin-log/scripts/git-cadence-commit-push.sh >>$HOME/.cache/git-cadence-koopa.log 2>&1 -*/9 * * * * $HOME/src/koopa/koopa-admin-log/scripts/git-cadence-commit-push.sh $HOME/taler/src/francpaysan-admin-log >>$HOME/.cache/git-cadence-lfp.log 2>&1 +*/7 * * * * CADENCE_JITTER=1 $HOME/src/koopa/koopa-admin-log/scripts/git-cadence-commit-push.sh >>$HOME/.cache/git-cadence-koopa.log 2>&1 ``` -**Auth note (this host):** `francpaysan-admin-log` → `ssh://git@git.gnunet.org/…` works. -`koopa-admin-log` → `https://git.hacktivism.ch/…` needs credentials / SSH key for -`git.hacktivism.ch` (push may stay local until that is fixed). +**Auth note:** `francpaysan-admin-log` (gnunet SSH) pushes OK. +`koopa-admin-log` (hacktivism HTTPS) needs credentials/SSH key before end-of-session push works from this host. ## What runs without Android