Docs de Autonomy
Integraciones

Bitrise

Dispara ejecuciones de Autonomy desde Bitrise y condiciona el flujo a su resultado para web, iOS Simulator o Android.

Usa un paso Script de Bitrise para subir un build móvil o probar una previsualización web desplegada, y mantén el flujo abierto hasta que Autonomy devuelva un veredicto.

Ubicación del flujo

Añade el paso de Autonomy después de los pasos existentes de build y despliegue. Para web, publica la URL pública final como PREVIEW_URL desde el paso de despliegue con envman add --key PREVIEW_URL --value "$PREVIEW_URL"; los pasos posteriores podrán leerla. Para móvil, conserva el build y la subida en el mismo flujo para que el artefacto siga en el directorio de trabajo.

Las configuraciones completas siguientes son alternativas para bitrise.yml. Copia la de tu plataforma o integra sus pasos en el flujo existente. Configura Bitrise para leer bitrise.yml del repositorio y guarda .ci/autonomy.sh junto a él. El flujo web también puede ejecutarse localmente en un repositorio clonado.

Secretos requeridos

Antes de la primera ejecución

  • Crea una clave de API de organización de Autonomy que empiece por aut_ en Settings → API Keys, en la organización que contiene tu plan.
  • Crea un plan de test en Test Plans con al menos un caso de prueba ejecutable para la plataforma seleccionada y copia su ID.
  • Usa casos de prueba que no referencien variables de entorno en tiempo de ejecución en esta receta con objetivos explícitos.
  • Ten un runner de Autonomy disponible para la plataforma y una URL de previsualización accesible desde ese runner.

En Workflows → Secrets, añade AUTONOMY_API_KEY. Deja desactivadas Expose for pull requests y Replace variables in inputs. Los secretos se convierten automáticamente en variables de entorno del shell; no incluyas la clave en bitrise.yml.

En Workflows → Env Vars, establece estos valores para el flujo seleccionado:

VariableValor
AUTONOMY_API_URLLa URL HTTP base de tu despliegue, como https://your-deployment.convex.site, sin /api. No uses .convex.cloud.
AUTONOMY_TEST_PLAN_IDEl ID copiado de Test Plans, que contiene los casos a ejecutar, no el ID de un caso de prueba individual. Usa un plan distinto por plataforma.
PREVIEW_URLSolo web: la URL final desplegada, sin inicio de sesión ni protección de previsualización. También puede proporcionarla el paso de despliegue.
APP_IDENTIFIERSolo móvil: el ID de bundle de iOS o el ID de aplicación de Android correspondiente al artefacto.
AUTONOMY_WAIT_SECONDSOpcional: tiempo máximo de espera en segundos; por defecto, 1200.

URL de previsualización web

Crea un directorio .ci en el repositorio y guarda este script completo como .ci/autonomy.sh. Necesita Bash, curl 7.76 o posterior y jq; los stacks alojados seleccionados los incluyen. Instala estas herramientas para una ejecución local con la CLI. Mantén este archivo idéntico en todas las plataformas.

.ci/autonomy.sh
#!/usr/bin/env bash
set -euo pipefail
set +x
: "${AUTONOMY_API_URL:?Set the API base URL, without /api}"
: "${AUTONOMY_API_KEY:?Set an aut_ organization API key}"
: "${AUTONOMY_TEST_PLAN_ID:?Set the Test Plans ID for this platform}"
: "${AUTONOMY_REQUEST_ID:?Set a unique CI job/attempt ID}"
platform="${1:-web}"
api="${AUTONOMY_API_URL%/}"
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT

post() {
  curl --fail-with-body --silent --show-error \
    --connect-timeout 15 --max-time 90 \
    -X POST "$api$1" \
    -H "Authorization: Bearer $AUTONOMY_API_KEY" \
    -H 'Content-Type: application/json' --data-binary "$2"
}

