Saltar al contenido principal

Documentación | Qably

Docs/Guía de integración

Documentación

Especificación técnica de la API pública de Qably. Describe los endpoints, esquemas de datos y flujos de integración disponibles.

Primeros pasos

Qably centraliza la gestión de calidad para equipos de ingeniería. La plataforma no ejecuta pruebas directamente: los resultados se generan en pipelines externos de integración continua y se envían a Qably vía HTTP. El sistema almacena las ejecuciones y consolida el historial de cambios, suites y cobertura.

Dos flujos independientes

Qably procesa dos flujos de datos desacoplados. Configurar uno no activa el otro, lo cual explica por qué ciertas vistas pueden aparecer vacías inicialmente.

PipelineEndpointCredencialLlena
Resultados de pruebasPOST /runs/ingestAPI key del proyecto (Authorization: Bearer)Suites, casos y ejecuciones en el panel principal
Cambios de códigoPOST /webhooks/scm/:providerFirma HMAC (sin API key)Historial de commits, lotes de ingesta y trazabilidad en la vista Repository
El envío de resultados de pruebas desde CI no alimenta la vista Repository, y conectar un repositorio no registra ejecuciones de prueba. Si una pantalla no muestra información, verifique cuál de los dos flujos debe suministrarla.

Requisitos previos

  • Una cuenta en Qably con al menos una organización activa.
  • Un repositorio alojado en GitHub o Bitbucket (proveedores compatibles actualmente).
  • Un pipeline de CI con capacidad de ejecutar pruebas y enviar peticiones HTTP al concluir.

1. Crear el proyecto

Cada proyecto está vinculado a una organización. Para crearlo, diríjase a Proyectos > Nuevo proyecto en la consola web.

  • Nombre (obligatorio, hasta 80 caracteres)
  • Descripción (opcional, hasta 500 caracteres)
  • Tecnologías (opcional, se autocompletan al vincular el repositorio en el siguiente paso)

No es indispensable contar con un repositorio vinculado para inicializar el proyecto. Conectar el repositorio, generar la API key y configurar el reporte en CI son pasos independientes que pueden realizarse en cualquier orden.

Los proyectos nuevos inician sin suites registradas, sin ejecuciones y con el indicador de repositorio desconectado hasta recibir la primera carga de datos.

2. Conectar el repositorio mediante el webhook del SCM

Este paso habilita el flujo de cambios de código. Qably recibe las actualizaciones mediante webhooks enviados por el proveedor del repositorio, de forma independiente a la API key del paso 3.

Selección del repositorio

  1. Inicie sesión con GitHub o Bitbucket si aún no lo ha hecho. Qably utiliza este token de OAuth para listar los repositorios accesibles en su cuenta personal y organizaciones asociadas.
  2. En la sección Integraciones del proyecto, seleccione el repositorio deseado de la lista disponible, ordenada por fecha de push reciente.
  3. Al seleccionar un repositorio no vinculado, se crea una conexión dentro de la organización y se genera su secreto de webhook. Seleccionar un repositorio previamente vinculado reutiliza la conexión existente.

Registro del webhook en el proveedor

Qably no registra webhooks de forma automática en proveedores externos. Debe agregarse manualmente en la configuración del repositorio.

  1. Obtenga el secreto ejecutando POST /connections/:id/webhook-secret desde la interfaz de la conexión. La respuesta entrega el valor en texto plano una sola vez (al crearlo o rotarlo), por lo que debe copiarse inmediatamente.
  2. En GitHub, acceda a Settings > Webhooks > Add webhook dentro del repositorio.
  3. Payload URL: https://api.qably.dev/webhooks/scm/github
  4. Content type: application/json
  5. Secret: el valor obtenido en el paso anterior
  6. Events: seleccione push como mínimo. Se recomienda marcar también pull request para registrar la actividad completa del equipo.
