feat(jira): kanban backfill-jira CLI con batches + ejecutado backfill 127 cards

Subcomando 'kanban backfill-jira':
- --batch-size N --pause-sec S: procesa N cards entre pausas para no saturar Jira REST.
- --limit N: cap total.
- --column NAME: filtro case-insensitive por columna kanban.
- --dry-run: lista candidatos + counts por columna sin tocar Jira.

Walk: cards con jira_key vacio, no borradas, no archivadas, ORDER BY created_at ASC.
Por cada card: jiraHandler.Handle(card.created event) que crea issue + transition al
status del status_map + labels. Tras success/failure updateCardJiraSync persiste
jira_last_status, jira_last_sync_at, jira_last_error.

Ejecutado contra Jira DATA project: 127 issues creadas (DATA-276..DATA-402), 0 fail.
Distribucion final:
  Done: 85 (HECHO)
  In Progress: 18 (HACIENDO 7 + Bloqueadas 11, las ultimas con label 'blocked')
  IMPLEMENTADO: 14 (PNDNT FEEDBACK)
  To Do: 6 (DEUDA TECNICA)
  CREADO: 4 (IDEAS)
This commit is contained in:
egutierrez
2026-05-29 14:37:56 +02:00
parent c3cc42b350
commit cd14e81487
2 changed files with 200 additions and 0 deletions
+10
View File
@@ -55,6 +55,16 @@ func main() {
return
}
// Subcommand `kanban backfill-jira` mirrors every active kanban card that
// is not yet linked to a Jira issue into Jira, in batches.
if len(os.Args) > 1 && os.Args[1] == "backfill-jira" {
if err := runBackfillJira(os.Args[2:]); err != nil {
fmt.Fprintf(os.Stderr, "kanban backfill-jira: %v\n", err)
os.Exit(1)
}
return
}
flags := flag.NewFlagSet("kanban", flag.ExitOnError)
port := flags.Int("port", 8095, "HTTP port")
dbPath := flags.String("db", "operations.db", "SQLite database path")