case "$platform" in
  web)
    : "${PREVIEW_URL:?Set the reachable preview URL after deployment}"
    targets=$(jq -n --arg url "$PREVIEW_URL" '{web:{baseUrl:$url}}')
    ;;
  ios|android)
    : "${ARTIFACT_PATH:?Set the path to the app archive or APK}"
    : "${APP_IDENTIFIER:?Set the bundle ID or Android package name}"
    test -s "$ARTIFACT_PATH"
    file=$(basename "$ARTIFACT_PATH")
    bytes=$(wc -c < "$ARTIFACT_PATH" | tr -d '[:space:]')
    content_type=application/zip
    if [ "$platform" = android ]; then
      content_type=application/vnd.android.package-archive
    fi
    upload=$(post /api/artifacts/upload-url "$(jq -n \
      --arg platform "$platform" --arg fileName "$file" \
      --arg contentType "$content_type" --argjson declaredBytes "$bytes" \
      '{platform:$platform,fileName:$fileName,contentType:$contentType,declaredBytes:$declaredBytes}')")
    url=$(jq -er '.uploadUrl | strings | select(length > 0)' <<< "$upload")
    storage=$(jq -er '.storageId | strings | select(length > 0)' <<< "$upload")
    intent=$(jq -er '.intentId | strings | select(length > 0)' <<< "$upload")
    jq -e '.method == "PUT"' <<< "$upload" > /dev/null
    curl --fail-with-body --silent --show-error \
      --connect-timeout 15 --max-time 600 -X PUT "$url" \
      -H "Content-Type: $content_type" --data-binary "@$ARTIFACT_PATH"
    scan=$(post /api/artifacts/scan "$(jq -n \
      --arg storageId "$storage" --arg intentId "$intent" \
      '{storageId:$storageId,intentId:$intentId}')")
    if ! jq -e '.status == "clean"' <<< "$scan" > /dev/null; then
      echo 'Artifact scan did not pass; refusing to trigger.' >&2
      exit 1
    fi
    targets=$(jq -n --arg platform "$platform" --arg storageId "$storage" \
      --arg fileName "$file" --arg identifier "$APP_IDENTIFIER" \
      '{($platform):({storageId:$storageId,sourceMode:"upload",fileName:$fileName} +
        (if $platform == "ios" then {bundleId:$identifier} else {packageName:$identifier} end))}')
    ;;
  *) echo 'Usage: bash .ci/autonomy.sh web|ios|android' >&2; exit 2 ;;
esac

body=$(jq -n --arg testPlanId "$AUTONOMY_TEST_PLAN_ID" \
  --arg platform "$platform" --argjson targets "$targets" \
  --arg branch "${AUTONOMY_BRANCH:-manual}" \
  --arg commitSha "${AUTONOMY_COMMIT_SHA:-}" \
  --arg key "$AUTONOMY_REQUEST_ID:$platform" \
  '{testPlanId:$testPlanId,platforms:[$platform],targets:$targets,
    branch:$branch,deployment:{branch:$branch,commitSha:$commitSha},idempotencyKey:$key}')
post /api/v1/run.trigger "$body" > "$work/trigger.json"
jq -e '.runIds | type == "array" and length > 0' "$work/trigger.json" > /dev/null
jq -er '.runIds[] | strings | select(length > 0)' "$work/trigger.json" > "$work/run-ids"
printf 'Queued Autonomy runs:\n'
cat "$work/run-ids"

deadline=$((SECONDS + ${AUTONOMY_WAIT_SECONDS:-1200}))
while IFS= read -r run_id; do
  while :; do
    if (( SECONDS >= deadline )); then
      echo "Timed out waiting for $run_id; failing the CI job." >&2
      exit 1
    fi
    result=$(post /api/v1/run.get "$(jq -n --arg runId "$run_id" '{runId:$runId}')")
    status=$(jq -er '.status' <<< "$result")
    case "$status" in
      queued|running|retrying) sleep 10 ;;
      passing|failed|unverified|invalid|canceled)
        printf '%s: %s\n' "$run_id" "$status"
        if ! jq -e '.verdict == "passed" and .validity == "valid"' <<< "$result" > /dev/null; then
          echo "Autonomy gate failed for $run_id." >&2
          exit 1
        fi
        break ;;
      *) echo "Unexpected run status: $status" >&2; exit 1 ;;
    esac
  done
done < "$work/run-ids"
echo 'Every Autonomy run passed.'

Guarda esta configuración como bitrise.yml. Establece las variables del flujo anteriores y elige Start build → web después de desplegar la previsualización. El paso de clonación se ejecuta en Bitrise; la CLI local usa el repositorio que ya has clonado.