Qably valida cada entrega entrante contra el secreto registrado mediante una firma HMAC-SHA256 (encabezado x-hub-signature-256 en formato sha256=<hex>). Las peticiones sin firma o con firmas inválidas se rechazan con código HTTP 401.

Las conexiones de Bitbucket siguen el mismo principio, utilizando el encabezado de firma propio de Bitbucket. Actualmente, GitHub y Bitbucket son los dos proveedores compatibles.

Las entregas exitosas se reflejan de inmediato en el historial de webhooks del proveedor. En la vista Repository de Qably, el lote de ingesta y los cambios de código aparecerán tras el siguiente push o pull request.

3. Emitir una API key

Este paso habilita el flujo de resultados de pruebas, proporcionando una credencial de máquina para que el pipeline de CI reporte ejecuciones sin requerir una sesión de usuario.

  1. En la pestaña API Keys del proyecto, cree una clave asignándole un nombre identificable como "CI/CD Pipeline". Esta acción requiere rol de owner o admin en la organización.
  2. El token generado sigue la estructura qbly_<lookupId>_<secret> y se muestra una única vez en la pantalla de confirmación. Qably almacena únicamente su hash SHA-256 y no puede recuperarlo posteriormente.
  3. Guarde el valor en su proveedor de CI. En GitHub Actions, vaya a Settings > Secrets and variables > Actions > Secrets y cree el secreto de repositorio QABLY_API_KEY. Si utiliza una URL personalizada, agregue la variable QABLY_API_BASE_URL en la pestaña Variables. Nunca incluya este token en el repositorio de código.

Cada API key tiene alcance exclusivo sobre un proyecto y únicamente permite registrar ejecuciones. No tiene permisos de lectura sobre otros proyectos ni facultades administrativas sobre la organización. El proyecto destino se infiere directamente de la clave.

Revocar una clave desactiva su uso de forma inmediata pero conserva los registros históricos asociados. Es posible mantener múltiples claves activas simultáneamente para facilitar la rotación sin interrumpir los pipelines de CI.

4. Reportar resultados desde CI

Para conectar Qably a su integración continua, cree un archivo de flujo de trabajo en su repositorio (por ejemplo, .github/workflows/ci.yml). El lenguaje YAML organiza el pipeline a través de los eventos de activación on, la definición de entornos bajo jobs y la secuencia ordenada de comandos en steps para preparar el entorno, ejecutar las pruebas y enviar el reporte.

En Jest, instale jest-junit y defina JEST_JUNIT_ADD_FILE_ATTRIBUTE como "true" para que el XML incluya la ruta de archivo de cada caso de prueba, lo que permite a Qably vincular las pruebas con el código fuente. En Vitest, el reporte JUnit se genera de forma nativa indicando el reporter correspondiente en la línea de comandos.

          
            name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run tests and report to Qably
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install dependencies
        run: npm ci

      - name: Run Jest tests
        env:
          JEST_JUNIT_OUTPUT_DIR: ./reports
          JEST_JUNIT_OUTPUT_NAME: junit.xml
          JEST_JUNIT_ADD_FILE_ATTRIBUTE: 'true'
        run: npx jest --ci --reporters=default --reporters=jest-junit

      - name: Report results to Qably
        if: always()
        env:
          QABLY_API_KEY: ${{ secrets.QABLY_API_KEY }}
        run: |
          curl --fail --silent --request POST \
            "https://api.qably.dev/runs/ingest/junit?externalId=gha-${{ github.run_id }}-${{ github.job }}&source=github_actions" \
            --header "Authorization: Bearer $QABLY_API_KEY" \
            --header "Content-Type: application/xml" \
            --data-binary @./reports/junit.xml || true
          
        
La directiva if: always() en el paso de reporte es obligatoria para garantizar el envío del archivo incluso si fallaron las pruebas. El resultado del build en CI debe responder a las aserciones de la suite, sin interrumpir el registro de telemetría en Qably.

