Ir al contenido

Git y GitHub

Thulu trabaja sobre repos de GitHub. Cada tarea recibe su propia rama, task-<id>, en cada repo que toca, y termina en un pull request por repo. Los agentes hacen los cambios; Thulu publica la rama en GitHub con la credencial del proyecto, que nunca entra al contenedor del agente, y en la tarea te muestra el estado de cada PR. Por default ningún agente mergea ni dispara deploys: un admin decide si se lo concede a un agente, tool por tool.

Funciona con GitHub y GitHub Enterprise Server. Si el código no está en GitHub, el proyecto puede ser una carpeta subida, sin proveedor ni pull requests (ver Proyectos).

Un proyecto se autentica de una de tres maneras. Las elegís al crearlo, en “Acceso al repositorio”:

Opción Qué hace Cuándo conviene
“GitHub App” Thulu pide a GitHub un token de vida corta (alrededor de una hora) para cada operación, limitado al repo del proyecto y a los permisos que esa operación necesita. No guarda nada de larga duración. Siempre que puedas. En la SaaS la App ya está registrada y sólo tenés que instalarla en tu organización.
“Credencial guardada” Usa un token personal de GitHub guardado en Credenciales. Se valida al guardarlo y se puede rotar o deshabilitar desde ahí. Self-hosted sin App, o un repo de una cuenta donde no podés instalar la App.
“Repo público” Clona sin credenciales. Para leer un repo público. Sin credencial, Thulu no puede pushear ni abrir PRs.

Si un proyecto está vinculado a la App, la App manda: el selector de credencial del proyecto queda deshabilitado y dice “La instalación de la App de arriba es la que clona y pushea. Desvinculala para usar una credencial.”

Flujo recomendado: instalar la App y crear el proyecto

Sección titulada «Flujo recomendado: instalar la App y crear el proyecto»

En la SaaS, o en un self-hosted donde el operador ya conectó la App, conectar un repo es esto. Necesitás rol admin en el workspace para crear proyectos e instalar la App, y permiso en GitHub para instalar Apps en la organización (si no lo tenés, GitHub deja pedírselo a un admin).

  1. Abrí “Proyectos” en la barra lateral y tocá “Nuevo proyecto” (o la tecla N).

  2. En “Acceso al repositorio”, la opción “GitHub App” ya viene elegida. Si no aparece, la App no está conectada en esta instalación: mirá la sección self-hosted más abajo o usá un token. Si la App todavía no está instalada en tu organización, tocá “Conectar GitHub” (con la App ya instalada en alguna organización, el botón dice “Instalar en otra organización”). Thulu te lleva a GitHub, donde elegís la organización, qué repos habilitar (todos o algunos) y confirmás la instalación.

  3. GitHub te devuelve a Proyectos con el aviso “GitHub conectado. Elegí un repositorio” y el modal abierto de nuevo, con lo que ya habías escrito. Elegí la organización y el repositorio: el nombre, la URL y la rama por defecto se completan solos.

    Modal Nuevo proyecto con GitHub App elegida, la organización acme y el repo acme/backoffice seleccionados; nombre, URL y rama por defecto completados
    Al elegir acme/backoffice, el modal completa el nombre, la URL y la rama por defecto (develop) que informa GitHub.
  4. Escribí una descripción corta (la lee el agente al arrancar), revisá el tablero por defecto y tocá “Crear”. El modal se cierra y Thulu clona el repo en segundo plano con un token de sólo lectura; guarda únicamente el vínculo a la instalación. La tarjeta del proyecto dice “Clonando” hasta que termina.

Desde ese momento, cada tarea que vincule este proyecto trabaja en su propia rama (ver Qué pasa con una tarea). Para que un agente haga el trabajo y abra el PR, la columna tiene que correr un agente que tenga argus-github; eso se arma en Tableros y etapas y Agentes.

Si la conexión falla, el aviso dice por qué: “el link de instalación venció, ya se usó o se abrió en otro navegador”, “esa instalación ya está conectada a otro workspace”, “tu usuario de GitHub no ve esa instalación”, entre otros. Si tu organización exige que un admin apruebe las Apps, vas a ver “Instalación solicitada. Falta que la apruebe el admin de tu organización en GitHub” y el repo aparece recién cuando lo aprueben.

