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.
Utilisez une Script Step Bitrise pour téléverser un build mobile ou tester une prévisualisation web déployée, puis gardez le workflow ouvert jusqu'à ce que chaque exécution Autonomy ait un résultat. La step ne réussit que si toutes les exécutions sont Passed.
Placement du workflow
Ajoutez la step Autonomy après vos steps de build et de déploiement existantes. Pour le web, exportez l'URL publique finale de la prévisualisation sous le nom PREVIEW_URL depuis la step de déploiement, avec envman add --key PREVIEW_URL --value "$PREVIEW_URL" ; les steps suivantes peuvent la lire. Pour le mobile, gardez le build et le téléversement dans le même workflow, pour que le build reste dans le workspace.
Les configurations ci-dessous sont des versions complètes et alternatives de bitrise.yml. Copiez celle de votre plateforme, ou fusionnez ses steps dans votre workflow existant. Configurez Bitrise pour qu'il lise bitrise.yml depuis le dépôt, et committez .ci/autonomy.sh à côté. Le workflow web peut aussi s'exécuter en local dans un dépôt récupéré.
Secrets requis
Avant la première exécution
- Créez une clé API d'organisation commençant par aut_ dans Organization → API keys. Les propriétaires et les administrateurs peuvent créer des clés.
- Créez un plan de test sous Test plans avec au moins un cas de test pour la plateforme, et copiez son identifiant.
- Pour cette recette sans environnement, utilisez des cas de test qui n'utilisent pas de valeurs d'environnement, ou définissez AUTONOMY_ENVIRONMENT_SLUG.
- Rendez l'URL de prévisualisation joignable depuis Internet.
Dans Workflows → Secrets, ajoutez AUTONOMY_API_KEY. Laissez Expose for pull requests désactivé et Replace variables in inputs décoché. Les secrets deviennent automatiquement des variables d'environnement du shell ; ne placez pas la clé dans bitrise.yml.
Dans Workflows → Env Vars, définissez ces valeurs pour le workflow :
| Variable | Valeur |
|---|---|
AUTONOMY_TEST_PLAN_ID | Le plan de test à exécuter : la dernière partie de /p/<project>/plans/<id> dans Test plans. Utilisez un plan distinct pour chaque plateforme. Pour exécuter plutôt un seul cas de test, définissez AUTONOMY_TEST_CASE_ID (issu de /p/<project>/tests/<id>) et laissez celle-ci vide. |
PREVIEW_URL | Web uniquement : l'URL déployée finale, sans page de connexion ni de protection de prévisualisation. Une step de déploiement peut la définir à la place. |
APP_IDENTIFIER | Mobile uniquement : le bundle ID iOS ou l'application ID Android du build. |
AUTONOMY_ENVIRONMENT_SLUG | Facultatif : exécuter sur un environnement enregistré du même projet, avec ses cibles et ses valeurs, au lieu de l'URL ou de l'application de ce build. Le script saute alors le téléversement. |
AUTONOMY_WAIT_SECONDS | Facultatif : le temps d'attente total en secondes, 1200 par défaut. |
Sans environnement, une exécution n'a pas de valeurs d'environnement : une étape qui utilise {{env.NAME}} se termine en Couldn't start.
URL de prévisualisation web
Créez un dossier .ci dans le dépôt et enregistrez l'intégralité de ce script sous .ci/autonomy.sh. Il nécessite Bash, curl 7.76 ou ultérieur et jq ; les stacks hébergées ci-dessous en disposent. Installez-les vous-même pour une exécution en local avec la CLI. Gardez ce fichier identique pour toutes les plateformes.
#!/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 bitrise.yml. Définissez les variables de workflow ci-dessus, puis choisissez Start build → web après avoir déployé la prévisualisation. La step de checkout s'exécute sur Bitrise ; la CLI locale utilise le dépôt que vous avez déjà récupéré.
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 webPour l'exécuter en local, installez la CLI Bitrise, puis enregistrez ceci sous .bitrise.secrets.yml à côté de bitrise.yml. Remplacez les trois valeurs d'exemple par votre clé API, l'identifiant de votre plan de test et votre URL de prévisualisation :
envs:
- AUTONOMY_API_KEY: 'aut_REPLACE_WITH_ORG_KEY'
opts:
is_expand: false
- AUTONOMY_TEST_PLAN_ID: 'REPLACE_WITH_TEST_PLAN_ID'
opts:
is_expand: false
- PREVIEW_URL: 'https://your-preview.example.com'
opts:
is_expand: falseExécutez ces commandes depuis la racine du dépôt. Gardez le fichier de secrets hors du contrôle de version. La CLI locale s'exécute sur votre machine ; la stack meta ne s'applique qu'aux builds hébergés.
printf '\n.bitrise*\n' >> .gitignore
chmod 600 .bitrise.secrets.yml
bitrise setup
bitrise run webTransmission d'un build mobile
Utilisez le même .ci/autonomy.sh. Pour iOS et Android, il demande une URL de téléversement, envoie le build avec PUT, attend que le contrôle de sécurité revienne sans anomalie et lance les exécutions avec le build téléversé. Le build et le téléversement partagent le workspace : il n'y a donc aucun transfert d'artefact à configurer.
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.
Ce bitrise.yml complet et alternatif utilise une stack macOS Xcode. Définissez AUTONOMY_TEST_PLAN_ID sur votre plan iOS et APP_IDENTIFIER sur son bundle ID. Remplacez ios/MyApp.xcodeproj, MyApp et le nom du .app par votre projet, votre schéma partagé et votre produit. Pour un workspace, remplacez -project ios/MyApp.xcodeproj par -workspace ios/MyApp.xcworkspace. Conservez les éventuelles steps d'installation des dépendances avant xcodebuild.
Construisez un .app de simulateur et compressez-le ; un .ipa pour appareil physique ne peut pas être utilisé. Le téléversement et l'attente s'exécutent aussi sous macOS et consomment son temps de build.
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 iosAndroid
Ce bitrise.yml complet et alternatif utilise la stack Linux Android. Définissez AUTONOMY_TEST_PLAN_ID sur votre plan Android et APP_IDENTIFIER sur son application ID. Il suppose un projet Android dans android/, un wrapper Gradle versionné et le module app. Pour un autre module ou une autre variante de build, modifiez ensemble le dossier, la tâche et le chemin de l'APK. Conservez les versions du JDK et du SDK Android dont votre build a besoin. Un .aab fonctionne aussi.
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 androidBitrise propose actuellement macOS Medium et Linux Medium dans son offre gratuite Hobby, avec 300 crédits par mois et une durée de build limitée à 90 minutes. Les exemples sélectionnent g2.mac.medium et standard. Un bitrise run ios en local nécessite toujours votre propre Mac avec Xcode ; choisir une stack macOS dans le YAML ne crée pas de Mac distant. Vérifiez vos crédits restants avant les builds mobiles hébergés. Voir les tarifs de Bitrise.
Conditionner 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.
Un code de sortie non nul fait échouer la Script Step et arrête les steps normales suivantes. Ne lui ajoutez pas is_skippable: true. Chaque démarrage du workflow génère un nouvel UUID à côté du slug du build et de l'identifiant du workflow : une nouvelle tentative ou une exécution locale lance donc de nouvelles exécutions. Ouvrez une exécution dans Runs du projet à l'aide de l'identifiant affiché pour consulter ses preuves.
Stratégie de branches et d'événements
Les exemples sont des workflows manuels sans déclencheur automatique : leur configuration n'expose donc pas de clé API à du code non fiable. Commencez par un petit plan de smoke test, puis définissez dans Bitrise un déclencheur de push pour une branche de staging ou de release de confiance. Ajoutez la step Autonomy après le déploiement dans ce workflow et conservez ses filtres de branche. Réservez les plans plus larges aux exécutions planifiées ou manuelles.
Tenez les secrets à l'écart des builds de pull request, y compris celles issues de forks. Exécutez les tests sur du code relu une fois qu'il atteint une branche de confiance, ou lancez à la main le build d'un commit relu. N'activez pas l'exposition des secrets aux pull requests pour faire passer une recette. La branche et le commit sont envoyés à Autonomy ; cette recette ne publie pas de commentaire sur la pull request.
Références de l'éditeur
Vous n’avez pas trouvé ?
Jenkins
Lancez des exécutions Autonomy depuis Jenkins pour une URL de prévisualisation ou un build mobile, et faites échouer le build si une exécution ne réussit pas.
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.