El endpoint POST /runs/ingest/junit recibe el archivo XML directo y procesa todo en el servidor. Si el reporte contiene suites o casos no registrados previamente, Qably los crea de forma automática en ese proyecto.

El parámetro externalId asegura idempotencia ante reintentos de CI. Al enlazarlo con identificadores provistos por el runner (como github.run_id y github.job), reintentar un job en GitHub Actions actualiza la ejecución previa en Qably en lugar de generar registros duplicados.

5. Verificar que llegaron los datos

Cada flujo se valida de forma independiente, dado que uno puede estar recibiendo datos mientras el otro requiere ajustes de configuración.

  • Resultados de pruebas: abra el proyecto y verifique la ejecución recién enviada por CI. El estado general del run se deriva de sus casos: cualquier prueba fallida marca el run como fallido; casos en ejecución o pendientes lo mantienen en progreso; y se considera exitoso cuando al menos un caso pasa o se omite sin fallas acompañantes.
  • Cambios de código: requiere haber completado el paso 2. La vista Repository del proyecto debe reflejar el lote de ingesta correspondiente al push o pull request más reciente.
Si los datos no se visualizan en la interfaz, consulte la sección de preguntas frecuentes para diagnosticar webhooks no registrados o variables de entorno omitidas en CI.

Reportar JUnit XML desde cualquier lenguaje

El backend de Qably procesa cualquier archivo con estructura estándar <testsuite>/<testcase>, extrayendo el resultado de cada prueba a partir de los elementos <failure>, <error> o <skipped>. Genere el reporte XML utilizando las herramientas nativas de su lenguaje y envíe el archivo resultante en su pipeline de CI.

JavaScript y TypeScript

Jest y Vitest se detallaron en el paso anterior y mantienen la misma configuración.

          
            PLAYWRIGHT_JUNIT_OUTPUT_NAME=results.xml npx playwright test --reporter=junit
          
        

El reporter de JUnit incorporado en Playwright escribe a la salida estándar a menos que se indique un archivo, ya sea mediante una variable de entorno o en el archivo de configuración.

También puede configurarse una vez en playwright.config.ts: reporter: [['junit', { outputFile: 'results.xml' }]].

mvn test escribe un reporte por clase de prueba sin ninguna bandera extra; el plugin Surefire lo hace por defecto.

PHPUnit 9 y anteriores aceptan una bandera directa por línea de comandos. PHPUnit 10 en adelante la eliminó, por lo que el archivo de salida se configura en phpunit.xml.

El paquete NuGet JunitXml.TestLogger se agrega como dependencia, y el logger se pasa por línea de comandos.

El comando sugerido para go-junit-report debe validarse con la documentación oficial de la herramienta antes de integrarlo en entornos productivos.
En Qably, la identidad de un caso dentro de una suite se define exclusivamente por el atributo name del elemento <testcase>; el atributo classname se descarta. Por lo tanto, dos pruebas denominadas test_login en clases distintas se consolidarán bajo el mismo caso.
pytest genera de forma predeterminada un único elemento <testsuite name="pytest"> para toda la sesión de pruebas, a diferencia de Jest o Vitest, que generan uno por archivo. En consecuencia, todas las pruebas de pytest se agrupan en una única suite en Qably. Para obtener una granularidad por archivo, defina junit_suite_name en la configuración de pytest o divida la ejecución en varios comandos.

Cómo nombrar tus pruebas para Qably

Qably deriva los nombres de las pruebas y suites a partir de los identificadores emitidos por el ejecutor de pruebas y la estructura de archivos del repositorio. Los títulos definidos en el código se reflejan directamente en la plataforma, convirtiendo los nombres de las pruebas en documentación técnica accesible para todo el equipo.