Si creaste el proyecto con un token o como repo público y después instalaste la App, abrí el proyecto, pestaña “Repositorio”, panel “Acceso a GitHub”. Elegí la instalación en “Instalación de la GitHub App” y tocá “Vincular”: Thulu revisa que la instalación llegue al repositorio antes de guardar. Desde ahí la App manda y el selector de credencial queda deshabilitado. “Desvincular” vuelve a la credencial guardada o al acceso público; la App sigue instalada en GitHub.

Conectar la GitHub App en una instalación self-hosted

Sección titulada «Conectar la GitHub App en una instalación self-hosted»

En self-hosted, el operador registra una App propia en GitHub y le pasa sus datos a Thulu. Operador es un owner del workspace que nombra OCTOPUS_OPERATOR_WORKSPACE; thulu init apunta esa variable al primer workspace que crea. Una sola App sirve a todos los workspaces de la instalación. En la SaaS este paso ya está hecho: el panel se ve de sólo lectura y lo único que queda activo es “Instalar en una organización”.

En “Configuración” → “Credenciales”, el panel “GitHub App” ofrece “Crear la App en GitHub”. GitHub abre su formulario con los permisos, el webhook y las direcciones de esta instalación ya cargados: elegís la “Organización” (vacía, la App queda en tu cuenta personal), tildás si los agentes van a disparar workflows o aprobar deploys (suma Actions y Deployments en escritura), confirmás el nombre en GitHub y volvés con la App conectada. El nombre que propone es “Thulu” seguido del host de la instalación.

GitHub tiene que llegar a la dirección de la instalación para mandar los webhooks. Si abriste Thulu desde una dirección local o privada, el modal lo avisa: abrilo desde su dirección pública antes de crear la App.

  1. En GitHub, registrá una App en tu organización (Settings → Developer settings → GitHub Apps → New GitHub App).

    Permisos de repositorio obligatorios: Contents y Pull requests en lectura y escritura, y Actions en lectura. Cada token que Thulu pide para pushear, abrir PRs o leer su estado incluye Actions en lectura; sin ese permiso GitHub rechaza el token. Opcionales: Checks en lectura (para ver todo el CI en la tarea), Actions en escritura si los agentes van a disparar, reintentar o cancelar workflows, y Deployments en escritura sólo si vas a conceder deployment_approve.

    Como Setup URL poné https://<tu-thulu>/github/setup y tildá “Redirect on update”. Si preferís que GitHub identifique a quien instala, activá “Request user authorization (OAuth) during installation”: GitHub deja de usar la Setup URL y vuelve a la Callback URL, https://<tu-thulu>/github/oauth/callback, y en Thulu vas a cargar Client ID y Client secret. Para el webhook, https://<tu-thulu>/github/webhook con un secreto, suscripto a los eventos que vas a usar (pull request, reviews y comentarios, push, check suite, deployment status). Si la App se va a instalar en otra organización, elegí “Any account” en dónde se puede instalar.

    Al final, generá una clave privada: GitHub baja un archivo .pem.

  2. En Thulu, entrá a “Configuración” → “Credenciales”. El panel “GitHub App” dice “Sin conectar”. Tocá “Conectar una App existente”.

    Panel GitHub App en estado Sin conectar, con el texto explicativo y los botones Crear la App en GitHub y Conectar una App existente
    Sin App, cada proyecto usa un token personal de la lista de credenciales.
  3. Completá “App ID” (está en la configuración de la App, debajo de About) y pegá el .pem completo en “Clave privada”. Si activaste OAuth o el webhook, abrí “OAuth y webhook” y completá “Client ID” y “Client secret” (están en la página de la App en GitHub) o el “Secreto del webhook” que elegiste. Tocá “Verificar y conectar”: Thulu valida contra GitHub que la clave corresponda a ese App ID antes de guardar. Si a la App le falta un permiso obligatorio, el panel lo nombra (“A la App le faltan permisos que Thulu necesita…”); si le falta Checks en lectura, avisa que la sección de pull requests sólo va a ver los checks de GitHub Actions.

    Modal Conectar una GitHub App con los campos App ID, Clave privada y la sección OAuth y webhook abierta con Client ID, Client secret y Secreto del webhook
    El texto de arriba del modal pide Contents y Pull requests en escritura y Actions en lectura. OAuth y webhook son opcionales: el webhook alimenta las automatizaciones y Evidencia con eventos de GitHub y refresca la sección de PRs al instante.
  4. Con la App conectada, tocá “Instalar en una organización”. GitHub te devuelve a Proyectos con el modal “Nuevo proyecto” abierto, como en el flujo recomendado. Cada instalación aparece en la tabla del panel con su organización, si cubre todos los repos o sólo los elegidos, y su estado.

    Panel GitHub App en estado Conectada: la App thulu-tienda-ejemplo con su App ID y Client ID, los botones Quitar e Instalar en otra organización, y la instalación tienda-ejemplo activa con repositorios elegidos y el botón Desvincular
    “Desvincular” corta los tokens de esa instalación en el acto; la App sigue instalada en GitHub.