bitrise.yml
format_version: '13'
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
workflows:
  web:
    meta:
      bitrise.io:
        stack: linux-docker-android-22.04
        machine_type_id: standard
    steps:
      - activate-ssh-key@4:
          run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
      - git-clone@8:
          run_if: '{{getenv "BITRISE_IO" | eq "true"}}'
      - script@1:
          title: Autonomy
          inputs:
          - content: |-
              #!/usr/bin/env bash
              set -euo pipefail
              set +x
              : "${PREVIEW_URL:?Set the deployed preview URL}"
              curl --fail --silent --show-error --retry 12 \
                --retry-delay 5 --retry-connrefused --max-time 20 \
                "$PREVIEW_URL" > /dev/null
              attempt="$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)"
              export AUTONOMY_REQUEST_ID="bitrise:${BITRISE_BUILD_SLUG:-local}:${BITRISE_TRIGGERED_WORKFLOW_ID}:$attempt"
              export AUTONOMY_BRANCH="${BITRISE_GIT_BRANCH:-$(git branch --show-current)}"
              export AUTONOMY_COMMIT_SHA="$(git rev-parse HEAD)"
              bash .ci/autonomy.sh web

Para usar el runner local, instala la CLI de Bitrise y guarda lo siguiente como .bitrise.secrets.yml junto a bitrise.yml. Sustituye los cuatro valores de ejemplo por tu clave de API, URL del despliegue, ID del plan y URL de previsualización accesible:

.bitrise.secrets.yml
envs:
- AUTONOMY_API_KEY: 'aut_REPLACE_WITH_ORG_KEY'
  opts:
    is_expand: false
- AUTONOMY_API_URL: 'https://your-deployment.convex.site'
  opts:
    is_expand: false
- AUTONOMY_TEST_PLAN_ID: 'REPLACE_WITH_TEST_PLANS_ID'
  opts:
    is_expand: false
- PREVIEW_URL: 'https://your-preview.example.com'
  opts:
    is_expand: false

Ejecuta estos comandos desde la raíz del repositorio. Excluye el archivo de secretos del control de versiones. La CLI local se ejecuta en tu equipo; la selección del stack en meta solo se aplica a los builds alojados.

printf '\n.bitrise*\n' >> .gitignore
chmod 600 .bitrise.secrets.yml
bitrise setup
bitrise run web

Transferencia de artefactos móviles

Usa el mismo .ci/autonomy.sh anterior. Solicita una URL de subida, envía el binario mediante PUT, exige un análisis limpio y dispara la ejecución con el ID de almacenamiento recibido. El build y la subida comparten el directorio de trabajo; no necesitas configurar transferencias de artefactos entre flujos.

iOS

Esta alternativa completa de bitrise.yml usa un stack de Xcode en macOS. Establece AUTONOMY_TEST_PLAN_ID con tu plan de iOS y APP_IDENTIFIER con su ID de bundle. Sustituye ios/MyApp.xcodeproj, MyApp y el nombre del .app resultante por tu proyecto, esquema compartido y nombre de producto. Si tu app usa un workspace, sustituye -project ios/MyApp.xcodeproj por -workspace ios/MyApp.xcworkspace. Conserva los pasos existentes de instalación de dependencias antes de xcodebuild.

Construye un .app para Simulator y comprímelo en ZIP; aquí no sirve un .ipa para dispositivos. La subida y la espera del veredicto también se ejecutan en macOS y consumen tiempo de build.

bitrise.yml
format_version: '13'
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
workflows:
  ios:
    meta:
      bitrise.io:
        stack: osx-xcode-26.4.x
        machine_type_id: g2.mac.medium
    steps:
      - activate-ssh-key@4:
          run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
      - git-clone@8:
          run_if: '{{getenv "BITRISE_IO" | eq "true"}}'
      - script@1:
          title: Autonomy
          inputs:
          - content: |-
              #!/usr/bin/env bash
              set -euo pipefail
              set +x
              xcodebuild -project ios/MyApp.xcodeproj -scheme MyApp \
                -configuration Release -sdk iphonesimulator \
                -destination 'generic/platform=iOS Simulator' \
                -derivedDataPath .build/ios CODE_SIGNING_ALLOWED=NO build
              mkdir -p .build/artifacts
              ditto -c -k --sequesterRsrc --keepParent \
                .build/ios/Build/Products/Release-iphonesimulator/MyApp.app \
                .build/artifacts/MyApp.app.zip
              export ARTIFACT_PATH="$PWD/.build/artifacts/MyApp.app.zip"
              attempt="$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)"
              export AUTONOMY_REQUEST_ID="bitrise:${BITRISE_BUILD_SLUG:-local}:${BITRISE_TRIGGERED_WORKFLOW_ID}:$attempt"
              export AUTONOMY_BRANCH="${BITRISE_GIT_BRANCH:-$(git branch --show-current)}"
              export AUTONOMY_COMMIT_SHA="$(git rev-parse HEAD)"
              bash .ci/autonomy.sh ios