Las siguientes pautas de diseño ayudan a estructurar suites descriptivas y legibles:

  1. Agrupe por funcionalidad de negocio en lugar de estructuras técnicas o clases internas. Los bloques descriptivos deben reflejar la acción del usuario (por ejemplo, "Carrito de compras" en lugar de "CartServiceImpl").
  2. Redacte cada prueba combinando un verbo en presente y la condición esperada: "rechaza un token vacío", "acepta un token de hasta 500 caracteres".
  3. Limite cada prueba a un comportamiento específico. Nombres que requieren conectores como "y" suelen indicar casos compuestos que conviene independizar.
  4. Nombre el archivo según el módulo o funcionalidad que valida, ya que este nombre define el título de la suite en Qably.

Normalización automática de nombres

Durante la ingesta, Qably formatea identificadores técnicos en texto legible separando palabras en camelCase o snake_case y omitiendo prefijos comunes como "test", "spec", "prueba" o "caso". De este modo, un identificador como testTokenNull se registra en la plataforma como "Token null".

Si el nombre en el código ya está formulado como una oración (por ejemplo, "debe rechazar un token vacío"), Qably conserva la redacción intacta capitalizando únicamente la primera letra sin alterar el verbo ni recortar términos.

Qably no traduce el contenido de las pruebas. El identificador técnico actúa como clave de enlace entre el código fuente y el historial de ejecuciones. Si su equipo escribe pruebas en inglés pero opera la plataforma en español, las descripciones traducidas deben gestionarse en la documentación del caso, no en su identificador.

Un ejemplo antes y después

En lugar deEscribe
test_login_1inicia sesión con credenciales válidas
testTokenNullrechaza un token vacío
should return 400 when body is invalid and user is anonymousrechaza una solicitud con cuerpo inválido
UserServiceTest.javaregistro-de-usuarios

No es necesario renombrar pruebas existentes para comenzar a utilizar Qably. La plataforma importa los identificadores actuales y respeta cualquier ajuste manual posterior: si un miembro del equipo edita el título de un caso desde la consola, las importaciones subsecuentes preservan el valor modificado.

Referencia: POST /runs/ingest

Registra los resultados de ejecución de una suite de pruebas. Requiere autenticación mediante el encabezado Authorization: Bearer <API key del proyecto>. El proyecto y la organización se determinan a partir de la clave.

          
            curl --fail --silent \
  --request POST \
  "https://api.qably.dev/runs/ingest" \
  --header "Authorization: Bearer $QABLY_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "externalId": "gh-run-482913",
    "source": "github_actions",
    "suiteId": "suite_123",
    "name": "Checkout regression - main",
    "startedAt": "2026-09-01T10:00:00Z",
    "finishedAt": "2026-09-01T10:04:12Z",
    "commitSha": "a1b2c3d",
    "commitMessage": "fix: checkout rounding",
    "commitAuthor": "Ada Lovelace",
    "cases": [
      { "name": "Adds an item to the cart", "status": "pass" },
      {
        "name": "Applies a discount code",
        "steps": ["open cart", "apply code SAVE10"],
        "expectedResult": "total is reduced by 10%",
        "status": "fail"
      }
    ]
  }'
          
        
CampoObligatorioNotas
externalIdCadena no vacía. Clave de idempotencia para actualizar ejecuciones existentes en lugar de duplicarlas.
sourceno"api" (valor por defecto) o "github_actions".
suiteId / suiteNameexactamente unoUn suiteId inexistente devuelve 404. Un suiteName inexistente crea la suite automáticamente.
nameNombre descriptivo de la ejecución, hasta 200 caracteres.
startedAt / finishedAtnoMarcas temporales ISO 8601 con zona horaria explícita.
commitSha / commitMessage / commitAuthornoMetadatos opcionales del commit, hasta 64, 2000 y 200 caracteres respectivamente.
casesArreglo con al menos un caso de prueba.
Campo del casoObligatorioNotas
nameHasta 120 caracteres.
suiteNamenoHereda el nombre de la suite resuelta; permite conservar etiquetas adicionales (como proyectos de Playwright) para trazabilidad.
stepsnoArreglo de texto de hasta 50 elementos (máximo 500 caracteres por elemento). JUnit XML no incluye este campo, por lo que llega vacío por defecto salvo cuando se envía JSON directamente.
expectedResultnoHasta 1000 caracteres. Llega vacío por defecto al importar desde JUnit XML.
statusValores permitidos: pending, running, pass, fail, skip, blocked.
recordedAtnoMarca temporal ISO 8601 con zona horaria explícita.