Si la App se configura por variables de entorno (OCTOPUS_GITHUB_APP_ID, OCTOPUS_GITHUB_APP_PRIVATE_KEY y las demás), el panel lo dice y no deja cambiarla desde la UI. Para GitHub Enterprise Server, el operador apunta OCTOPUS_GITHUB_URL y OCTOPUS_GITHUB_API_URL a su servidor. Los detalles de despliegue están en Operación self-hosted.

  1. Generá el token en GitHub. Un token clásico necesita el scope repo, y además workflow si los agentes van a disparar Actions.

  2. En “Nuevo proyecto”, elegí “Credencial guardada” y tocá “Nueva credencial…”. Poné un nombre (por ejemplo “GitHub — deploys”), pegá el token en “Token de acceso personal” y tocá “Guardar credencial”. Thulu lo valida contra api.github.com y lo guarda en Credenciales; si GitHub lo rechaza, queda guardado igual con el aviso de que no va a poder clonar.

  3. Completá “Nombre”, “URL del repositorio” y, si querés otra que la del repo, “Rama por defecto”, y tocá “Crear”.

Para cambiar la credencial de un proyecto que ya existe, abrilo, andá a la pestaña “Repositorio” y elegí otra en “Acceso a GitHub”. El botón “Administrar” te lleva a Credenciales, donde se crean, rotan y comparten entre proyectos. Ese recorrido está en Credenciales y motores.

Pestaña Repositorio del proyecto tienda-web con el panel Acceso a GitHub: selector de credencial en ninguna, botones Administrar y Guardar, y el aviso de que no hay credenciales de GitHub en el workspace
Sin credencial ni App, el repo tiene que ser público para clonarlo y Thulu no puede pushear.

Qué pasa con una tarea: rama, worktree y push

Sección titulada «Qué pasa con una tarea: rama, worktree y push»

Vos no creás ramas a mano. Esto es lo que hace Thulu con cada tarea que tiene proyectos vinculados:

  • Cuando la tarea sale de su primera columna, Thulu trae la última versión de la rama por defecto desde GitHub y crea la rama task-<id> con un worktree (una copia de trabajo propia) en cada proyecto vinculado. Si no pudo traerla, deja un comentario en la tarea con el commit desde el que arrancó, que puede estar atrasado.
  • Una tarea con dos repos tiene dos worktrees y termina en dos PR, uno por repo, sobre la misma rama task-<id>.
  • Las subtareas trabajan en la rama de la tarea madre y entran en su pull request. En la subtarea, “Rama y PR” dice “Compartida con la tarea madre”.
  • “Bifurcar la tarea” (menú “…” de la tarea) saca un worktree nuevo desde la rama de la original. “Clonar la tarea” copia sólo título, descripción, repos y asignaciones, sin rama.
  • Una columna con “Pushear la rama” publica la rama en GitHub cuando la corrida termina bien. En el tablero de fábrica, “In progress” la trae activada; corre el agente que le asignes a la tarea (el workspace arranca sin agentes).

