CircleCI
Lancez Autonomy depuis CircleCI avec une URL de prévisualisation web ou un build mobile, puis conditionnez le pipeline au verdict.
Utilisez CircleCI pour mettre en file d'attente des exécutions Autonomy après un déploiement ou un build mobile. Cette page contient le script d'API, les configurations complètes et le contrôle du verdict.
Placement dans le workflow
Lancez Autonomy lorsque la prévisualisation est accessible ou que l'artefact mobile existe. Chaque configuration est une alternative complète pour .circleci/config.yml ; copiez celle de votre plateforme. Dans un workflow existant, conservez le job de déploiement et faites-en une dépendance du job Autonomy avec requires. Transmettez l'URL finale du déploiement, pas le localhost d'un conteneur CI.
Secrets requis
Dans CircleCI, ouvrez Project Settings → Environment Variables et ajoutez les entrées ci-dessous. CircleCI les injecte dans le shell du job ; n'inscrivez pas la clé d'API dans le YAML. Un contexte restreint peut aussi les contenir : associez-le avec context sur l'entrée du job dans workflows, pas dans jobs.
-
AUTONOMY_API_URL: l'URL de base de l'API Autonomy, sans/api, avec l'URL HTTP Convex se terminant par.convex.site. -
AUTONOMY_API_KEY: une clé d'API d'organisationaut_du même déploiement et de la même organisation que le plan. -
AUTONOMY_TEST_PLAN_ID: ouvrez un plan existant dans Test Plans et copiez son ID depuis/test-plans/<id>dans l'URL du tableau de bord. Le plan doit contenir au moins un cas de test pour la plateforme choisie. Il s'agit de l'ID du plan, pas d'un cas de test individuel. - Web :
PREVIEW_URL, l'URL HTTPS accessible du déploiement. - Mobile :
APP_IDENTIFIER, le bundle ID iOS ou le nom de package Android correspondant à l'artefact. - Des cas de test qui peuvent s'exécuter avec ces cibles explicites, sans valeurs d'exécution ni identifiants fournis uniquement par un Environment enregistré. Un runner doit être disponible pour la plateforme choisie.
Utilisez un plan distinct par plateforme. Les configurations attendent que AUTONOMY_TEST_PLAN_ID et APP_IDENTIFIER correspondent à la recette choisie. Si vous combinez les plateformes, fournissez les valeurs appropriées avec des contextes distincts ou des variables propres à chaque plateforme. Consultez Plans de test pour regrouper les cas.
URL de prévisualisation web
Créez .ci/ dans votre dépôt, enregistrez le bloc suivant dans .ci/autonomy.sh et ajoutez-le au dépôt avec .circleci/config.yml. Les jobs l'appellent avec Bash ; le fichier n'a donc pas besoin d'être exécutable. Il nécessite Bash, curl et jq, fournis par les images Linux ci-dessous.
#!/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.'Enregistrez cette configuration dans .circleci/config.yml. Pour une première exécution, définissez PREVIEW_URL avec une prévisualisation déjà déployée, puis poussez les fichiers sur staging. La vérification HTTP doit réussir avant le déclenchement d'Autonomy.
Pour les prévisualisations par commit, exportez PREVIEW_URL et appelez le script dans la même étape run. Un simple export ne persiste pas dans une autre étape. Pour utiliser une étape run ultérieure du même job, ajoutez cette ligne après l'obtention de l'URL dans l'étape de déploiement ; CircleCI charge BASH_ENV dans les étapes suivantes :
printf 'export PREVIEW_URL=%q\n' "$PREVIEW_URL" >> "$BASH_ENV"Pour des jobs distincts, enregistrez l'URL obtenue 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 lancez export PREVIEW_URL="$(cat /tmp/autonomy-preview/preview-url.txt)" avant la vérification HTTP. BASH_ENV ne transfère pas les valeurs entre les jobs.
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)-$$}:web"
bash .ci/autonomy.sh web
workflows:
preview-qa:
jobs:
- autonomy-web:
filters:
branches:
only: stagingPour une vérification locale sur macOS ou Linux, démarrez Docker et téléchargez la version officielle de l'ancienne CLI v0.1.47860. Choisissez l'archive .tar.gz de votre système (darwin pour macOS, linux pour Linux) et processeur (arm64 pour Apple silicon ou ARM, amd64 pour Intel ou AMD). Extrayez-la et placez l'exécutable circleci-v0 dans un répertoire de votre PATH. La CLI v1 actuelle a supprimé l'exécution locale ; les commandes suivantes utilisent donc l'ancien binaire.
Exportez les quatre entrées dans votre shell local, puis lancez ces commandes depuis le dépôt contenant les fichiers commités. CircleCI n'importe pas les secrets du projet ni les contextes en local ; chaque -e est nécessaire. La configuration 2.1 doit être traitée avant l'exécution.
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_URL=$AUTONOMY_API_URL" \
-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 lance uniquement ce job Docker. Elle ne prouve pas la planification du workflow, les restrictions des contextes, l'exécution macOS ni le transfert du workspace iOS.
Transmission des artefacts mobiles
Le script demande une URL d'envoi avec la taille du fichier, envoie avec PUT, puis analyse avec storageId et intentId. Il ne déclenche l'exécution qu'après une analyse clean. Conservez .ci/autonomy.sh et remplacez .circleci/config.yml par la configuration adaptée ci-dessous.
iOS
Construisez le .app de simulateur sur macOS et archivez-le avant son transfert pour préserver les permissions d'exécution et les liens symboliques. Transmettez le ZIP à un job Linux avec persist_to_workspace et attach_workspace. L'envoi 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 ceux de votre projet. Si votre application utilise un workspace Xcode, remplacez -project par -workspace et son chemin ; conservez vos étapes d'installation des dépendances avant xcodebuild. N'envoyez pas de .ipa destiné aux appareils.
CircleCI documente actuellement 27.0.0 sur m4pro.medium. macOS est disponible avec l'offre Free dans la limite des crédits inclus ; vérifiez le solde avant de lancer les 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 archive 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:ios"
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 Android pour Linux inclut le SDK, Java, curl et jq. Cet exemple suppose un projet Gradle natif dans android/, son gradlew exécutable versionné et l'APK de débogage du module app. Adaptez la tâche Gradle et le chemin de l'APK à votre module ou variante. Conservez la préparation des dépendances si l'application nécessite aussi JavaScript ou d'autres outils de build.
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:android"
bash .ci/autonomy.sh android
workflows:
android-qa:
jobs:
- autonomy-android:
filters:
branches:
only: stagingConditionner le pipeline au verdict
Une exécution en file d'attente n'est pas un test réussi. Le script affiche chaque ID d'exécution renvoyé et interroge POST /api/v1/run.get. Il ne réussit que si chaque exécution renvoie verdict: "passed" et validity: "valid" ; les échecs, annulations, exécutions invalides ou non vérifiées, erreurs d'API et délais dépassés font échouer le job.
Le délai d'attente est de 1 200 secondes pour tout le plan. Définissez AUTONOMY_WAIT_SECONDS si votre plan nécessite davantage de temps et augmentez no_output_timeout en conséquence. Le délai de silence par défaut de CircleCI pourrait sinon arrêter une boucle de consultation qui fonctionne correctement. L'envoi et l'analyse précèdent ce délai d'attente. Placez les jobs de publication après le job Autonomy avec requires pour bloquer la promotion en cas d'échec.
Stratégie de branches et d'événements
Ces exemples s'exécutent sur staging. Étendez filters uniquement à des branches de confiance. Utilisez un petit plan smoke pour les changements de prévisualisation revus et des plans plus larges pour les versions ou les pipelines planifiés. Configurez les déclencheurs push, pull request ou planifiés dans le projet CircleCI pour votre VCS ; les filtres de branches ne créent pas ces déclencheurs.
Laissez Pass secrets to builds from forked pull requests désactivé lorsque ce réglage est disponible. Relisez le code non fiable avant de l'exécuter dans un job disposant de la clé d'API d'organisation et limitez les contextes partagés aux projets et acteurs prévus. L'ID de requête combine le workflow et le numéro du job : une nouvelle tentative peut créer une nouvelle exécution, tandis qu'une requête répétée dans la même tentative est idempotente.
Références du fournisseur
Vérifié dans la documentation publique de CircleCI le 20 septembre 2026 :