Files
skill-gitea/scripts/setup.sh
claudecode0 d5e1cf3696 fix: forzar PYTHONIOENCODING=utf-8 en scripts con python -c
En Windows el stdout de Python defaultea a cp1252 y crashea con
UnicodeEncodeError al imprimir literales no-ASCII (e.g. el ✓ del print
de éxito de pr-create.sh). El sintoma era que el PR se creaba OK pero
el script terminaba con exit 1 por el crash del print posterior.

Agrego export PYTHONIOENCODING=utf-8 después de set -euo pipefail en
los 10 scripts que invocan python (todos menos query.sh). Cubre tanto
las invocaciones inline como futuras sin tener que acordarse caso por
caso. Mantiene los literales unicode existentes (✓, →, ─, ⚠️).
2026-04-26 15:00:37 -06:00

185 lines
6.1 KiB
Bash

#!/usr/bin/env bash
# gitea skill — setup inicial.
#
# Idempotente. Cada corrida:
# 1. Busca el PAT en la skill bitwarden (item "claudecode0 · Gitea PAT
# claude-agent-gitops").
# 2. Si hay duplicados, toma el primero y avisa al usuario que limpie.
# 3. Escribe ~/.claude/skills/gitea/.env con BASE_URL + PAT + DEFAULT_OWNER.
# 4. Valida con GET /api/v1/version → debe responder.
#
# Re-corré esto cuando rotás el PAT en Gitea y lo guardás de nuevo en bitwarden.
set -euo pipefail
# Forzar UTF-8 en stdout de Python (Windows defaultea a cp1252 y crashea con
# literales no-ASCII). Ver memoria feedback_api_utf8_encoding.md.
export PYTHONIOENCODING=utf-8
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_FILE="$SKILL_DIR/.env"
ENV_EXAMPLE="$SKILL_DIR/.env.example"
BW_QUERY="$HOME/.claude/skills/bitwarden/scripts/query.sh"
# Matchamos por substring porque los items reales en bitwarden tienen el `·`
# doble-encodeado (corrupción histórica del web vault). El substring esquiva
# el carácter roto.
PAT_NAME_SUBSTR="Gitea PAT claude-agent-gitops"
PAT_ITEM_DESCRIPTION="claudecode0 · Gitea PAT claude-agent-gitops"
GITEA_BASE_URL="${GITEA_BASE_URL:-https://gitea.nucleoriofrio.com}"
DEFAULT_OWNER="${GITEA_DEFAULT_OWNER:-NucleOS}"
if [[ ! -x "$BW_QUERY" ]]; then
cat >&2 <<EOF
ERROR: la skill bitwarden no está configurada en $BW_QUERY.
Setup necesario primero:
bash ~/.claude/skills/bitwarden/scripts/setup.sh
Después re-corré esto.
EOF
exit 1
fi
echo "→ Buscando PAT en el vault de bitwarden (claudecode0)..."
# Search por substring corto (el `·` en el nombre URL-encoded confunde a
# bw serve). Filtramos por nombre exacto en el python downstream.
list_resp="$("$BW_QUERY" "/list/object/items?search=Gitea+PAT+claude-agent-gitops")" || {
echo "ERROR: query a bitwarden falló. ¿bw serve arriba? ¿session expirada?" >&2
echo " Probá: bash ~/.claude/skills/bitwarden/scripts/setup.sh" >&2
exit 2
}
# Filtrar matches por substring del nombre. Python lee JSON por stdin y
# el substring por env var (export antes del pipe — sino el VAR=val inline
# solo aplica al `printf`, no al `python`).
export PAT_NAME_SUBSTR
mapfile -t pat_ids < <(
printf '%s' "$list_resp" | python -c '
import json, os, sys
target = os.environ["PAT_NAME_SUBSTR"]
data = json.load(sys.stdin)
items = (data.get("data") or {}).get("data") or data.get("data") or []
if isinstance(items, dict):
items = items.get("data", [])
for it in items:
name = it.get("name", "") or ""
if target in name:
print(it.get("id", ""))
' | tr -d '\r'
)
case "${#pat_ids[@]}" in
0)
cat >&2 <<EOF
ERROR: no encontré ningún item con substring "$PAT_NAME_SUBSTR" en el nombre.
Pasos:
1. Generá un PAT en https://gitea.nucleoriofrio.com/user/settings/applications
con scopes: read:repo, write:repo, read:issue, write:issue, read:user.
2. Guardalo en bitwarden con un nombre que contenga "$PAT_NAME_SUBSTR".
(Idealmente: "$PAT_ITEM_DESCRIPTION".)
3. Re-corré este setup.
EOF
exit 3
;;
1)
pat_id="${pat_ids[0]}"
;;
*)
pat_id="${pat_ids[0]}"
cat >&2 <<EOF
⚠️ Hay ${#pat_ids[@]} items en bitwarden con substring "$PAT_NAME_SUBSTR".
Tomé el primero (id: $pat_id). Si no es el activo, este setup va a fallar
en la validación más abajo.
Limpiá los duplicados desde la web (https://vault.nucleoriofrio.com) — la
skill bitwarden bloquea DELETE así que no podemos borrarlos desde acá.
EOF
;;
esac
echo "→ Extrayendo password del item $pat_id..."
pat_value="$("$BW_QUERY" "/object/password/${pat_id}" | python -c "
import json,sys
d=json.load(sys.stdin)
v=d.get('data')
if isinstance(v, dict):
v=v.get('data')
print(v or '')
" | tr -d '\r')"
if [[ -z "$pat_value" ]]; then
echo "ERROR: el item existe pero el password vino vacío. Revisá en web." >&2
exit 4
fi
echo "→ Escribiendo $ENV_FILE..."
{
echo "# gitea skill — generado por setup.sh"
echo "# NO editar a mano (re-corré setup.sh para refrescar el PAT)."
echo ""
echo "GITEA_BASE_URL=$GITEA_BASE_URL"
echo "GITEA_PAT=$pat_value"
echo "GITEA_DEFAULT_OWNER=$DEFAULT_OWNER"
} > "$ENV_FILE"
chmod 600 "$ENV_FILE" 2>/dev/null || true
echo "→ Validando con GET /api/v1/version..."
version_resp="$(GITEA_PAT="$pat_value" GITEA_BASE_URL="$GITEA_BASE_URL" \
curl -sS -m 10 \
-H "Authorization: token $pat_value" \
-H "Accept: application/json" \
"${GITEA_BASE_URL}/api/v1/version")" || {
echo "ERROR: GET /version falló. ¿base URL correcta? ¿conexión?" >&2
exit 5
}
version="$(echo "$version_resp" | python -c "import json,sys; print(json.load(sys.stdin).get('version','?'))" 2>/dev/null || echo "?")"
if [[ "$version" == "?" || -z "$version" ]]; then
cat >&2 <<EOF
ERROR: el server respondió pero no pude parsear la versión.
Respuesta cruda:
$version_resp
Posibles causas:
- PAT inválido / revocado (limpiá el duplicado en bitwarden)
- Base URL mal en .env
EOF
exit 6
fi
# Sanity check del user actual con el PAT — capturamos el login para
# escribirlo a .env (lo usa repo-create.sh para detectar user vs. org).
user_resp="$(curl -sS -m 10 \
-H "Authorization: token $pat_value" \
-H "Accept: application/json" \
"${GITEA_BASE_URL}/api/v1/user")"
username="$(echo "$user_resp" | python -c "import json,sys; print(json.load(sys.stdin).get('login','?'))" 2>/dev/null || echo "?")"
if [[ "$username" != "?" && -n "$username" ]]; then
# Append/replace GITEA_BOT_USER en .env
if grep -q '^GITEA_BOT_USER=' "$ENV_FILE" 2>/dev/null; then
# Reemplazar línea existente (sed -i no es portable en Git Bash, usar archivo temp)
grep -v '^GITEA_BOT_USER=' "$ENV_FILE" > "$ENV_FILE.tmp"
echo "GITEA_BOT_USER=$username" >> "$ENV_FILE.tmp"
mv "$ENV_FILE.tmp" "$ENV_FILE"
else
echo "GITEA_BOT_USER=$username" >> "$ENV_FILE"
fi
chmod 600 "$ENV_FILE" 2>/dev/null || true
fi
echo ""
echo "→ Listo: Gitea $version | user=$username | $GITEA_BASE_URL"
echo ""
echo "Próximos pasos:"
echo " bash $SKILL_DIR/scripts/query.sh /version"
echo " bash $SKILL_DIR/scripts/pr-list.sh NucleOS/nucleo-infra"
echo " bash $SKILL_DIR/scripts/actions-list-runs.sh NucleOS/nucleo-infra"