Cómo llegan los commits a GitHub depende de dónde corren los agentes. No tenés que configurarlo, pero explica algunos comentarios que vas a ver en la tarea:

Desde 0.3.3, el agente trabaja en su propia copia del repo y usa git como cualquier persona: git commit, git fetch origin && git rebase origin/main y git push. El push llega a Thulu, que mueve la rama de la tarea a lo que mandó el agente y la publica en GitHub antes de devolverle el control, así el agente ya puede abrir el PR. git fetch trae lo que GitHub tiene en main (Thulu lo refresca como mucho cada 20 segundos por proyecto).

Si main avanzó, el agente rebasea y resuelve los conflictos en su copia, y Thulu publica la historia nueva con --force-with-lease. Si la rama de la tarea tiene un commit que la copia del agente no trae, Thulu no lo pisa: no publica ese proyecto y deja un comentario que empieza con “No se pudieron traer a la rama de la tarea los commits del agente…”. El token de GitHub nunca entra al pod del agente ni al sandbox.

Un commit que toca .github/workflows/ no se puede pushear con la App salvo que el operador active OCTOPUS_GITHUB_ALLOW_WORKFLOW_WRITES=1 y la App tenga el permiso Workflows en escritura: un workflow pusheado corre en los runners con los secretos del repo. Sin esa variable, GitHub rechaza el push y el error la nombra.

El agente abre el PR con su tool pr_create y la tarea lo registra en el acto (“El agente abrió un PR: …”).

Sección Actividad de la tarea Aplicar el cupón BIENVENIDA10: la corrida 1 de desarrollador terminada en 51 minutos y un comentario del agente que detalla el PR #88 de pagos-api y el #214 de tienda-web, con los archivos y tests que tocó
Al terminar la corrida, desarrollador cuenta qué PR abrió en cada repo, qué cambió y que no mergeó nada.

Hay otras dos maneras de que se abra:

  • Una columna con “Abrir un pull request” abre el PR de cada repo que todavía no lo tiene cuando una tarea entra a ella. El tablero de fábrica no tiene ninguna columna con esa opción. Para activarla, en el tablero tocá “Editar tablero”, abrí el menú ⋯ de la columna, elegí “Comportamiento” y tildá “Abrir un pull request”; se guarda al tocarla. El detalle está en Tableros y etapas.
  • “Forzar PR” hace lo mismo a mano, en cualquier etapa.
Modal Comportamiento de En curso con Agente por defecto, Avanzar cuando el agente termina y Pushear la rama tildados, y Abrir un pull request sin tildar
“Pushear la rama” publica al terminar la corrida; “Abrir un pull request” abre el PR cuando la tarea entra a la columna.

Abrí la tarea. En la columna de propiedades, “Rama y PR” muestra la rama (con un botón para copiar el nombre). Los PR tienen su propia sección, “Pull requests”, a todo el ancho de la tarea debajo de la descripción, con una fila por PR. En una subtarea la sección muestra los PR de la tarea madre. La fila resume, de izquierda a derecha: número, título, el CI como pasaron/total (con un ícono que gira mientras corre), el estado del review (ojo: revisión pendiente; tilde: aprobado; alerta: pidieron cambios) y “Listo” cuando está aprobado, el CI pasó y GitHub lo puede mergear. El borde izquierdo toma el color de lo más urgente: rojo si falló el CI, hay conflictos o pidieron cambios.

Sección Pull requests de la tarea Pagar con gift card en el checkout, con dos repos: #214 con CI 5/8 corriendo y revisión pendiente, y #88 con CI 6/6, aprobado y Listo
Una tarea con dos repos tiene dos PR sobre la misma rama.

Al tocar una fila se expande con estos datos:

