Exportar el estado
ajat export escribe cada regla de Automation de tu tenant de Jira Cloud en un árbol de directorios de archivos JSON consciente del alcance, más un archivo de estado que impulsa las reejecuciones incrementales. El objetivo no es solo la recuperación ante desastres: la exportación se convierte en el inventario base para entender cómo está distribuido Jira Automation entre los alcances global, de proyecto, multiproyecto y otros.
Este es el flujo operativo principal de ajat y la base sobre la que se construyen los demás comandos. Los informes, diff, search y las operaciones masivas de rule leen todos el árbol local que produce este comando.
ajat es compatible solo con Atlassian Jira Cloud Automation. No es compatible con Jira Server ni con Jira Data Center.
Si estás configurando ajat por primera vez, empieza por Instalación y configuración inicial, que va desde la instalación hasta tu primera exportación e informe de inventario.
Los sitios grandes de Jira suelen acumular automatización durante años. Distintos equipos crean reglas, las copian entre proyectos y las amplían a alcance multiproyecto o global a medida que crecen los procesos de negocio. ajat export captura ese estado completo en una única ejecución repetible para que los equipos puedan revisar la malla de automatización desde disco en lugar de saltar entre pantallas de administración de proyectos.
Primera exportación
ajat export --output-dir ./jira-automations-backup--output-dir es obligatorio y debe indicarse explícitamente. El comando primero pagina el endpoint de resumen de reglas de Automation de Jira para construir la lista de trabajo completa y luego descarga cada regla de forma concurrente.
🔍 Fetching rules...
📥 Fetched 100 rule(s)...
📥 Fetched 200 rule(s)...
...
📥 Fetched 951 rule(s) ✅
Discovered 951 rule(s)
Exporting rules ... 23.66% [225 in 2.1s; ~ETA: 7s]El banner de descubrimiento, la barra de progreso por regla y las líneas de estado por regla van todas a stderr, por lo que redirigir stdout (por ejemplo a tee, jq o un archivo) se mantiene limpio.
export es un comando de solo lectura. Nunca modifica Jira — solo lee
definiciones de reglas y, por defecto, resuelve los account ID que esas reglas
referencian.
Estructura en disco
Las reglas se escriben en un árbol consciente del alcance para que puedas responder preguntas básicas de gobernanza antes de abrir un informe: qué reglas son globales, qué proyectos tienen reglas locales, qué automatizaciones abarcan más de un proyecto y qué definiciones requieren una inspección más detallada.
<output-dir>/
├── .ajat_state.json # estado incremental
├── .ajat_external_directory.json # directorio de cuentas (omitido con --resolve-users=false)
├── global/
│ └── <uuid>__<rule-name>.json # reglas sin ARI de alcance
├── projects/
│ └── <KEY>__<Project-Name>/
│ ├── <uuid>__<rule-name>.json # reglas de un solo proyecto
│ └── <uuid>__<rule-name>.external-info.json # identidades resueltas (omitido con --resolve-users=false)
├── multi-project/
│ └── <KEY1>__<Name1>__<KEY2>__<Name2>__and-N-more/
│ └── <uuid>__<rule-name>.json # reglas multiproyecto
└── other-scope/
└── <uuid>__<rule-name>.json # reglas con ARI de alcance no de proyectoLos nombres de archivo se normalizan (NFKD a ASCII, caracteres especiales a -) para que el árbol sea seguro en Linux y macOS.
Para las reglas multiproyecto, las etiquetas de proyecto en el nombre del directorio se ordenan alfabéticamente. La API de Atlassian no garantiza un orden estable para ruleScopeARIs entre respuestas, así que el ordenamiento hace la ruta determinista entre ejecuciones — que es también lo que hace funcionar el salto incremental.
Modos incremental y sync
Reejecutar con el mismo --output-dir solo vuelve a descargar las reglas cuyo timestamp updated ha cambiado en el listado upstream. Las reglas ya en disco con el mismo updated se omiten. Dos flags mutuamente excluyentes controlan cómo se tratan las reglas que han desaparecido del listado upstream:
| Flag | Predeterminado | Efecto en reglas cambiadas | Efecto en reglas eliminadas de Jira |
|---|---|---|---|
--incremental | true | Redescarga solo reglas cambiadas | Tumba en el estado (status: deleted); el archivo JSON local se conserva |
--sync | false | Redescarga solo reglas cambiadas | Tumba en el estado y elimina el archivo JSON local |
# Predeterminado: incremental, conserva en disco las reglas eliminadas para auditoría
ajat export --output-dir ./jira-automations-backup
# Modo sync: refleja upstream exactamente, incluidas las eliminaciones
ajat export --output-dir ./jira-automations-backup --sync
# Desactiva el estado por completo: redescarga cada regla, sin reconciliación de huérfanos
ajat export --output-dir ./jira-automations-backup --sync=false --incremental=falseEl --incremental por defecto conserva en disco los archivos con tumba porque la automatización eliminada puede formar parte de la historia de auditoría — un flujo que cambia, un proyecto que se retira, una limpieza que hay que revisar. Cambia a --sync cuando quieras que el árbol en disco refleje Jira exactamente, por ejemplo cuando la exportación alimenta un pipeline downstream que nunca debería ver reglas obsoletas.
Esto refleja el modelo --sync / --incremental que usa el comando
space convert de la herramienta prima acs2md: --sync
elimina archivos locales para las eliminaciones upstream, --incremental los
conserva.
Elegir un modo
| Escenario | Modo recomendado |
|---|---|
| Archivo de cumplimiento o auditoría que debe retener reglas eliminadas | --incremental |
| Espejo en vivo que alimenta un pipeline downstream | --sync |
| Copia de seguridad respaldada en Git que debe seguir a Jira exactamente | --sync |
| Copia de continuidad conservadora que nunca pierde historial | --incremental |
El archivo de estado
El archivo de estado (.ajat_state.json) registra qué se descargó, cuándo y con qué resultado. Se escribe como una sola línea de JSON, lo que lo mantiene amigable con git diff y con herramientas grep que esperan un registro por línea.
Cuando --sync o --incremental está activo, el bloque de resumen final imprime la ruta resuelta del archivo de estado, para que sea fácil copiarla a un depurador o a un comando grep:
Export complete
discovered : 951
downloaded : 12
skipped : 939
failed : 0
deleted : 0
elapsed : 8.3s
output : /Users/me/jira-automations-backup
state file : /Users/me/jira-automations-backup/.ajat_state.json
external : /Users/me/jira-automations-backup/.ajat_external_directory.jsonLa línea state file se omite cuando el seguimiento de estado está desactivado (--sync=false --incremental=false). La línea external se muestra solo cuando se solicitó --resolve-users.
Por defecto el archivo de estado vive en <output-dir>/.ajat_state.json. Anula su ubicación con --state-file solo si necesitas un estado no colocado junto a la salida.
Reanudabilidad
.ajat_state.json se reescribe de forma atómica (archivo temporal y luego rename(2)) después de cada regla que el exportador procesa — descarga correcta, fallo o reclasificación de alcance. No hay un volcado de fin de ejecución que puedas perder: si pulsas Ctrl-C, o el proceso se termina, o el portátil se queda sin batería, cada regla que terminó está de forma duradera en disco con status: "downloaded", y la siguiente ejecución la omite.
Las reglas que terminaron en status: "failed" se reintentan en la siguiente ejecución. El reintento conserva el campo last_error previo en el estado hasta que la regla tiene éxito, por lo que el archivo de estado es también el registro de auditoría de lo que está roto actualmente.
Para forzar una redescarga completa conservando los archivos JSON, elimina
solo .ajat_state.json y reejecuta. Para empezar completamente de cero,
elimina todo el directorio de salida. También puedes ignorar el estado en una
sola ejecución con --sync=false --incremental=false.
¿Por qué se está redescargando una regla?
Si esperabas que una reejecución incremental omitiera casi todo y el contador de descargas sube rápido, pasa -v (--debug-changes). Cada regla que falla la comprobación de salto se imprime con el motivo exacto:
↻ redownloading "Triage Bugs" — updated 1.6739e+09 → 1.6741e+09
↻ redownloading "Onboarding" — path projects/X/... → projects/Y/...
↻ redownloading "Audit Log" — local file missing
↻ redownloading "Send Slack" — prior status: failed| Motivo | Qué significa |
|---|---|
new | El archivo de estado no tiene entrada para este UUID (se cuenta como una descarga). |
prior status: <X> | La ejecución anterior no terminó como downloaded (p. ej. failed), así que la regla se reintenta. |
updated <a> → <b> | Jira reporta un timestamp updated más fresco que el que recuerda el estado. |
path <old> → <new> | El directorio derivado del alcance de la regla cambió (proyecto renombrado, ARI de alcance añadido o eliminado). |
local file missing | El estado dice que la regla se descargó, pero el archivo JSON ya no está en disco. |
Deja -v desactivado en ejecuciones rutinarias — el conteo en curso y el resumen final son suficientes — y actívalo al investigar rotación.
Resolver identidades de usuario
Cada regla exportada está llena de account ID opacos de Jira — el autor de la regla, la identidad con la que se ejecuta (actor), sus colaboradores y cualquier account ID enterrado en la configuración de los componentes. Por sí solos se leen como 712020:9c32… y no dicen nada.
ajat los convierte en identidades legibles automáticamente. --resolve-users está activado por defecto, porque los nombres resueltos son lo que hace realmente legibles la copia de seguridad y los informes:
# La resolución se ejecuta como parte de una exportación normal — sin flag extra.
ajat export --output-dir ./jira-automations-backup
# Desactívala cuando solo quieras el JSON crudo de las reglas, o el token carezca
# del scope read:jira-user:
ajat export --output-dir ./jira-automations-backup --resolve-users=falseCuando está activado, una fase posterior a la descarga recopila cada account ID distinto referenciado a lo largo de la ejecución, los resuelve en una única pasada por lotes, concurrente y cacheada (un tenant con cientos de reglas pero un puñado de cuentas distintas cuesta aproximadamente un viaje de ida y vuelta) y escribe las identidades resueltas junto a cada regla. El JSON de la regla exportada nunca se modifica, por lo que la copia de seguridad sigue siendo una copia byte a byte de lo que Jira devolvió.
Se producen dos tipos de archivo:
- Sidecar por regla
<uuid>__<rule-name>.external-info.json, escrito junto a la regla que describe. Registra el autor de la regla, el actor, los colaboradores y las referencias de componentes, cada uno con el nombre resuelto, el tipo de cuenta (atlassian/app/customer), el indicador de actividad y — donde aparece — la ruta JSON dentro de la regla. Los sidecars se imprimen con formato porque están pensados para leerse a mano junto a cada regla. - Índice de directorio
.ajat_external_directory.jsonen la raíz de salida: un mapaaccountId → identitya nivel de tenant más un conteo por cuenta de cuántas reglas la referencian, para que los informes y las herramientas puedan responder “¿quién posee más automatización?” sin abrir cada sidecar. Como.ajat_state.json, se escribe como una sola línea de JSON.
Los account ID que la API no puede resolver — cuentas desactivadas, eliminadas o de app que el token no puede ver — se registran como marcadores no resueltos ("resolved": false) en lugar de hacer fallar la ejecución. El enriquecimiento es aditivo, idempotente y reejecutable: cada archivo lleva un schemaVersion y una marca de tiempo resolvedAt, así que reejecutar --resolve-users refresca los nombres cambiados sin volver a descargar reglas. Cualquier fallo de enriquecimiento se registra pero nunca hace fallar la copia de seguridad — el JSON de la regla ya está a salvo en disco para entonces.
ajat report inventory recoge estos sidecars automáticamente: nombres resueltos de actor y autor, un panel de Top authors y filas de Author / Collaborators por regla. Las copias de seguridad exportadas sin --resolve-users se renderizan exactamente como antes.
Los sidecars almacenan nombres y — cuando Jira los expone — direcciones de correo por diseño. Trata una copia de seguridad enriquecida como si contuviera datos personales y compártela en consecuencia. Las direcciones de correo suelen estar ocultas por la configuración de privacidad de Atlassian y simplemente no aparecerán cuando sea el caso.
Flags comunes
| Flag | Short | Predeterminado | Descripción |
|---|---|---|---|
--output-dir | obligatorio | Directorio raíz del árbol JSON — debe indicarse explícitamente | |
--state-file | <output-dir>/.ajat_state.json | Anula solo si necesitas un estado no colocado junto a la salida | |
--page-size | 100 | Tamaño de página del resumen de Jira (1..100) | |
--workers | 4 | Descargas concurrentes por regla (1..64); ver Límites de tasa | |
--redact-sensitive-fields | false | Pide a Jira que enmascare secretos en el cuerpo JSON exportado | |
--resolve-users | true | Resuelve los account ID referenciados a identidades y escribe sidecars *.external-info.json más un índice de directorio. Pasa --resolve-users=false para omitir las llamadas extra a la API read:jira-user | |
--incremental | true | Rastrea el estado, omite reglas sin cambios, conserva archivos locales de reglas eliminadas de Jira. Mutuamente excluyente con --sync | |
--sync | false | Rastrea el estado, omite reglas sin cambios, elimina archivos locales de reglas eliminadas de Jira. Mutuamente excluyente con --incremental | |
--debug-changes | -v | false | Imprime un motivo de una línea por cada regla redescargada por discrepancia de estado |
Enmascarar campos sensibles
--redact-sensitive-fields pide a Jira que enmascare secretos (como credenciales embebidas en acciones webhook o connect) en el JSON de la regla devuelto. Actívalo para exportaciones que se compartirán más allá del equipo de plataforma o que se confirmarán en un repositorio.
Informe de progreso
La etiqueta de progreso se actualiza en el sitio con el conteo en curso:
Exporting · ↓12 skip 939 fail 0 ... 99%↓N— reglas obtenidas de la API de Automation en esta ejecución.skip N— reglas cuyo estado las mostró sin cambios y cuyo archivo JSON local sigue en disco.fail N— reglas donde la llamada a la API o la escritura local falló.
Cuando --resolve-users está activo la ejecución tiene dos fases — descargar reglas y luego resolver las cuentas que referencian — y el display muestra tres barras juntas: un agregado combinado Overall, el rastreador de descargas Automations y el rastreador de enriquecimiento External info. Las tres se crean por adelantado para que el display nunca colapse entre fases.
Todo se renderiza a stderr. Suprime la barra de progreso y las líneas de descubrimiento por página por completo con el flag persistente --no-progress — útil para logs de CI/CD, scripting y grabaciones de terminal. Cada transición por regla también se registra como un evento estructurado cuando --log-file está definido, así que desactivar la barra nunca pierde información visible para el operador.
Límites de tasa y concurrencia
La API de Automation de Atlassian limita la tasa por tenant. ajat export está diseñado para replegarse limpiamente en lugar de reventar la ejecución:
- Se respeta
Retry-After. Un 429 pausa la petición ofensora durante la duración de reloj indicada (más jitter, con tope de 120 segundos por espera), luego reintenta, con un presupuesto acumulado de reintentos de 5 minutos por petición y un cinturón de seguridad de 60 intentos. - Una compuerta de repliegue compartida aparca a todos los workers en el mismo muro. Cuando un worker es limitado, los workers paralelos esperan al mismo plazo en lugar de martillar la API en sincronía. Esto es lo que hace seguros los valores altos de
--workers. X-RateLimit-NearLimit: truedispara un colchón preventivo — el pool se ralentiza durante unos 750 ms para evitar caer en una oleada de 429.- Los errores 5xx y de red reintentan de forma independiente con backoff exponencial con jitter, hasta cuatro intentos por petición.
El --workers 4 por defecto coincide con el perfil de baja concurrencia recomendado por Atlassian. Los tenants sanos suelen poder subirlo a --workers 16 sin ver 429; los tenants muy grandes o restringidos deberían considerar --workers 2. El exportador es totalmente reanudable — mata la ejecución, baja el número de workers y relánzala con el mismo --output-dir para retomar donde lo dejaste.
Códigos de salida
| Código | Significado |
|---|---|
| 0 | Cada regla descubierta se descargó u omitió correctamente |
| 1 | Fallo de bootstrap / configuración / autenticación |
| 2 | Al menos una regla falló al descargar (consulta last_error en el archivo de estado) |
| 130 | Interrumpido (SIGINT / SIGTERM) |
Exportaciones programadas
ajat export es seguro de ejecutar desde cron, GitHub Actions o cualquier otro planificador. Como es incremental y reanudable por defecto, un trabajo recurrente mantiene un inventario actualizado de forma barata.
# .github/workflows/jira-automations-backup.yaml
on:
schedule: [{ cron: "0 4 * * *" }] # 04:00 UTC diario
workflow_dispatch:
jobs:
export:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: |
# La URL de descarga viene de tu correo de pedido de Climakers; guárdala como secreto de CI.
curl -sL "${{ secrets.AJAT_DOWNLOAD_URL }}" -o ajat.zip
unzip ajat.zip && chmod +x ajat && sudo mv ajat /usr/local/bin/
- run: ajat export --output-dir ./jira-automations-backup --workers 16 --redact-sensitive-fields --no-progress
env:
AJAT_JIRA_DOMAIN: ${{ secrets.AJAT_JIRA_DOMAIN }}
AJAT_JIRA_USERNAME: ${{ secrets.AJAT_JIRA_USERNAME }}
AJAT_JIRA_API_TOKEN: ${{ secrets.AJAT_JIRA_API_TOKEN }}
- uses: actions/upload-artifact@v6
with: { name: jira-automations-backup, path: ./jira-automations-backup/ }Para CI programado, usa la edición de licencia CI/CD Automation para que la revalidación no golpee la API de licencias en cada ejecución. Consulta Licenciamiento para las ediciones.
Empareja el artefacto exportado con un trabajo downstream que ejecute Informes HTML o Comparar snapshots cuando necesites una vista fresca para revisiones de plataforma, reuniones de comité de cambios o evidencia de cumplimiento.
Lo que NO se exporta
- Historial de ejecución de reglas. Jira retiene aproximadamente 90 días de registro de auditoría; no forma parte de la definición de la regla.
- Configuración de workflow, proyecto o tablero. ajat se limita a reglas de Automation.
- Esquemas de campos personalizados. El JSON completo de la regla referencia IDs de campos personalizados pero no lleva sus esquemas.
ajat v1 es solo de exportación para copia de seguridad, auditoría y análisis. Restaurar reglas exportadas de vuelta a un tenant lo gestiona Importar y restaurar.
Relacionado
- Instalación y configuración inicial — desde la instalación hasta tu primera exportación.
- Informes HTML — convierte el árbol de exportación en informes de inventario, colisión, consistencia, riesgo y workflow.
- Comparar snapshots — compara dos directorios de exportación para revisión de deriva y compuertas de CI.
- Operaciones masivas de reglas — ejecuta selectores de etiqueta, nombre, alcance y estado contra un directorio de exportación.
- Importar y restaurar — envía un árbol de exportación de vuelta a Jira, de forma segura y con plan primero.
- Configuración — precedencia, variables de entorno y ajustes de proxy.