Android

Esta alternativa completa de bitrise.yml usa el stack de Android en Linux. Establece AUTONOMY_TEST_PLAN_ID con tu plan de Android y APP_IDENTIFIER con su ID de aplicación. Se presupone un proyecto Android en android/, un wrapper de Gradle incluido en el repositorio y el módulo app. Adapta conjuntamente el directorio, la tarea y la ruta del APK si usas otro módulo o variante de build. Conserva las versiones de JDK y Android SDK que requiere tu build actual.

bitrise.yml
format_version: '13'
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
workflows:
  android:
    meta:
      bitrise.io:
        stack: linux-docker-android-22.04
        machine_type_id: standard
    steps:
      - activate-ssh-key@4:
          run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
      - git-clone@8:
          run_if: '{{getenv "BITRISE_IO" | eq "true"}}'
      - script@1:
          title: Autonomy
          inputs:
          - content: |-
              #!/usr/bin/env bash
              set -euo pipefail
              set +x
              (cd android && bash ./gradlew --no-daemon assembleDebug)
              export ARTIFACT_PATH="$PWD/android/app/build/outputs/apk/debug/app-debug.apk"
              attempt="$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)"
              export AUTONOMY_REQUEST_ID="bitrise:${BITRISE_BUILD_SLUG:-local}:${BITRISE_TRIGGERED_WORKFLOW_ID}:$attempt"
              export AUTONOMY_BRANCH="${BITRISE_GIT_BRANCH:-$(git branch --show-current)}"
              export AUTONOMY_COMMIT_SHA="$(git rev-parse HEAD)"
              bash .ci/autonomy.sh android

Bitrise incluye actualmente macOS Medium y Linux Medium en su plan gratuito Hobby, con 300 créditos al mes y un límite de 90 minutos por build. Los ejemplos seleccionan g2.mac.medium y standard, respectivamente. Un bitrise run ios local sigue necesitando tu propio Mac con Xcode; seleccionar un stack de macOS en YAML no crea un Mac remoto. Revisa los créditos disponibles antes de los builds móviles alojados. Consulta los precios de Bitrise.

Condicionar el pipeline al veredicto

El script muestra cada ID de ejecución en cola y consulta POST /api/v1/run.get. Una respuesta en cola solo confirma el envío. El flujo termina correctamente únicamente cuando todas las ejecuciones tienen verdict: "passed" y validity: "valid". Un resultado fallido, sin verificar, inválido, cancelado, desconocido, con tiempo agotado o con error HTTP hace fallar el paso Script y detiene los pasos normales posteriores. No añadas is_skippable: true a este paso.

La espera predeterminada es de 20 minutos; aumenta AUTONOMY_WAIT_SECONDS dentro del límite de Bitrise si tu plan lo necesita. Agotar la espera no cancela la ejecución de Autonomy. Abre la ejecución en Runs con el ID mostrado para ver sus evidencias. Cada invocación crea un UUID nuevo junto al slug del build y el ID del flujo, por lo que cada reintento o invocación local pone en cola una ejecución nueva.

Estrategia de ramas y eventos

Los ejemplos son flujos manuales sin disparadores automáticos, para que la configuración no exponga una clave de API a código no confiable. Empieza con un plan de smoke reducido y configura después un disparador de push para una rama de staging o de versión confiable en Bitrise. Añade el paso de Autonomy después del despliegue de ese flujo, conservando sus filtros de rama. Reserva los planes más grandes para ejecuciones programadas o manuales.

Mantén los secretos inaccesibles en builds de pull requests, incluidas las procedentes de forks. Ejecuta QA sobre código revisado cuando llegue a una rama confiable o inicia manualmente un build de un commit revisado. No habilites la exposición de secretos a pull requests para conseguir que la receta funcione. Se envían a Autonomy los metadatos de rama y commit; esta receta no crea comentarios en pull requests.

Referencias del proveedor

On this page