UiPath Documentation
uipath-cli
latest
false
Important :
Ce contenu a été traduit à l'aide d'une traduction automatique. La localisation du contenu nouvellement publié peut prendre 1 à 2 semaines avant d’être disponible.

Guide de l'utilisateur de UiPath CLI

Schéma CI/CD: GitLab CI

Cette page vous fournit une .gitlab-ci.yml complète qui installe la CLI, s'authentifie avec une application externe, compresse et publie une solution UiPath, la déploie dans Orchestrator sur plusieurs locataires (via une matrice) et exécute une suite Test Manager. Déplacez-le à la racine de votre référentiel et définissez trois variables CI/CD, et il s'exécute.

Pour les principes sous-jacents — authentification, mise en cache, préinstallation d'outils, épinglage de version — voir Comment: déployer dans Orchestrator depuis CI. Cette page se concentre sur la syntaxe de GitLab, y compris les fonctionnalités (cache avec une étendue clés, parallel: matrix) qui sont spécifiques à GitLab.

Prérequis

Avant de copier le YAML ci-dessous:

  1. Créez une application externe dans UiPath avec les étendues OR.* dont votre pipeline a besoin. Voir Authentification — Flux 2.
  2. Stockez les clés secrètes sous forme de variables CI/CD:
    • Projet → Paramètres → CI/CD → Variables.
    • Ajoutez UIPATH_CLIENT_ID et UIPATH_CLIENT_SECRET. Marquez les deux comme masqués et protégés (c'est-à-dire qu'ils n'apparaissent que sur les branches / balises protégées).
    • Ajoutez UIPATH_TENANT_DEV, UIPATH_TENANT_STAGE, UIPATH_TENANT_PROD avec les noms de locataires (non masqués — les noms de locataires ne sont pas sensibles).
  3. Enregistrez un projet et un ensemble de tests Test Manager si vous souhaitez la tâche de test. Ajoutez TEST_SET_KEY et PROJECT_KEY comme variables standard.

.gittab-ci.yml

# -----------------------------------------------------------------------------
# Deploy UiPath Solution
# -----------------------------------------------------------------------------
# Auth: External Application, env.VAR_NAME prefix (never the literal value).
# Cache: npm global node_modules, keyed by CLI version.
# Matrix: deploy job fans out across dev / stage / prod tenants.
# -----------------------------------------------------------------------------

image: node:20

stages:
  - build
  - deploy
  - test

variables:
  CLI_VERSION: '1.0.0'
  SOLUTION_NAME: 'my-solution'
  SOLUTION_DIR:  './my-solution'
  OUTPUT_DIR:    './dist'
  SOLUTION_VERSION: '1.2.0-ci.$CI_PIPELINE_IID'

  # Workspace-local npm prefix so installs need no sudo and are cacheable.
  NPM_PREFIX: "$CI_PROJECT_DIR/.npm-global"

# Re-usable install block. GitLab does not have anchors for script:; we use
# YAML anchors on a hidden job and extend from it.
.install-uip: &install-uip |
  set -euo pipefail
  mkdir -p "$NPM_PREFIX"
  npm config set prefix "$NPM_PREFIX"
  export PATH="$NPM_PREFIX/bin:$PATH"

  if ! command -v uip >/dev/null; then
    npm install -g "@uipath/cli@$CLI_VERSION"
  fi
  uip --version

cache:
  key: "uip-$CLI_VERSION"
  paths:
    - .npm-global/lib/node_modules
  policy: pull-push

# -----------------------------------------------------------------------------
# Stage: build
# -----------------------------------------------------------------------------

pack:
  stage: build
  script:
    - *install-uip
    - mkdir -p "$OUTPUT_DIR"
    - |
      uip solution pack "$SOLUTION_DIR" "$OUTPUT_DIR" \
        --name "$SOLUTION_NAME" \
        --version "$SOLUTION_VERSION"
  artifacts:
    paths:
      - "$OUTPUT_DIR/*.zip"
    expire_in: 30 days

# -----------------------------------------------------------------------------
# Stage: deploy — matrix across environments
# -----------------------------------------------------------------------------

deploy:
  stage: deploy
  needs:
    - job: pack
      artifacts: true
  parallel:
    matrix:
      - ENVIRONMENT: dev
        TENANT_VAR:  UIPATH_TENANT_DEV
      - ENVIRONMENT: stage
        TENANT_VAR:  UIPATH_TENANT_STAGE
      - ENVIRONMENT: prod
        TENANT_VAR:  UIPATH_TENANT_PROD
  environment:
    name: uipath/$ENVIRONMENT
  rules:
    # Prod only on protected branches — set protection under Settings → Repository.
    - if: '$ENVIRONMENT == "prod" && $CI_COMMIT_REF_PROTECTED != "true"'
      when: never
    - when: on_success
  script:
    - *install-uip
    - |
      # Resolve the per-environment tenant from the matrix variable.
      UIPATH_TENANT="${!TENANT_VAR}"
      if [ -z "$UIPATH_TENANT" ]; then
        echo "Tenant variable $TENANT_VAR is empty; set it in CI/CD settings." >&2
        exit 3
      fi

      uip login \
        --client-id env.UIPATH_CLIENT_ID \
        --client-secret env.UIPATH_CLIENT_SECRET \
        --tenant "$UIPATH_TENANT"

      ARTIFACT=$(find "$OUTPUT_DIR" -maxdepth 1 -name "*.zip" | head -1)
      uip solution publish "$ARTIFACT"

      uip solution deploy run \
        --name "$SOLUTION_NAME-$ENVIRONMENT-$CI_PIPELINE_IID" \
        --package-name "$SOLUTION_NAME" \
        --package-version "$SOLUTION_VERSION" \
        --folder-name MySolution \
        --folder-path Shared

# -----------------------------------------------------------------------------
# Stage: test
# -----------------------------------------------------------------------------

test:
  stage: test
  needs:
    - job: "deploy: [dev, UIPATH_TENANT_DEV]"   # depend on the dev leg of the matrix
      optional: true
  rules:
    - if: '$TEST_SET_KEY == null || $TEST_SET_KEY == ""'
      when: never
    - when: on_success
  script:
    - *install-uip
    - |
      uip login \
        --client-id env.UIPATH_CLIENT_ID \
        --client-secret env.UIPATH_CLIENT_SECRET \
        --tenant "$UIPATH_TENANT_DEV"

      EXECUTION_ID=$(uip tm testsets run \
        --test-set-key "$TEST_SET_KEY" \
        --output-filter "Data.ExecutionId" \
        --output plain)

      echo "started execution $EXECUTION_ID"

      if ! uip tm wait \
        --execution-id "$EXECUTION_ID" \
        --project-key "$PROJECT_KEY" \
        --timeout 1800; then
        code=$?
        case "$code" in
          2) echo "test run did not finish within 30 minutes" >&2; exit 2 ;;
          *) echo "wait failed (exit $code)" >&2; exit "$code" ;;
        esac
      fi

      uip tm report get \
        --execution-id "$EXECUTION_ID" \
        --project-key "$PROJECT_KEY"

      FAILED=$(uip tm report get \
        --execution-id "$EXECUTION_ID" \
        --project-key "$PROJECT_KEY" \
        --output-filter "Data.Failed" \
        --output plain)

      if [ "$FAILED" -gt 0 ]; then
        echo "$FAILED test case(s) failed" >&2
        exit 1
      fi
