Files
balam/planeacion/pruebas-jira-lectura.sh

100 lines
4.9 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Pruebas de SOLO LECTURA contra la instancia real de Jira (FAC) — Bloques 2,
# 3 (inventario), 4 y 5 de Investigacion-API-Jira.md. Ninguna llamada muta nada.
#
# Requisitos: el token en propuesta/token-jira.txt (gitignoreado) o en $JIRA_TOKEN.
# Uso: ./pruebas-jira-lectura.sh [directorio_salida]
# La salida VA FUERA DEL REPO por default (los tickets traen datos reales de
# clientes): /tmp/jira-probes-<fecha>. Al repo solo se llevan los hallazgos
# agregados, transcritos a mano a Investigacion-API-Jira.md.
set -euo pipefail
SITE="https://balam-jsm-temp.atlassian.net"
EMAIL="pedro.ayala@balamtalentoestrategico.com"
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
TOKEN="${JIRA_TOKEN:-$(cat "$REPO_DIR/propuesta/token-jira.txt" 2>/dev/null || true)}"
if [ -z "$TOKEN" ]; then
echo "ERROR: token no encontrado (propuesta/token-jira.txt o \$JIRA_TOKEN)." >&2
exit 1
fi
OUT="${1:-/tmp/jira-probes-$(date +%Y%m%d-%H%M%S)}"
mkdir -p "$OUT"
AUTH="$EMAIL:$TOKEN"
req() { # req <nombre> <ruta> — guarda body y headers, imprime status + rate limit
local name="$1" path="$2"
local hdr="$OUT/$name.headers" body="$OUT/$name.json"
local status
status=$(curl -sS -u "$AUTH" -H "Accept: application/json" \
-D "$hdr" -o "$body" -w "%{http_code}" "$SITE$path")
local rate
rate=$(grep -i "x-ratelimit" "$hdr" | tr -d '\r' | paste -sd' ' - || true)
echo "[$status] $name ${rate:-(sin headers de rate limit)}"
}
echo "== Bloque 0 · auth =="
req myself "/rest/api/3/myself"
echo "== Bloque 4 · búsqueda vigente, fields acotados y tope de maxResults =="
req search-recientes "/rest/api/3/search/jql?jql=$(python3 -c 'import urllib.parse;print(urllib.parse.quote("project = FAC ORDER BY updated DESC"))')&maxResults=10&fields=summary,status,updated,created,issuetype,reporter"
req search-tope "/rest/api/3/search/jql?jql=$(python3 -c 'import urllib.parse;print(urllib.parse.quote("project = FAC"))')&maxResults=5000&fields=id"
req search-delta "/rest/api/3/search/jql?jql=$(python3 -c 'import urllib.parse;print(urllib.parse.quote("project = FAC AND updated >= \"-20m\" ORDER BY updated ASC"))')&fields=updated"
echo "== Bloque 5 · origen de los tickets (changelog de los 8 más recientes) =="
python3 - "$OUT" <<'PY'
import json, sys, subprocess, os
out = sys.argv[1]
data = json.load(open(f"{out}/search-recientes.json"))
keys = [(i["id"], i["key"]) for i in data.get("issues", [])][:8]
open(f"{out}/ids-muestra.txt", "w").write("\n".join(f"{i} {k}" for i, k in keys))
print("muestra:", ", ".join(k for _, k in keys))
PY
while read -r id key; do
req "issue-$key" "/rest/api/3/issue/$id?expand=changelog&fields=summary,status,issuetype,created,reporter,attachment,description,resolution"
done < "$OUT/ids-muestra.txt"
echo "== Bloque 3 · transiciones con campos obligatorios (2 tickets de la muestra) =="
head -2 "$OUT/ids-muestra.txt" | while read -r id key; do
req "transitions-$key" "/rest/api/3/issue/$id/transitions?expand=transitions.fields"
done
echo "== Bloque 2 · request types faltantes (12 Facturación, 389 Automatización) =="
req requesttype-12 "/rest/servicedeskapi/servicedesk/35/requesttype/12/field"
req requesttype-389 "/rest/servicedeskapi/servicedesk/35/requesttype/389/field"
echo "== Resumen para transcribir a Investigacion-API-Jira.md =="
python3 - "$OUT" <<'PY'
import json, sys, glob, os
out = sys.argv[1]
def load(n):
try: return json.load(open(f"{out}/{n}.json"))
except Exception: return None
tope = load("search-tope")
if tope: print(f"- maxResults efectivo con 5000 pedidos: {len(tope.get('issues', []))} issues devueltos; isLast={tope.get('isLast')}")
delta = load("search-delta")
if delta is not None: print(f"- delta 20m: {len(delta.get('issues', []))} tickets actualizados en la ventana")
moves = 0
for f in sorted(glob.glob(f"{out}/issue-*.json")):
d = load(os.path.basename(f)[:-5])
if not d: continue
key = d.get("key", "?")
fields = d.get("fields", {})
hist = (d.get("changelog") or {}).get("histories", []) or (d.get("changelog") or {}).get("values", [])
key_changes = [i for h in hist for i in h.get("items", []) if i.get("field") in ("Key", "project")]
if key_changes: moves += 1
att = fields.get("attachment") or []
desc = fields.get("description")
desc_len = len(json.dumps(desc)) if desc else 0
total_hist = (d.get("changelog") or {}).get("total", len(hist))
print(f"- {key}: type={ (fields.get('issuetype') or {}).get('name') } · status={(fields.get('status') or {}).get('name')} · "
f"resolution={(fields.get('resolution') or {}).get('name') if fields.get('resolution') else None} · "
f"adjuntos={len(att)} · descripcion_adf={desc_len}B · changelog(total={total_hist}, en_expand={len(hist)})"
f"{' · ⚠️ MOVE/KEY-CHANGE detectado' if key_changes else ''}")
print(f"- tickets con move/cambio de llave en la muestra: {moves}")
print(f"\nBodies completos en: {out} (NO copiar al repo: contienen datos reales)")
PY