Dato Qué muestra
Proyecto El proyecto de Thulu al que pertenece el PR.
Archivos, Líneas, Commits Cantidad de archivos cambiados, líneas agregadas y quitadas, y commits.
Rama task-<id> → rama base.
CI Cuántos checks pasaron, fallaron y siguen corriendo, sobre el total del último commit.
Revisión “Sin revisión pedida”, “Revisión pendiente”, “Aprobado” o “Pidieron cambios”.
Merge “Se puede mergear”, “Bloqueado por las reglas de la rama”, “Atrasado respecto de la rama base”, “Tiene conflictos con la rama base” o “GitHub todavía no lo calculó”.
Actualizado Cuándo cambió por última vez en GitHub.
Sección Pull requests desplegada con el PR #214 de tienda-web: borde rojo, CI 7 de 8 con 1 fallado, revisión pendiente y merge bloqueado por las reglas de la rama; debajo el #88 de billing-api con CI 6 de 6, aprobado y Listo
El #214 tiene el borde rojo porque falló 1 de sus 8 checks; GitHub lo bloquea hasta que pase y alguien lo apruebe. El #88 tiene el CI en verde y la aprobación, y dice Listo.

Debajo está “Abrir en GitHub”. Thulu lee estos datos con la credencial del proyecto, los guarda 30 segundos y los vuelve a pedir cada 20 segundos mientras algo se mueve (CI corriendo o review pendiente) y cada minuto si no. Con el webhook de la App activo, un evento de GitHub los refresca antes.

Si el proyecto no tiene credencial, la fila conserva el link al PR y avisa “Este proyecto no tiene credencial de GitHub.” con un link para agregar una. Si la App no tiene el permiso Checks: read, el CI cuenta sólo los jobs de GitHub Actions y la fila lo aclara.

Cuando la tarea tiene rama y ningún PR, “Rama y PR” muestra el botón “Forzar PR”. También está en el menú “…” del panel, que abrís con la tecla punto; con ese menú abierto, la P lo ejecuta. Thulu pushea la rama si hace falta y abre un PR en cada repo vinculado que no tenga uno, con el título de la tarea y, en el cuerpo, la descripción, las notas de los agentes y una línea que dice que lo abrió Thulu desde Forzar PR. Si el agente ya había abierto uno, lo vincula a la tarea.

Panel de la tarea Buscador con sugerencias mientras escribís con el botón Forzar PR debajo de la rama y un aviso: Forzar PR: el proyecto tienda-web no tiene credencial de GitHub. Elegí una en Proyecto → Repositorio → Acceso a GitHub, con el link Abrir el proyecto
Sin credencial, Forzar PR no abre nada y el aviso dice dónde elegir una.

Un proyecto subido desde una carpeta no pasa por GitHub. Si todos los proyectos de la tarea son subidos, “Forzar PR” no aparece y la fila “Rama y PR” ofrece “Integrar en…”, que lleva la rama de la tarea a la rama que elijas. Está explicado en Proyectos.

Los agentes hablan con GitHub por el MCP argus-github. Lo cablea un admin por etapa en el editor del agente (pestaña “MCP”); el detalle de esa pantalla está en MCPs y Agentes. El token se resuelve del lado del servidor en cada llamada: el agente nunca lo ve.

Se concede con Qué incluye
argus-github@read Leer PRs, su diff, archivos, comentarios, hilos de review, reviewers y CI; listar labels; ver el estado de la rama; listar workflows y corridas de Actions, sus jobs, logs y artefactos.
argus-github@write Todo lo de read, más commitear y pushear la rama de la tarea, abrir PRs, comentar, revisar, contestar y resolver hilos, manejar labels, reviewers y asignados, editar el PR, y reintentar o cancelar corridas de Actions. Es lo que necesita un agente que implementa.
Sólo por nombre pr_merge (mergear un PR), run_dispatch (disparar un workflow) y deployment_approve (aprobar un deploy que espera revisión). Ningún scope las incluye, ni write.

Por default ningún agente mergea ni deploya: un admin decide si concede pr_merge o las de deploy, y las marca una por una. Si argus-github no aparece en la pestaña “MCP” del agente, no está habilitado en el workspace: ver MCPs.

  1. Abrí “Agentes”, elegí el agente y entrá a la pestaña “MCP”.

  2. En la etapa donde querés que mergee, con argus-github activado, tocá el botón de tools de argus-github. Se abre la lista de 42 tools de esa etapa, agrupadas en Lectura, Escritura y “Deploy · se conceden por nombre”.

  3. En el grupo Deploy, tildá pr_merge y tocá “Listo”. Después, “Guardar” en el editor del agente. La etapa queda con argus-github@write+pr_merge: todo lo de write más esa tool.

    Panel lateral de tools de argus-github en la etapa En curso, 39 de 42 elegidas, con el grupo Deploy · se conceden por nombre y run_dispatch, deployment_approve y pr_merge sin tildar
    Con argus-github tildado en la etapa quedan 39 de 42: las del grupo Deploy no las cubre ningún scope y se marcan una por una.

