CircleCI
Lancez des exécutions Autonomy depuis CircleCI pour une URL de prévisualisation web ou un build mobile, et faites échouer le pipeline si une exécution ne réussit pas.
Utilisez CircleCI pour lancer des exécutions Autonomy après un déploiement ou un build mobile. Cette page contient le script partagé, des configurations complètes et la condition sur le résultat. Le job ne réussit que si toutes les exécutions sont Passed.
Placement du workflow
Exécutez Autonomy une fois que la prévisualisation répond ou que le build mobile existe. Chaque configuration ci-dessous est un .circleci/config.yml complet et alternatif ; copiez celle de votre plateforme. Dans un workflow existant, conservez votre job de déploiement et faites dépendre le job Autonomy de celui-ci avec requires. Transmettez l'URL déployée finale, et non le localhost d'un conteneur de CI.
Secrets requis
Dans CircleCI, ouvrez Project Settings → Environment Variables et ajoutez les valeurs ci-dessous. CircleCI les injecte dans le shell du job ; n'écrivez pas la clé API dans le YAML. Un contexte restreint peut contenir les mêmes valeurs à la place : rattachez-le avec context sur l'entrée du job sous workflows, et non sous jobs.
-
AUTONOMY_API_KEY: une clé API d'organisation commençant paraut_. Les propriétaires et les administrateurs créent les clés dans Organization → API keys. -
AUTONOMY_TEST_PLAN_ID: ouvrez le plan dans Test plans du projet et copiez la dernière partie de l'URL de la page,/p/<project>/plans/<id>. Le plan doit contenir au moins un cas de test pour la plateforme. Pour exécuter plutôt un seul cas de test, définissezAUTONOMY_TEST_CASE_ID(issu de/p/<project>/tests/<id>) et ne définissez pas l'identifiant du plan. Définissez exactement l'un des deux. - Web :
PREVIEW_URL, l'URL de déploiement HTTPS joignable. - Mobile :
APP_IDENTIFIER, le bundle ID iOS ou le nom de package Android du build. - Facultatif :
AUTONOMY_ENVIRONMENT_SLUGexécute sur un environnement enregistré du même projet, avec ses cibles et ses valeurs d'environnement, au lieu de l'URL ou du build de ce job. Le script saute alors le téléversement.AUTONOMY_WAIT_SECONDSmodifie le temps d'attente total.
Sans environnement, une exécution n'a pas de valeurs d'environnement : une étape qui utilise {{env.NAME}} se termine en Couldn't start. Définissez AUTONOMY_ENVIRONMENT_SLUG, ou utilisez des cas de test qui n'ont pas besoin de valeurs d'environnement.
Utilisez un plan distinct pour chaque plateforme. Les configurations ci-dessous attendent des valeurs AUTONOMY_TEST_PLAN_ID et APP_IDENTIFIER adaptées à la recette. Pour combiner plusieurs plateformes, fournissez les valeurs via des contextes distincts ou des variables propres à chaque plateforme. Voir Plans de test pour regrouper des cas de test.
URL de prévisualisation web
Créez .ci/ dans votre dépôt, enregistrez ce script sous .ci/autonomy.sh et committez-le avec .circleci/config.yml. Les jobs l'appellent avec Bash : il n'a donc pas besoin d'être exécutable. Il nécessite Bash, curl et jq, que contiennent les images Linux ci-dessous.
#!/usr/bin/env bash
# Usage: bash .ci/autonomy.sh web|ios|android
# Starts Autonomy runs for this CI job and exits 0 only if every run passed.
set -euo pipefail
set +x
: "${AUTONOMY_API_KEY:?Set an aut_ organization API key}"
: "${AUTONOMY_REQUEST_ID:?Set an ID that is unique for this CI job attempt}"
platform="${1:?Usage: bash .ci/autonomy.sh web|ios|android}"
api="${AUTONOMY_API_URL:-https://api.autonomyqa.com}"
api="${api%/}"
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"
}
# 1. What to run: a test plan or one test case.
if [ -n "${AUTONOMY_TEST_PLAN_ID:-}" ] && [ -z "${AUTONOMY_TEST_CASE_ID:-}" ]; then
what=$(jq -n --arg id "$AUTONOMY_TEST_PLAN_ID" '{testPlanId:$id}')
elif [ -n "${AUTONOMY_TEST_CASE_ID:-}" ] && [ -z "${AUTONOMY_TEST_PLAN_ID:-}" ]; then
what=$(jq -n --arg id "$AUTONOMY_TEST_CASE_ID" '{testCaseId:$id}')
else
echo 'Set exactly one of AUTONOMY_TEST_PLAN_ID or AUTONOMY_TEST_CASE_ID.' >&2
exit 2
fi
# 2. Where to run: a saved environment, or this job's preview URL or build.
if [ -n "${AUTONOMY_ENVIRONMENT_SLUG:-}" ]; then
where=$(jq -n --arg slug "$AUTONOMY_ENVIRONMENT_SLUG" '{environmentSlug:$slug}')
else
case "$platform" in
web)
: "${PREVIEW_URL:?Set PREVIEW_URL, or AUTONOMY_ENVIRONMENT_SLUG}"
where=$(jq -n --arg url "$PREVIEW_URL" '{targets:{web:{baseUrl:$url}}}')
;;
ios|android)
: "${ARTIFACT_PATH:?Set the path to the zipped .app, .apk or .aab}"
: "${APP_IDENTIFIER:?Set the iOS bundle ID or Android package name}"
file=$(basename "$ARTIFACT_PATH")
bytes=$(wc -c < "$ARTIFACT_PATH" | tr -d '[:space:]')
if [ "$platform" = ios ]; then
type=application/zip
else
type=application/vnd.android.package-archive
fi
upload=$(post /api/artifacts/upload-url "$(jq -n \
--arg platform "$platform" --arg fileName "$file" \
--arg contentType "$type" --argjson declaredBytes "$bytes" \
'{platform:$platform,fileName:$fileName,contentType:$contentType,declaredBytes:$declaredBytes}')")
storage=$(jq -er '.storageId' <<< "$upload")
intent=$(jq -er '.intentId' <<< "$upload")
curl --fail-with-body --silent --show-error \
--connect-timeout 15 --max-time 600 \
-X PUT "$(jq -er '.uploadUrl' <<< "$upload")" \
-H "Content-Type: $type" --data-binary "@$ARTIFACT_PATH"
scan=$(post /api/artifacts/scan "$(jq -n \
--arg storageId "$storage" --arg intentId "$intent" \
'{storageId:$storageId,intentId:$intentId}')")
if [ "$(jq -r '.status' <<< "$scan")" != clean ]; then
echo 'The build did not pass the safety check, so no run was started:' >&2
jq -r '.findings[]?.message' <<< "$scan" >&2
exit 1
fi
where=$(jq -n --arg p "$platform" --arg storageId "$storage" \
--arg fileName "$file" --arg id "$APP_IDENTIFIER" \
'{targets:{($p):({storageId:$storageId,sourceMode:"upload",fileName:$fileName}
+ (if $p == "ios" then {bundleId:$id} else {packageName:$id} end))}}')
;;
*) echo 'Usage: bash .ci/autonomy.sh web|ios|android' >&2; exit 2 ;;
esac
fi
# 3. Start the runs. A plan starts one run per test case.
# The request ID's prefix (github, gitlab, ...) names the CI provider.
body=$(jq -n --argjson what "$what" --argjson where "$where" \
--arg platform "$platform" \
--arg branch "${AUTONOMY_BRANCH:-}" --arg pr "${AUTONOMY_PR:-}" \
--arg commitSha "${AUTONOMY_COMMIT_SHA:-}" \
--arg provider "${AUTONOMY_REQUEST_ID%%:*}" \
--arg key "$AUTONOMY_REQUEST_ID:$platform" \
'$what + $where + ({
platforms: [$platform],
branch: $branch,
pr: $pr,
deployment: ({provider: $provider, branch: $branch, commitSha: $commitSha}
| with_entries(select(.value != ""))),
idempotencyKey: $key
} | with_entries(select(.value != "")))')
run_ids=$(post /api/v1/run.trigger "$body" | jq -er '.runIds[]')
printf 'Started Autonomy runs:\n%s\n' "$run_ids"
# 4. Follow each run until it ends. run.get waits up to 25 s for a change;
# sending the last cursor back makes each call wait for something new.
deadline=$((SECONDS + ${AUTONOMY_WAIT_SECONDS:-1200}))
all_passed=true
for run_id in $run_ids; do
cursor=null
while :; do
left=$((deadline - SECONDS))
if [ "$left" -le 0 ]; then
echo "Stopped waiting for run $run_id after AUTONOMY_WAIT_SECONDS. It keeps going in Autonomy." >&2
exit 1
fi
wait_ms=$(( left < 25 ? left * 1000 : 25000 ))
run=$(post /api/v1/run.get "$(jq -n --arg runId "$run_id" \
--argjson cursor "$cursor" --argjson waitMs "$wait_ms" \
'{runId:$runId,cursor:$cursor,waitMs:$waitMs}')")
cursor=$(jq '.cursor' <<< "$run")
status=$(jq -r '.status' <<< "$run")
[ "$status" = queued ] || [ "$status" = running ] || break
done
name="$(jq -r '.testCaseName' <<< "$run") ($run_id)"
case "$status" in
passed)
echo "Passed: $name" ;;
failed)
echo "Failed: $name. Open the run in Autonomy to see which step failed." >&2
all_passed=false ;;
couldnt_start)
echo "Couldn't start: $name. The environment couldn't be tested, so this says nothing about your app. Open the run for the reason, fix it and run again." >&2
all_passed=false ;;
cancelled)
echo "Cancelled: $name." >&2
all_passed=false ;;
*)
echo "Unexpected status $status: $name." >&2
all_passed=false ;;
esac
done
if [ "$all_passed" != true ]; then
echo 'Not every Autonomy run passed.' >&2
exit 1
fi
echo 'Every Autonomy run passed.'Enregistrez cette configuration sous .circleci/config.yml. Pour une première exécution, définissez PREVIEW_URL sur une prévisualisation déjà déployée, puis poussez les fichiers sur staging. La vérification de disponibilité doit réussir avant le démarrage d'Autonomy.
Pour des prévisualisations par commit, exportez PREVIEW_URL et appelez le script dans la même step run. Un simple export ne se transmet pas à une autre step. Pour l'utiliser dans une step run ultérieure du même job, ajoutez cette ligne dans la step de déploiement une fois l'URL connue ; CircleCI charge BASH_ENV dans les steps suivantes :
printf 'export PREVIEW_URL=%q\n' "$PREVIEW_URL" >> "$BASH_ENV"Pour des jobs distincts, écrivez l'URL sur une seule ligne dans /tmp/autonomy-preview/preview-url.txt. Utilisez persist_to_workspace avec root: /tmp/autonomy-preview et paths: [preview-url.txt] dans le job de déploiement. Dans le job Autonomy, utilisez attach_workspace avec at: /tmp/autonomy-preview, puis exécutez export PREVIEW_URL="$(cat /tmp/autonomy-preview/preview-url.txt)" avant la vérification de disponibilité. BASH_ENV ne transmet pas de valeurs d'un job à l'autre.
version: 2.1
jobs:
autonomy-web:
docker:
- image: cimg/base:current
steps:
- checkout
- run:
name: Check preview and run Autonomy
no_output_timeout: 30m
command: |
set -euo pipefail
set +x
: "${PREVIEW_URL:?Set the deployed preview URL}"
curl --fail --silent --show-error --location \
--connect-timeout 15 --max-time 30 \
--retry 10 --retry-delay 3 --retry-all-errors \
--output /dev/null "$PREVIEW_URL"
export AUTONOMY_BRANCH="${CIRCLE_BRANCH:-local}"
export AUTONOMY_COMMIT_SHA="${CIRCLE_SHA1:-$(git rev-parse HEAD)}"
export AUTONOMY_REQUEST_ID="circleci:${CIRCLE_WORKFLOW_ID:-local}:${CIRCLE_BUILD_NUM:-$(date +%s)-$$}"
bash .ci/autonomy.sh web
workflows:
preview-qa:
jobs:
- autonomy-web:
filters:
branches:
only: stagingPour une vérification en local sous macOS ou Linux, démarrez Docker et téléchargez la version officielle v0.1.47860 de l'ancienne CLI. Choisissez le .tar.gz correspondant à votre système (darwin pour macOS, linux pour Linux) et à votre processeur (arm64 pour Apple silicon ou ARM, amd64 pour Intel ou AMD). Décompressez-le et placez l'exécutable circleci-v0 dans votre PATH. La CLI v1 actuelle a supprimé l'exécution locale : les commandes ci-dessous utilisent donc l'ancien binaire.
Exportez les trois valeurs dans votre shell local, puis exécutez ces commandes depuis le dépôt commité. CircleCI n'importe pas les secrets ni les contextes du projet en local : chaque -e est donc nécessaire. Une configuration en version 2.1 doit être traitée avant de s'exécuter.
circleci-v0 config validate .circleci/config.yml
circleci-v0 config process .circleci/config.yml > /tmp/autonomy-circleci.yml
circleci-v0 local execute -c /tmp/autonomy-circleci.yml \
-e "AUTONOMY_API_KEY=$AUTONOMY_API_KEY" \
-e "AUTONOMY_TEST_PLAN_ID=$AUTONOMY_TEST_PLAN_ID" \
-e "PREVIEW_URL=$PREVIEW_URL" \
-e "AUTONOMY_WAIT_SECONDS=${AUTONOMY_WAIT_SECONDS:-1200}" \
autonomy-webL'exécution locale ne lance que ce job Docker. Elle ne valide ni l'ordonnancement du workflow, ni les restrictions de contexte, ni l'exécution sous macOS, ni la transmission par workspace pour iOS.
Transmission d'un build mobile
Pour iOS et Android, le script demande une URL de téléversement en indiquant la taille et le type du fichier, téléverse avec PUT, et envoie storageId et intentId au contrôle de sécurité. Il ne lance les exécutions qu'après un résultat clean. Conservez .ci/autonomy.sh ci-dessus et remplacez .circleci/config.yml par la configuration dont vous avez besoin.
iOS
Les tests iOS arrivent bientôt. Conservez cette section pour le moment où ils seront disponibles. D'ici là, Autonomy ne lance pas d'exécutions sur iOS.
Construisez le .app de simulateur sous macOS, compressez-le pour conserver les permissions et les liens symboliques, puis transmettez le zip à un job Linux avec persist_to_workspace et attach_workspace. Le téléversement et l'attente consomment des crédits Linux.
Cet exemple suppose un projet Xcode natif dans ios/MyApp.xcodeproj, un schéma partagé MyApp et un produit MyApp.app. Remplacez ces noms par les vôtres. Pour un workspace Xcode, remplacez -project par -workspace et son chemin ; conservez vos steps d'installation des dépendances avant xcodebuild. Ne téléversez pas de .ipa pour appareil physique.
CircleCI documente actuellement 27.0.0 sur m4pro.medium. macOS est disponible dans l'offre Free, dans la limite de ses crédits ; vérifiez votre solde avant de lancer des builds. circleci-v0 local execute ne peut pas exécuter ce job macOS.
version: 2.1
jobs:
build-ios:
macos:
xcode: "27.0.0"
resource_class: m4pro.medium
steps:
- checkout
- run:
name: Build and zip the simulator app
command: |
set -euo pipefail
xcodebuild \
-project ios/MyApp.xcodeproj \
-scheme MyApp \
-configuration Release \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath ios/build \
CODE_SIGNING_ALLOWED=NO build
mkdir -p /tmp/autonomy-ios
(cd ios/build/Build/Products/Release-iphonesimulator && \
zip -qry /tmp/autonomy-ios/MyApp.app.zip MyApp.app)
- persist_to_workspace:
root: /tmp/autonomy-ios
paths:
- MyApp.app.zip
autonomy-ios:
docker:
- image: cimg/base:current
steps:
- checkout
- attach_workspace:
at: /tmp/autonomy-ios
- run:
name: Upload and run Autonomy
no_output_timeout: 30m
command: |
set -euo pipefail
set +x
export ARTIFACT_PATH=/tmp/autonomy-ios/MyApp.app.zip
export AUTONOMY_BRANCH="$CIRCLE_BRANCH"
export AUTONOMY_COMMIT_SHA="$CIRCLE_SHA1"
export AUTONOMY_REQUEST_ID="circleci:$CIRCLE_WORKFLOW_ID:$CIRCLE_BUILD_NUM"
bash .ci/autonomy.sh ios
workflows:
ios-qa:
jobs:
- build-ios:
filters:
branches:
only: staging
- autonomy-ios:
requires:
- build-ios
filters:
branches:
only: stagingAndroid
L'image Linux Android inclut le SDK, Java, curl et jq. Cet exemple suppose un projet Gradle natif sous android/, son gradlew exécutable versionné et l'APK de debug du module app. Adaptez la tâche Gradle et le chemin de l'APK à votre module ou à votre product flavor. Conservez votre préparation des dépendances si l'application a aussi besoin de JavaScript ou d'autres outils de build. Un .aab fonctionne aussi.
version: 2.1
jobs:
autonomy-android:
docker:
- image: cimg/android:2026.08
resource_class: medium
steps:
- checkout
- run:
name: Build the debug APK
command: |
set -euo pipefail
cd android
./gradlew --no-daemon :app:assembleDebug
- run:
name: Upload and run Autonomy
no_output_timeout: 30m
command: |
set -euo pipefail
set +x
export ARTIFACT_PATH=android/app/build/outputs/apk/debug/app-debug.apk
export AUTONOMY_BRANCH="$CIRCLE_BRANCH"
export AUTONOMY_COMMIT_SHA="$CIRCLE_SHA1"
export AUTONOMY_REQUEST_ID="circleci:$CIRCLE_WORKFLOW_ID:$CIRCLE_BUILD_NUM"
bash .ci/autonomy.sh android
workflows:
android-qa:
jobs:
- autonomy-android:
filters:
branches:
only: stagingConditionner le pipeline au résultat
Le script lance les exécutions avec POST /api/v1/run.trigger et affiche leurs identifiants. Un plan de test lance une exécution par cas de test. Le script suit ensuite chaque exécution avec POST /api/v1/run.get, en renvoyant le dernier cursor avec waitMs: 25000, si bien que chaque appel attend que l'exécution évolue. Une réponse avec timedOut: true signifie seulement que rien n'a encore changé. Voir Exécutions et preuves.
| Résultat de l'exécution | Le job | Ce qu'indique le log |
|---|---|---|
| Passed | Réussit, si toutes les autres exécutions ont aussi réussi. Une réussite flaky compte comme une réussite. | Passed |
| Failed | Échoue. | Ouvrez l'exécution pour voir quelle étape a échoué et pourquoi, y compris un Runner problem. |
| Couldn't start | Échoue. | L'environnement n'a pas pu être testé, par exemple parce que le build ne s'est pas installé ou qu'une valeur manquait. Cela ne dit rien de votre application ; corrigez la cause et relancez. |
| Cancelled | Échoue. | Cancelled |
Les erreurs d'API, un build qui ne passe pas le contrôle de sécurité et l'épuisement du temps d'attente font aussi échouer le job. AUTONOMY_WAIT_SECONDS est le temps d'attente total pour toutes les exécutions, 1 200 secondes par défaut. Donnez au job de CI une limite de temps supérieure à cette valeur, augmentée du temps de build et de téléversement. Arrêter le job de CI n'annule pas les exécutions déjà lancées.
AUTONOMY_REQUEST_ID, complété par la plateforme, devient l'idempotencyKey de run.trigger : si la même tentative de job renvoie la requête, elle récupère les mêmes exécutions au lieu d'en créer de nouvelles. Donnez à chaque tentative de job son propre identifiant. La partie située avant le premier deux-points est envoyée comme fournisseur de déploiement, et la branche et le commit accompagnent les exécutions. Les formats complets de requête et de réponse figurent dans Opérations.
Augmentez no_output_timeout en même temps que AUTONOMY_WAIT_SECONDS : sinon, la limite de silence par défaut de CircleCI peut interrompre une attente qui se déroule normalement. Placez les jobs de release après le job Autonomy avec requires, pour qu'une exécution qui n'a pas réussi bloque la promotion.
Stratégie de branches et d'événements
Ces exemples s'exécutent sur staging. N'élargissez filters qu'à des branches de confiance. Utilisez un petit plan de smoke test pour les modifications de prévisualisation relues, et des plans plus larges pour les pipelines de release ou planifiés. Configurez les déclencheurs de push, de pull request ou planifiés dans le projet CircleCI de votre VCS connecté ; les filtres de branche seuls ne les créent pas.
Laissez Pass secrets to builds from forked pull requests désactivé là où ce paramètre existe. Relisez le code non fiable avant de l'exécuter dans un job disposant de la clé API de l'organisation, et limitez tout contexte partagé aux projets prévus et aux personnes de confiance. L'identifiant de requête combine l'identifiant du workflow et le numéro du job : une nouvelle tentative de job lance donc de nouvelles exécutions, tandis qu'une requête répétée au cours d'une même tentative récupère les mêmes exécutions.
Références de l'éditeur
Vérifié par rapport à la documentation publique de CircleCI le 20 septembre 2026 :
Vous n’avez pas trouvé ?
Bitrise
Lancez des exécutions Autonomy depuis un workflow Bitrise pour une prévisualisation web ou un APK Android, et faites échouer le build si une exécution ne réussit pas.
Vercel
Exécutez les tests d'un projet sur chaque déploiement Vercel et publiez le résultat sous forme de check de déploiement Vercel.