# -----------------------------------------------------------------------------
# Deploy UiPath Solution
# -----------------------------------------------------------------------------
# Auth: External Application, env.VAR_NAME prefix (never the literal value).
# Cache: npm global node_modules, keyed by CLI version.
# Matrix: deploy job fans out across dev / stage / prod tenants.
# -----------------------------------------------------------------------------

image: node:20

stages:
  - build
  - deploy
  - test

variables:
  CLI_VERSION: '1.0.0'
  SOLUTION_NAME: 'my-solution'
  SOLUTION_DIR:  './my-solution'
  OUTPUT_DIR:    './dist'
  SOLUTION_VERSION: '1.2.0-ci.$CI_PIPELINE_IID'

  # Workspace-local npm prefix so installs need no sudo and are cacheable.
  NPM_PREFIX: "$CI_PROJECT_DIR/.npm-global"

# Re-usable install block. GitLab does not have anchors for script:; we use
# YAML anchors on a hidden job and extend from it.
.install-uip: &install-uip |
  set -euo pipefail
  mkdir -p "$NPM_PREFIX"
  npm config set prefix "$NPM_PREFIX"
  export PATH="$NPM_PREFIX/bin:$PATH"

  if ! command -v uip >/dev/null; then
    npm install -g "@uipath/cli@$CLI_VERSION"
  fi
  uip --version

cache:
  key: "uip-$CLI_VERSION"
  paths:
    - .npm-global/lib/node_modules
  policy: pull-push

# -----------------------------------------------------------------------------
# Stage: build
# -----------------------------------------------------------------------------