El estado general de la ejecución se evalúa en el servidor y no depende de valores calculados por el cliente. Si un caso de prueba falla, la ejecución se marca como fallida. Si existen casos pendientes o en progreso sin fallos, la ejecución permanece en estado de ejecución. La ejecución finaliza como exitosa cuando al menos un caso concluye en pass o skip. Una ejecución donde todos los casos están bloqueados se califica como fallida, ya que ninguna validación fue completada.

Reutilizar la combinación de proyecto, origen y externalId actualiza los datos existentes sin crear duplicados: la lista de casos se reemplaza íntegramente y los metadatos opcionales se actualizan si se incluyen en la nueva petición. El endpoint responde 200 OK tanto en la creación inicial como en actualizaciones.

Referencia: POST /runs/ingest/junit

Permite enviar archivos JUnit XML en formato original para su análisis en el servidor. Utiliza las mismas credenciales de autenticación que POST /runs/ingest.

El cuerpo de la petición contiene el archivo XML directo con cabecera Content-Type en application/xml o text/xml (hasta 10 MB). Los parámetros de configuración se transmiten mediante la cadena de consulta (query string).

Parámetro de consultaObligatorioNotas
externalIdClave de idempotencia idéntica a POST /runs/ingest.
sourceno"api" (valor por defecto) o "github_actions".
suiteId / suiteNamenoMismas reglas de resolución que en JSON. Si se omiten ambos, el nombre de la suite se toma del atributo name en <testsuite>.
namenoSi se omite, adopta el nombre de la suite del reporte.
startedAt / finishedAt / commitSha / commitMessage / commitAuthornoCampos equivalentes a POST /runs/ingest.
curl --fail --silent \
  --request POST \
  "https://api.qably.dev/runs/ingest/junit?externalId=ci-42" \
  --header "Authorization: Bearer $QABLY_API_KEY" \
  --header "Content-Type: application/xml" \
  --data-binary @junit.xml

El título de cada caso se extrae del atributo name en <testcase>. El atributo classname solo se utiliza como valor de respaldo si name está ausente. Los archivos con sintaxis XML inválida o cuerpos vacíos reciben una respuesta HTTP 400.

Referencia: POST /webhooks/scm/:provider

El parámetro :provider acepta los valores github o bitbucket (indistinto de mayúsculas). Este endpoint no utiliza API keys: cada entrega se valida mediante el secreto HMAC configurado para la conexión del repositorio.

GitHubBitbucket
Encabezado de firmax-hub-signature-256 (formato sha256=<hex>)x-hub-signature (formato sha256=<hex>)
Encabezado de eventox-github-event: push o pull_requestx-event-key: repo:push, pullrequest:created o pullrequest:updated
Encabezado de id de entregax-github-deliveryx-request-uuid
Acciones de pull request manejadasopened, synchronizecreated, updated
RespuestaSignificado
202, { "status": "accepted" }Firma válida. Evento almacenado y encolado para su procesamiento.
202, { "status": "duplicate" }El par (proveedor, id de entrega) ya fue procesado. Las entregas repetidas son idempotentes.
202, { "status": "ignored" }Firma válida pero tipo de evento no soportado por Qably.
404Proveedor no reconocido en la ruta.
401Fallo de verificación de firma contra las conexiones del repositorio.
400Cuerpo de la petición inválido o JSON mal formado.

