Un sync Gitea qui « réussit » (HTTP 200/201, zéro log d’erreur) mais dont le résultat est vide ou faux : le pire scénario, aucun feedback. 3 pièges qui m’ont coûté des heures, et la méthode.
Piège 1 : "user does not exist [uid: 0, name: ]" = token invalide
L’erreur cryptique de Gitea quand le PAT du header Authorization: token X n’est plus valide. Pas « 401 », pas « auth failed » : un message qui suggère un user supprimé. Vrai diag : le PAT a été régénéré (l’ancien invalidé aussitôt). Si plusieurs serveurs le consomment (nas + srv-a), les mettre TOUS à jour.
curl -H "Authorization: token $TOKEN" $GITEA_URL/api/v1/user
# 200 + JSON → OK | 401 → rejeté | 200 + user vide → régénéré entre-temps
Piège 2 : /repos/search?owner=X ignore le filtre
GET /api/v1/repos/search?owner=perso retourne tous les repos visibles, pas ceux de l’org perso : owner est une « préférence », pas un filtre strict. Le script reçoit aussi github-mirror et toute org accessible, puis tente de cloner http://gitea/perso/<repo>.git inexistant → « target couldn’t be found ». Fix : filtrer côté script.
filtered = [r for r in data if r['owner']['login'] == 'perso']
L’alternative /orgs/<org>/repos filtre strict mais demande read:organization.
Piège 3 : compteur bash dans while ... | ... toujours à 0
n=0; echo "$LIST" | while read -r repo; do n=$((n+1)); done; echo "n=$n" # toujours 0 !
Le pipe crée un subshell : les variables modifiées y sont perdues à la sortie. Mes logs total=0 étaient mensongers — tous les repos étaient traités. Fix : process substitution.
n=0; while read -r repo; do n=$((n+1)); done < <(echo "$LIST"); echo "n=$n" # vrai compteur
La méthode : ne jamais faire confiance aux logs Gitea
Gitea renvoie 200/201 même quand l’opération est partiellement ignorée (cas mirror=true + issues=true, cf. lkd/39). Le seul état qui ne ment pas, c’est la SQLite :
docker exec gitea sqlite3 /data/gitea/gitea.db "SELECT COUNT(*) FROM issue WHERE repo_id=...;"
docker logs gitea --since 1m | grep -iE "error|warn|failed" # Gitea logue plus que son JSON
Lessons learned
"user does not exist [uid: 0, name: ]"= token invalide. Régénérer un PAT Gitea invalide l’ancien : propager partout./repos/search?owner=Xne filtre pas strict — filtrer côté script surowner.login.while read | ...= subshell — utiliserwhile read; do; done < <(...)pour garder les variables.- HTTP 200 ne dit rien — valider en SQL direct après tout sync. Tester l’API à la main avant de scripter : 5 min économisent des heures.
- Pattern destroy/recreate + state file
<repo>.ts: idempotent, skip siupdated_atidentique. Le contrat entre 2 runs.