pack:
  stage: build
  script:
    - *install-uip
    - mkdir -p "$OUTPUT_DIR"
    - |
      uip solution pack "$SOLUTION_DIR" "$OUTPUT_DIR" \
        --name "$SOLUTION_NAME" \
        --version "$SOLUTION_VERSION"
  artifacts:
    paths:
      - "$OUTPUT_DIR/*.zip"
    expire_in: 30 days

# -----------------------------------------------------------------------------
# Stage: deploy — matrix across environments
# -----------------------------------------------------------------------------

deploy:
  stage: deploy
  needs:
    - job: pack
      artifacts: true
  parallel:
    matrix:
      - ENVIRONMENT: dev
        TENANT_VAR:  UIPATH_TENANT_DEV
      - ENVIRONMENT: stage
        TENANT_VAR:  UIPATH_TENANT_STAGE
      - ENVIRONMENT: prod
        TENANT_VAR:  UIPATH_TENANT_PROD
  environment:
    name: uipath/$ENVIRONMENT
  rules:
    # Prod only on protected branches — set protection under Settings → Repository.
    - if: '$ENVIRONMENT == "prod" && $CI_COMMIT_REF_PROTECTED != "true"'
      when: never
    - when: on_success
  script:
    - *install-uip
    - |
      # Resolve the per-environment tenant from the matrix variable.
      UIPATH_TENANT="${!TENANT_VAR}"
      if [ -z "$UIPATH_TENANT" ]; then
        echo "Tenant variable $TENANT_VAR is empty; set it in CI/CD settings." >&2
        exit 3
      fi

      uip login \
        --client-id env.UIPATH_CLIENT_ID \
        --client-secret env.UIPATH_CLIENT_SECRET \
        --tenant "$UIPATH_TENANT"

      ARTIFACT=$(find "$OUTPUT_DIR" -maxdepth 1 -name "*.zip" | head -1)
      uip solution publish "$ARTIFACT"

      uip solution deploy run \
        --name "$SOLUTION_NAME-$ENVIRONMENT-$CI_PIPELINE_IID" \
        --package-name "$SOLUTION_NAME" \
        --package-version "$SOLUTION_VERSION" \
        --folder-name MySolution \
        --folder-path Shared

# -----------------------------------------------------------------------------
# Stage: test
# -----------------------------------------------------------------------------

test:
  stage: test
  needs:
    - job: "deploy: [dev, UIPATH_TENANT_DEV]"   # depend on the dev leg of the matrix
      optional: true
  rules:
    - if: '$TEST_SET_KEY == null || $TEST_SET_KEY == ""'
      when: never
    - when: on_success
  script:
    - *install-uip
    - |
      uip login \
        --client-id env.UIPATH_CLIENT_ID \
        --client-secret env.UIPATH_CLIENT_SECRET \
        --tenant "$UIPATH_TENANT_DEV"

      EXECUTION_ID=$(uip tm testsets run \
        --test-set-key "$TEST_SET_KEY" \
        --output-filter "Data.ExecutionId" \
        --output plain)

      echo "started execution $EXECUTION_ID"

      if ! uip tm wait \
        --execution-id "$EXECUTION_ID" \
        --project-key "$PROJECT_KEY" \
        --timeout 1800; then
        code=$?
        case "$code" in
          2) echo "test run did not finish within 30 minutes" >&2; exit 2 ;;
          *) echo "wait failed (exit $code)" >&2; exit "$code" ;;
        esac
      fi

      uip tm report get \
        --execution-id "$EXECUTION_ID" \
        --project-key "$PROJECT_KEY"

      FAILED=$(uip tm report get \
        --execution-id "$EXECUTION_ID" \
        --project-key "$PROJECT_KEY" \
        --output-filter "Data.Failed" \
        --output plain)

      if [ "$FAILED" -gt 0 ]; then
        echo "$FAILED test case(s) failed" >&2
        exit 1
      fi

Présentation