Límite de tasa de 60 peticiones por minuto por instancia. Los eventos aceptados se procesan en segundo plano de manera asíncrona. La respuesta HTTP confirma la recepción correcta del evento, no la conclusión de su procesamiento.

Rotación del secreto

Cada conexión almacena su propio secreto HMAC. Si el secreto en el proveedor difiere del registrado en Qably, las entregas responderán con código 401. Al solicitar la rotación, Qably genera un nuevo valor, lo almacena cifrado y lo retorna en la respuesta por única vez.

AcciónEndpointRol requerido
Rotar el secreto del webhookPOST /projects/:projectId/repository/webhook-secretowner o admin

La respuesta HTTP 201 entrega el objeto { "webhookSecret": "<64 caracteres hexadecimales>" }. Este valor debe copiarse inmediatamente en la configuración del webhook en el repositorio. El secreto anterior queda invalidado al instante. Solicitar la rotación en un proyecto sin repositorio vinculado responde con código 404.

La rotación de secretos también está disponible desde la pestaña Repositorio en la consola de Qably. Durante el lapso entre la rotación y la actualización en el proveedor, las entregas entrantes fallarán con error 401 y deberán reenviarse desde el panel de entregas del proveedor.

Referencia: API keys

Las claves siguen la estructura qbly_<lookupId>_<secret>. Incorporan un prefijo constante, un identificador público de 6 bytes para ubicar el registro y un secreto criptográfico de 32 bytes para la autenticación. Qably almacena únicamente el hash SHA-256 y realiza comprobaciones en tiempo constante. El token en texto plano no puede recuperarse tras su emisión.

AcciónEndpointRol requerido
Listar keysGET /projects/:projectId/api-keysCualquier miembro de la organización
Crear una keyPOST /projects/:projectId/api-keys (cuerpo: { "name": string })owner o admin
Revocar una keyPOST /projects/:projectId/api-keys/:id/revokeowner o admin

Las claves revocadas permanecen archivadas en el sistema para conservar la trazabilidad de las ejecuciones históricas. Se envían en el encabezado Authorization: Bearer qbly_<lookupId>_<secret>.

Referencia: variables de entorno

Variables requeridas en los entornos de CI para la integración con Qably:

VariableObligatoriaNotas
QABLY_API_KEYsí (para reportar datos)Clave de autenticación del proyecto en CI. Si no está configurada, las peticiones sin autenticar se rechazan con código 401.
QABLY_API_BASE_URLnoPor defecto apunta a https://api.qably.dev. Puede configurarse para instancias privadas o pruebas locales contra http://localhost:3001.

Notificar por Discord o Slack

Qably puede enviar alertas a canales de Discord o espacios de trabajo de Slack ante eventos de ejecuciones fallidas o exitosas, regresiones de casos, fallos de ingesta y cambios en credenciales de conexión. Los webhooks se gestionan en las plataformas de destino; Qably únicamente despacha las notificaciones hacia la URL configurada.

Logo de DiscordDiscord
Logo de SlackSlack
Si un webhook se elimina o regenera en Discord o Slack, las entregas fallarán hasta que se actualice la URL en la configuración de Qably o se desvincule el canal.

Obtener una URL de webhook de Discord

  1. En el servidor de Discord donde desea recibir alertas, abra Configuración del servidor > Integraciones > Webhooks.
  2. Seleccione Nuevo Webhook, asigne el canal deseado y copie la URL generada.

Obtener una URL de webhook de Slack

  1. Cree o configure una aplicación en api.slack.com/apps y active la función Incoming Webhooks.
  2. Instale la app en su espacio de trabajo, seleccione el canal y copie la URL asignada por Slack.

Conectarlo a Qably

  1. En Configuración > Integraciones, dentro de Canales de notificación del equipo, seleccione Agregar canal.
  2. Seleccione Discord o Slack, asigne un nombre al canal, pegue la URL del webhook y marque los eventos correspondientes.
  3. Utilice la opción de envío de prueba para verificar la recepción del mensaje antes de activar el canal.