La casilla de arriba del panel dice “Todas, menos las que se conceden por nombre”: marca todo lo que cubre un scope y deja afuera pr_merge, run_dispatch y deployment_approve.

En una corrida de tarea, el agente mergea con el token de la tarea. En un chat con “Actuar por mí”, pr_merge no se ejecuta enseguida: queda esperando que la persona lo confirme en Thulu, y el daemon lo corre con un token para esa sola llamada (ver Chat).

Un agente puede disparar un workflow, seguirlo hasta que termine y leer los logs si falla. Hace falta:

  1. Un workflow en el repo que acepte disparo manual (on: workflow_dispatch, con sus inputs si los tiene). Esto se hace en el repo, fuera de Thulu.

  2. Permiso para Actions: con la App, Actions en escritura; con un token clásico, el scope workflow. Thulu sólo pide actions:write para una corrida cuya etapa concede run_dispatch, run_rerun o run_cancel.

  3. Una etapa (por ejemplo una columna “Deploy” en tu tablero) donde el agente tenga run_dispatch por nombre, además de las tools de lectura de Actions. En la pestaña “MCP” del editor del agente, “Plantilla Deploy” concede en esa etapa argus-github@read más run_dispatch, run_watch y run_logs. A mano: argus-github@read+run_dispatch, o argus-github@write+run_dispatch si también tiene que reintentar.

  4. En el prompt de esa etapa, qué workflow disparar y con qué inputs. El agente usa workflow_view para leer los inputs, run_dispatch para dispararlo, run_watch para esperar el resultado y run_jobs con run_logs para diagnosticar una falla.

Con el webhook de la App activo, los entornos de Evidencia pueden escuchar estos deploys (el evento deployment status) y correr los casos grabados después de uno exitoso; ver Evidencia. Y los eventos de GitHub (comentario en el PR, comentario de review, review, PR, push, check suite) pueden arrancar una receta en Automatizaciones.

Lo que ves Qué pasa y cómo salir
“Este proyecto no tiene credencial de GitHub.” en la fila del PR El proyecto no tiene App ni credencial que pueda leer el repo. Vinculá una en el proyecto → “Repositorio” → “Acceso a GitHub”. Si el proyecto sí está vinculado a la App, mirá si el panel “GitHub App” de Credenciales avisa un permiso que falta (Actions en lectura es obligatorio): agregalo en GitHub y aceptá el permiso nuevo en la instalación.
Comentario “No se pudo traer de GitHub la última versión de la rama por defecto…” El fetch inicial falló (credencial vencida, App suspendida). La rama arrancó de un commit posiblemente viejo. Revisá la conexión y, si hace falta, bifurcá la tarea cuando esté arreglado.
Comentario “Falló el push automático de la rama del proyecto…” GitHub rechazó el push. Si el error nombra OCTOPUS_GITHUB_ALLOW_WORKFLOW_WRITES, el agente tocó un workflow. Si no, revisá la credencial; el agente o vos pueden reintentar con “Forzar PR”.
Comentario “No se pudieron traer a la rama de la tarea los commits del agente…” (Kubernetes) La rama de la tarea tiene un commit que la copia del agente no tiene, por ejemplo porque alguien pusheó a mano o el agente reescribió la historia con un squash. Thulu no publica ese proyecto hasta que el agente traiga ese commit.
La fila dice “Sólo GitHub Actions: agregá Checks: read a la GitHub App…” Aceptá el permiso nuevo en la configuración de la instalación en GitHub.
“Falló la conexión con GitHub (esa instalación ya está conectada a otro workspace…)” Una instalación pertenece a un solo workspace. Pedile al operador que la mueva.