Configuration de niveau supérieur

  • image: node:20 — chaque tâche s'exécute dans l'image officielle Node.js 20. La CLI nécessite le nœud 18+. Si votre exécuteur GitLab a déjà installé Node et que vous n’avez pas besoin d’un conteneur, vous pouvez supprimer cette option et utiliser un exécuteur shell à la place.
  • variables: — les valeurs à l'échelle du pipeline. SOLUTION_VERSION interroge $CI_PIPELINE_IID (le numéro de pipeline incrémentiel à l'échelle du projet — meilleur pour le contrôle de version que $CI_JOB_ID, qui est global et non monobloc).
  • Ancre.install-uip - GitLab ne vous permet pas d'ancrer script: directement, mais vous pouvez ancrer un nœud YAML contenant une chaîne de shell et l'épingler avec - *install-uip Même garde-fou d'installation que les autres formules: préfixe local de l'espace de travail, installation de CLI conditionnelle. Les outils s'installent automatiquement lors de la première utilisation, de sorte que l'ancre ne gère que l'hôte.
  • cache: — la clé uip-$CLI_VERSION garantit qu'une bascule de version CLI invalide correctement le cache. policy: pull-push lit à l'entrée et écrit à la sortie réussie de la tâche. Si vous exécutez à grande échelle et que vous souhaitez économiser des secondes sur chaque tâche, divisez-vous en une tâche « générer le cache» dédiée qui exécute pull-push et que toutes les autres tâches utilisent uniquement policy: pull .

compresser la tâche

  • Installe la CLI via l’ancre partagée.
  • uip solution pack avec une version explicite — voir uip solution pack.
  • artifacts: déplace le .zip vers l'étape suivante. Le chemin est un grammaire ($OUTPUT_DIR/*.zip) pour qu'il récupère quel que soit le nom de fichier produit par uip solution pack . expire_in: 30 days empêche le stockage d’artefacts de GitLab de augmenter de manière illimitée; cassez-le si vous avez besoin d'une traçabilité plus longue.

déployer la tâche avec la matrice parallèle:

La matrice se développe en trois tâches — deploy: [dev, UIPATH_TENANT_DEV], deploy: [stage, UIPATH_TENANT_STAGE], deploy: [prod, UIPATH_TENANT_PROD] — qui s'exécutent en parallèle. Chacun obtient un $ENVIRONMENT et $TENANT_VAR différent, et utilise l'expansion indirecte bash (${!TENANT_VAR}) pour lire le locataire par environnement à partir de la variable CI/CD appropriée.

  • environment: name: uipath/$ENVIRONMENT — GitLab suit les déploiements dans sa vue Environnements afin que chaque locataire dispose d'un historique par environnement avec des boutons de restauration.
  • rules: — la première règle bloque prod des branches non protégées. Associé à Paramètres → Référentiel → Branches protégées (où vous marquez main protégé), c'est ainsi que vous empêchez une branche de fonctionnalité de se déployer accidentellement en production. Les variables UIPATH_CLIENT_* doivent également être marquées comme protégées afin de ne se résoudre que sur les références protégées.
  • uip login --client-id env.UIPATH_CLIENT_ID --client-secret env.UIPATH_CLIENT_SECRET — le préfixe env.VAR_NAME est le moyen pris en charge de transmettre une clé secrète à la CLI sans qu'elle n'apparaisse jamais dans la ligne de commande du shell. GitLab masque les variables dans les journaux lorsqu'elles sont marquées comme masqués, mais le préfixe env. est toujours une réponse approfondie. Voir Authentification — le préfixe env.VAR_NAME.
  • Nom du déploiement$SOLUTION_NAME-$ENVIRONMENT-$CI_PIPELINE_IID rend chaque déploiement traçable à une exécution de pipeline et à un environnement spécifiques.
Remarque :

Dans les tâches à matrice parallèle, si une branche échoue, les autres continuent de s'exécuter par défaut. Si vous souhaitez que la production attende le développement et l’étape de développement, transformez plutôt la matrice en trois tâches séquentielles (ou utilisez needs: entre elles).

Tâche de test

  • needs: fait référence à la partie de la matrice par son nom développé — "deploy: [dev, UIPATH_TENANT_DEV]". La variable optional: true rend la dépendance non fatale si l’élément de développement a été ignoré par le bloc rules: .
  • rules: ignore la tâche lorsque TEST_SET_KEY n'est pas défini, même modèle que les autres formules.
  • Lancer → attendre → vérifier — le modèle de test canonique de Comment faire: exécuter des tests à partir de la CLI. La sortie 2 de uip tm wait entraîne un délai d'expiration (pas un échec d'authentification).

Variations courantes

Production en série avec passerelle manuelle

Si vous souhaitez que la fonctionnalité Prod exige un clic manuel plutôt que le blocage de la branche protégée, divisez la matrice en trois tâches et ajoutez when: manual à la variable Prod:

deploy-dev:
  stage: deploy
  # …as deploy above, fixed to UIPATH_TENANT_DEV…