EventoSe dispara cuando
Ejecución fallidaLa ejecución concluye con al menos una prueba fallida.
Ejecución completadaLa ejecución concluye con todas las pruebas aprobadas.
Caso con regresiónUna prueba que previamente pasaba falla en la ejecución actual.
Ingesta fallidaOcurre un error al procesar los cambios de código del repositorio.
Seguridad de la conexiónSe modifica el secreto del webhook o las credenciales vinculadas al repositorio.
La administración de canales de notificación requiere rol de owner o admin en la organización. Una vez activo, las alertas de seguridad de conexión serán visibles para cualquier usuario con acceso al canal o servidor de destino, ya que Qably no valida permisos en la plataforma receptora.

Preguntas frecuentes

¿Por qué mi pipeline de CI finaliza con éxito pero no aparece la ejecución en Qably?

Verifique que la variable QABLY_API_KEY esté declarada como secreto en el entorno del job de CI y que el paso de reporte se haya ejecutado. Al incluir la directiva if: always(), el envío se realiza incluso si las pruebas fallaron.

Confirme además que su ejecutor de pruebas generó el archivo XML en la ruta indicada antes de la petición. Si la llamada con curl devuelve un código HTTP de error (como 401 por una clave revocada o 400 por un archivo XML mal formado), revise los registros del runner para confirmar el motivo exacto.

¿Cómo organiza Qably las suites y casos de prueba si no especifico identificadores manuales?

Al importar un reporte JUnit XML, Qably lee los atributos del archivo para identificar cada suite y cada caso. Si una suite con ese nombre no existe en el proyecto, el servidor la crea de inmediato y le asigna los casos correspondientes.

No es necesario registrar previamente las pruebas en la interfaz web ni gestionar identificadores numéricos. Si envía datos mediante la API JSON en lugar de XML, use el campo suiteName para que el sistema adopte o cree la suite de forma automática.

¿Qué sucede en Qably si reintento un job de pruebas en mi CI?

Qably maneja reintentos de forma idempotente cuando se incluye el parámetro externalId en la llamada. Al utilizar identificadores únicos provistos por el runner (como el número de ejecución y el nombre del job en GitHub Actions), el servidor actualiza el registro existente en lugar de crear una ejecución duplicada.

Esto garantiza que las métricas de aprobación reflejen el estado definitivo de la corrida sin distorsionar el historial del proyecto ni duplicar conteos de pruebas.

¿Puedo registrar pasos individuales y resultados esperados al importar desde JUnit XML?

El estándar JUnit XML registra únicamente el estado final de cada prueba (aprobada, fallida u omitida), su duración y el mensaje de error o traza del fallo. Por esta razón, las importaciones desde archivos XML dejan vacíos los campos de pasos y resultados esperados.

Para documentar procedimientos detallados con pasos individuales y resultados previstos, envíe los datos en formato JSON directamente al endpoint POST /runs/ingest, o gestione casos estructurados desde la interfaz web del proyecto.

¿Por qué la sección Repository del proyecto no muestra commits ni ramas?

La vista Repository se alimenta exclusivamente mediante el webhook del sistema de control de versiones (GitHub o Bitbucket). El envío de reportes de pruebas desde CI registra ejecuciones en el historial, pero no transmite el contenido de los commits ni la actividad del repositorio.

Para ver los cambios de código y vincularlos con las corridas de pruebas, configure el webhook en los ajustes de su repositorio siguiendo el paso 2 de esta guía.

¿Puede una misma API key reportar resultados a varios proyectos?

No. Cada API key tiene alcance exclusivo sobre un proyecto específico dentro de la organización. El servidor deduce el proyecto de destino a partir de la propia clave y restringe su uso a la ingesta de pruebas.

Para entornos con múltiples proyectos o arquitecturas basadas en microservicios, genere una clave independiente para cada proyecto y configure el secreto correspondiente en sus flujos de CI.