deploy-stage:
  stage: deploy
  needs: [ pack, deploy-dev ]
  # …as deploy above, fixed to UIPATH_TENANT_STAGE…

deploy-prod:
  stage: deploy
  needs: [ pack, deploy-stage ]
  when: manual                    # requires a reviewer to click "Play"
  allow_failure: false
  environment:
    name: uipath/prod
  # …as deploy above, fixed to UIPATH_TENANT_PRODdeploy-dev:
  stage: deploy
  # …as deploy above, fixed to UIPATH_TENANT_DEV…

deploy-stage:
  stage: deploy
  needs: [ pack, deploy-dev ]
  # …as deploy above, fixed to UIPATH_TENANT_STAGE…

deploy-prod:
  stage: deploy
  needs: [ pack, deploy-stage ]
  when: manual                    # requires a reviewer to click "Play"
  allow_failure: false
  environment:
    name: uipath/prod
  # …as deploy above, fixed to UIPATH_TENANT_PROD…

Restaurer (Rollback)

Déclenchez manuellement via une tâche distincte avec une variable de pipeline:

rollback:
  stage: deploy
  when: manual
  rules:
    - if: '$ROLLBACK_VERSION != null && $ROLLBACK_VERSION != ""'
  script:
    - *install-uip
    - |
      uip login \
        --client-id env.UIPATH_CLIENT_ID \
        --client-secret env.UIPATH_CLIENT_SECRET \
        --tenant "$UIPATH_TENANT_PROD"

      uip solution deploy run \
        --name "$SOLUTION_NAME-rollback" \
        --package-name "$SOLUTION_NAME" \
        --package-version "$ROLLBACK_VERSION" \
        --folder-name MySolution \
        --folder-path Shared
rollback:
  stage: deploy
  when: manual
  rules:
    - if: '$ROLLBACK_VERSION != null && $ROLLBACK_VERSION != ""'
  script:
    - *install-uip
    - |
      uip login \
        --client-id env.UIPATH_CLIENT_ID \
        --client-secret env.UIPATH_CLIENT_SECRET \
        --tenant "$UIPATH_TENANT_PROD"

      uip solution deploy run \
        --name "$SOLUTION_NAME-rollback" \
        --package-name "$SOLUTION_NAME" \
        --package-version "$ROLLBACK_VERSION" \
        --folder-name MySolution \
        --folder-path Shared

Démarrez le pipeline depuis CI/CD → Pipelines → Exécuter le pipeline et définissez ROLLBACK_VERSION sur la version cible (par exemple, 1.1.9). Pour une restauration irréversible (désinstallation + suppression d'artefact), consultez la section Comment procéder: compresser et publier une solution — restauration.

Ignorer les tests

Laissez TEST_SET_KEY indéfini dans les variables CI/CD. Le bloc rules: de la tâche test l'ignore proprement.

Erreurs courantes

  • Masqué != Protégé. Une variable masquée masque la valeur dans les journaux, mais est toujours disponible sur toutes les branches (y compris les branches de fonctionnalité éphémères). Une variable protégée n'expose que sur les références protégées. Vous souhaitez les deux pour les clés secrètes d'authentification - sinon une branche de fonctionnalité push pourrait exécuter uip login contre prod.
  • L'expansion indirecte a besoin de bash. ${!TENANT_VAR} est une fonctionnalité bash; la valeur sh par défaut dans certaines images minimales ne la prend pas en charge. L'image node:20 inclut bash par défaut; sur les images basées sur alpine , ajoutez apk add bash ou passez à une instruction de cas sur des variables explicites par environnement.
  • Les noms des tâches de matrice contiennent des espaces. needs: - job: "deploy: [dev, UIPATH_TENANT_DEV]" — le nom inclut : [, alors guillez-le en YAML.
  • Les chemins de cache sont relatifs à l’espace de travail. L'entrée de cache .npm-global/lib/node_modules fonctionne car NPM_PREFIX="$CI_PROJECT_DIR/.npm-global" la place dans l'espace de travail. Si vous déplacez le préfixe à l'extérieur, le cache cesse de fonctionner.
  • set -euo pipefail doit se trouver en haut de chaque script multiligne. Sans cela, un pack défaillant peut être suivi d’une publication « réussie» d’un artefact obsolète. Voir Modèles de script — Options shell strictes.

Voir également

Cette page vous a-t-elle été utile ?

Connecter

Besoin d'aide ? Assistance

Vous souhaitez apprendre ? UiPath Academy

Vous avez des questions ? UiPath Forum

Rester à jour