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

Formule CI/CD : Jenkins

Cette page vous donne une Jenkinsfiledéclarative complète qui installe la CLI, s'authentifie avec une application externe, compresse et publie une solution UiPath, la déploie sur Orchestrator et exécute une suite Test Manager. Placez-la à la racine de votre référentiel, créez une entrée d'informations d'identification Jenkins correspondante et le pipeline 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 Jenkins, y compris les bits (withCredentials, stash / unstash, sélection de l'agent) qui sont spécifiques à Jenkins.

Prérequis

Avant de copier le fichier Jenkins:

  1. Créez une application externe dans UiPath avec les étendues OR.* dont votre pipeline a besoin. Voir Authentification — Flux 2.
  2. Stockez les secrets dans les informations d’identification Jenkins:
    • Gérer Jenkins → Informations d’identification → Système → Informations d’identification globales (sans restriction).
    • Ajoutez deux entrées de texte secrètes avec les ID UIPATH_CLIENT_ID et UIPATH_CLIENT_SECRET.
    • Ajoutez une entrée de texte brut ou de texte secret avec l’ID UIPATH_TENANT (le nom du locataire; pas strictement secret, mais les informations d’identification sont l’endroit le plus portable).
  3. Exigences de l'agent. Le pipeline suppose un agent labellisé linux avec Node.js 18+ et npm sur le PATH. Consultez les autres options d’agent ci-dessous si vous exécutez sous Windows ou dans un conteneur.
  4. Enregistrez un projet et un ensemble de tests Test Manager si vous souhaitez passer à l'étape de test. Ajoutez TEST_SET_KEY et PROJECT_KEY comme informations d'identification supplémentaires (ou comme paramètres de pipeline).

Fichier Jenkins

pipeline {
  agent none

  options {
    timestamps()
    buildDiscarder(logRotator(numToKeepStr: '30'))
    disableConcurrentBuilds()
  }

  environment {
    CLI_VERSION      = '1.0.0'
    SOLUTION_NAME    = 'my-solution'
    SOLUTION_DIR     = 'my-solution'
    OUTPUT_DIR       = 'dist'
    SOLUTION_VERSION = "1.2.0-ci.${env.BUILD_NUMBER}"

    // npm global prefix for a user-local, no-sudo install
    NPM_PREFIX       = "${env.WORKSPACE}/.npm-global"
  }

  stages {

    stage('Build') {
      agent { label 'linux' }
      steps {
        checkout scm
        sh '''#!/usr/bin/env bash
          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

          mkdir -p "$OUTPUT_DIR"
          uip solution pack "$SOLUTION_DIR" "$OUTPUT_DIR" \
            --name "$SOLUTION_NAME" \
            --version "$SOLUTION_VERSION"
        '''

        // Carry the .zip to the Deploy stage, which runs on a fresh agent.
        stash name: 'solution-zip', includes: "${OUTPUT_DIR}/*.zip"

        archiveArtifacts artifacts: "${OUTPUT_DIR}/*.zip", fingerprint: true
      }
    }

    stage('Deploy') {
      agent { label 'linux' }
      steps {
        unstash 'solution-zip'

        withCredentials([
          string(credentialsId: 'UIPATH_CLIENT_ID',     variable: 'UIPATH_CLIENT_ID'),
          string(credentialsId: 'UIPATH_CLIENT_SECRET', variable: 'UIPATH_CLIENT_SECRET'),
          string(credentialsId: 'UIPATH_TENANT',        variable: 'UIPATH_TENANT')
        ]) {
          sh '''#!/usr/bin/env bash
            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 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}-${BUILD_NUMBER}" \
              --package-name "$SOLUTION_NAME" \
              --package-version "$SOLUTION_VERSION" \
              --folder-name MySolution \
              --folder-path Shared
          '''
        }
      }
    }

    stage('Test') {
      when {
        expression { return env.TEST_SET_KEY?.trim() }
      }
      agent { label 'linux' }
      steps {
        withCredentials([
          string(credentialsId: 'UIPATH_CLIENT_ID',     variable: 'UIPATH_CLIENT_ID'),
          string(credentialsId: 'UIPATH_CLIENT_SECRET', variable: 'UIPATH_CLIENT_SECRET'),
          string(credentialsId: 'UIPATH_TENANT',        variable: 'UIPATH_TENANT'),
          string(credentialsId: 'TEST_SET_KEY',         variable: 'TEST_SET_KEY'),
          string(credentialsId: 'PROJECT_KEY',          variable: 'PROJECT_KEY')
        ]) {
          sh '''#!/usr/bin/env bash
            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 login \
              --client-id env.UIPATH_CLIENT_ID \
              --client-secret env.UIPATH_CLIENT_SECRET \
              --tenant "$UIPATH_TENANT"

            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
          '''
        }
      }
    }
  }

  post {
    always {
      // Best-effort cleanup; uip logout only matters on a persistent agent.
      node('linux') {
        sh '''
          if command -v uip >/dev/null; then
            uip logout || true
          fi
        '''
      }
    }
  }
}
pipeline {
  agent none

  options {
    timestamps()
    buildDiscarder(logRotator(numToKeepStr: '30'))
    disableConcurrentBuilds()
  }

  environment {
    CLI_VERSION      = '1.0.0'
    SOLUTION_NAME    = 'my-solution'
    SOLUTION_DIR     = 'my-solution'
    OUTPUT_DIR       = 'dist'
    SOLUTION_VERSION = "1.2.0-ci.${env.BUILD_NUMBER}"

    // npm global prefix for a user-local, no-sudo install
    NPM_PREFIX       = "${env.WORKSPACE}/.npm-global"
  }

  stages {

    stage('Build') {
      agent { label 'linux' }
      steps {
        checkout scm
        sh '''#!/usr/bin/env bash
          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

          mkdir -p "$OUTPUT_DIR"
          uip solution pack "$SOLUTION_DIR" "$OUTPUT_DIR" \
            --name "$SOLUTION_NAME" \
            --version "$SOLUTION_VERSION"
        '''

        // Carry the .zip to the Deploy stage, which runs on a fresh agent.
        stash name: 'solution-zip', includes: "${OUTPUT_DIR}/*.zip"

        archiveArtifacts artifacts: "${OUTPUT_DIR}/*.zip", fingerprint: true
      }
    }

    stage('Deploy') {
      agent { label 'linux' }
      steps {
        unstash 'solution-zip'

        withCredentials([
          string(credentialsId: 'UIPATH_CLIENT_ID',     variable: 'UIPATH_CLIENT_ID'),
          string(credentialsId: 'UIPATH_CLIENT_SECRET', variable: 'UIPATH_CLIENT_SECRET'),
          string(credentialsId: 'UIPATH_TENANT',        variable: 'UIPATH_TENANT')
        ]) {
          sh '''#!/usr/bin/env bash
            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 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}-${BUILD_NUMBER}" \
              --package-name "$SOLUTION_NAME" \
              --package-version "$SOLUTION_VERSION" \
              --folder-name MySolution \
              --folder-path Shared
          '''
        }
      }
    }

    stage('Test') {
      when {
        expression { return env.TEST_SET_KEY?.trim() }
      }
      agent { label 'linux' }
      steps {
        withCredentials([
          string(credentialsId: 'UIPATH_CLIENT_ID',     variable: 'UIPATH_CLIENT_ID'),
          string(credentialsId: 'UIPATH_CLIENT_SECRET', variable: 'UIPATH_CLIENT_SECRET'),
          string(credentialsId: 'UIPATH_TENANT',        variable: 'UIPATH_TENANT'),
          string(credentialsId: 'TEST_SET_KEY',         variable: 'TEST_SET_KEY'),
          string(credentialsId: 'PROJECT_KEY',          variable: 'PROJECT_KEY')
        ]) {
          sh '''#!/usr/bin/env bash
            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 login \
              --client-id env.UIPATH_CLIENT_ID \
              --client-secret env.UIPATH_CLIENT_SECRET \
              --tenant "$UIPATH_TENANT"

            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
          '''
        }
      }
    }
  }

  post {
    always {
      // Best-effort cleanup; uip logout only matters on a persistent agent.
      node('linux') {
        sh '''
          if command -v uip >/dev/null; then
            uip logout || true
          fi
        '''
      }
    }
  }
}

Présentation

Configuration de niveau supérieur

  • agent none en haut indique que le pipeline n'a pas d'agent par défaut; chaque étape sélectionne la sienne avec agent { label 'linux' } Cela vous permet de mettre le développement sur un agent haute capacité et le déploiement sur un agent verrouillé si votre infrastructure les sépare de cette manière.
  • optionstimestamps() ajoute des préfixes [2026-04-24T10:30:12] à chaque ligne de console, ce qui facilite le débogage des exécutions longues. disableConcurrentBuilds() empêche deux déploiements de s'exécuter dans le même dossier Orchestrator.
  • blocenvironment — le même modèle que les autres formules: épingler CLI_VERSION, calculer SOLUTION_VERSION à partir de BUILD_NUMBER et acheminer le préfixe global de npm vers l'espace de travail afin que les installations soient par construction et ne nécessitent pas sudo.

Créer l’étape

  • checkout scm — Jenkins en a besoin explicitement dans un pipeline déclaratif.
  • Étape d'installation — même garde-fou if ! command -v uip que les autres plates-formes. Le préfixe npm local de l'espace de travail ($NPM_PREFIX) signifie que chaque build démarre proprement; aucune mise en cache entre les exécutions. Si vos agents Jenkins sont persistants et que vous souhaitez mettre en cache la CLI, utilisez le plug-in Job Cacher ou définissez NPM_PREFIX sur un chemin sur l’agent plutôt que ${env.WORKSPACE}.
  • Étape de compression — directement uip solution pack avec une version explicite.
  • stash name: 'solution-zip' — il s'agit de la pièce spécifique à Jenkins. Contrairement aux artefacts d’actions GitHub ou aux pipelines Azure publish, une stash est limitée à l’exécution du pipeline et survient à travers les étapes sans nécessiter l’espace de travail pour persister. Le stash utilise une syntaxe générique (${OUTPUT_DIR}/*.zip) pour récupérer quel que soit le nom de fichier uip solution pack produit. Chaque étape qui a besoin des appels .zip appelle unstash 'solution-zip' à son début. Voir les documents Jenkins sur stash / unstash.
  • archiveArtifacts — une copie de .zip apparaît également sur la page du build pour les humains à télécharger. fingerprint: true permet à Jenkins de le suivre entre les tâches.

Étape de déploiement

  • unstash 'solution-zip' restaure le .zip dans l'espace de travail. Associé à un nouvel agent, cela sépare clairement la « création du contexte » du « déploiement du contexte ».
  • withCredentials lie trois entrées d'informations d'identification aux variables d'environnement visibles au bloc sh . La fermeture est la limite sécurisée pour les informations d'identification - les valeurs sont masquées dans le journal de la console et ne sont divulguées à aucune étape en dehors de ce bloc. Utilisez cette option pour chaque appel uip destiné à Orchestrator.
  • uip login utilise env.UIPATH_CLIENT_ID / env.UIPATH_CLIENT_SECRET — le préfixe env.VAR_NAME lit la variable définie par withCredentials. Voir Authentification — le préfixe env.VAR_NAME. N’interrogez jamais la clé secrète dans la ligne de commande directement (--client-secret "$UIPATH_CLIENT_SECRET") — qui l’intègre dans la commande shell rendue et, sous certaines configurations de journalisation, dans la sortie de la console.
  • Publier + déployeruip solution publish puis uip solution deploy run --name "${SOLUTION_NAME}-${BUILD_NUMBER}" rend chaque déploiement traçable jusqu'à son build Jenkins.

Étape de test

Limité par when { expression { return env.TEST_SET_KEY?.trim() } } — si vous ne définissez pas les informations d'identification TEST_SET_KEY (ou si vous la laissez vide), l'étape est ignorée. Le bloc shell est le lancement canonique → attendre → vérifier le modèle de Comment faire: exécuter des tests à partir de la CLI:

  1. uip tm testsets run se lance et renvoie une ExecutionId.
  2. uip tm wait bloque jusqu'à ce que l'exécution atteigne un état terminal. Sur wait, le code de sortie 2 indique un délai d'expiration (pas un échec d'authentification — il s'agit d'une réutilisation du code spécifique au domaine).
  3. uip tm report get lit Data.Failed et le shell quitte 1 lorsqu'un test a échoué.

publier { toujours }

Dans la mesure du possible uip logout. Sur les agents éphémères, cela n'est pas nécessaire; sur un agent persistant, il efface le dossier .uipath/ local de l'espace de travail afin qu'une tâche ultérieure sur le même espace de travail n'utilise pas de session obsolète. L' || true gère l'erreur si uip n'a jamais été installé (la génération a échoué avant l'installation).

Variations courantes

Variations d’agent

  • Agent Windows — Remplacez sh par bat, traduisez les scripts bash en cmd.exe ou PowerShell. Le préfixe env. et toutes les commandes uip sont identiques; seul le shell environnement change. Voir Installation de la UiPath CLI — Windows.
  • Agent Dockeragent { docker { image 'node:20' } } vous donne un nouveau runtime Node par build avec zéro configuration d'agent. Ajoutez args '-u root' si vous avez besoin d'installations globales de NPM sans sudo dans une image racine; sinon, configurez le préfixe NPM sur $WORKSPACE/.npm-global comme ci-dessus et ignorez la danse des privilèges.
  • Plug-in Kubernetes - utilisez un modèle de pod avec un conteneur node:20 et installez /root/.npm-global en tant que PVC pour mettre en cache la CLI entre les versions.

Promouvoir dans tous les environnements

Transformez chaque environnement en sa propre étape, en réutilisant le même stash:

stage('Deploy stage') {
  agent { label 'linux' }
  steps {
    unstash 'solution-zip'
    withCredentials([string(credentialsId: 'UIPATH_STAGE_CLIENT_ID', variable: 'UIPATH_CLIENT_ID'), ...]) {
      sh '...deploy to stage tenant...'
    }
  }
}

stage('Approval') {
  steps {
    input message: 'Deploy to production?', ok: 'Deploy'
  }
}

stage('Deploy prod') {
  agent { label 'linux' }
  steps {
    unstash 'solution-zip'
    withCredentials([string(credentialsId: 'UIPATH_PROD_CLIENT_ID', variable: 'UIPATH_CLIENT_ID'), ...]) {
      sh '...deploy to prod tenant...'
    }
  }
}
stage('Deploy stage') {
  agent { label 'linux' }
  steps {
    unstash 'solution-zip'
    withCredentials([string(credentialsId: 'UIPATH_STAGE_CLIENT_ID', variable: 'UIPATH_CLIENT_ID'), ...]) {
      sh '...deploy to stage tenant...'
    }
  }
}

stage('Approval') {
  steps {
    input message: 'Deploy to production?', ok: 'Deploy'
  }
}

stage('Deploy prod') {
  agent { label 'linux' }
  steps {
    unstash 'solution-zip'
    withCredentials([string(credentialsId: 'UIPATH_PROD_CLIENT_ID', variable: 'UIPATH_CLIENT_ID'), ...]) {
      sh '...deploy to prod tenant...'
    }
  }
}

L'étape input suspend le pipeline jusqu'à ce qu'un humain clique sur Déployer. Utilisez la stratégie d'autorisation par matrice de Jenkins pour restreindre qui peut approuver. Couverture plus approfondie dans Comment procéder: compresser et publier une solution — promouvoir un package entre les locataires.

Restaurer (Rollback)

Ajoutez une tâche paramétrée — Jenkins → Nouvel élément → Pipeline → Ce projet est paramétré → Ajouter un paramètre (Chaîne) → "ROLLBack_VERSION" — et ajoutez une étape gardee:

stage('Rollback') {
  when { expression { return params.ROLLBACK_VERSION?.trim() } }
  agent { label 'linux' }
  steps {
    withCredentials([/* UIPATH_* credentials */]) {
      sh '''#!/usr/bin/env bash
        set -euo pipefail
        # …install + login…

        uip solution deploy run \
          --name "${SOLUTION_NAME}-rollback" \
          --package-name "$SOLUTION_NAME" \
          --package-version "$ROLLBACK_VERSION" \
          --folder-name MySolution \
          --folder-path Shared
      '''
    }
  }
  environment {
    ROLLBACK_VERSION = "${params.ROLLBACK_VERSION}"
  }
}
stage('Rollback') {
  when { expression { return params.ROLLBACK_VERSION?.trim() } }
  agent { label 'linux' }
  steps {
    withCredentials([/* UIPATH_* credentials */]) {
      sh '''#!/usr/bin/env bash
        set -euo pipefail
        # …install + login…

        uip solution deploy run \
          --name "${SOLUTION_NAME}-rollback" \
          --package-name "$SOLUTION_NAME" \
          --package-version "$ROLLBACK_VERSION" \
          --folder-name MySolution \
          --folder-path Shared
      '''
    }
  }
  environment {
    ROLLBACK_VERSION = "${params.ROLLBACK_VERSION}"
  }
}

Déclencheur à partir de la page de création avec Créer avec des paramètres. Pour une restauration irréversible (désinstallation + suppression d'artefact), consultez la section Comment procéder: compresser et publier une solution — restauration.

Erreurs courantes

  • withCredentials étendue. Les informations d’identification sont disponibles uniquement à l’intérieur de la fermeture. Si vous appelez uip login à l'intérieur withCredentials et uip solution publish à l'extérieur, la deuxième commande n'a pas de session. Conservez l'ensemble du bloc CLI dans un withCredentials.
  • stash avant de changer d'agent. Un stash déclaré dans une seule étape ne sera utilisable dans les étapes ultérieures que si l’étape de blocage s’est terminée avant que l’agent ne change de. Si le bloc shell de l'étape Build se termine par une valeur non nulle avant stash, les étapes ultérieures échoueront à unstash. Mettre stash en dehors du bloc sh — comme dans cette règle — garantit qu'il s'exécute sur un agent propre quel que soit le résultat du shell.
  • || true au mauvais moment. L’ uip logout || true dans post est en sécurité, car le seul mode d’échec est « uip n’a jamais été installé». Ne processus pas || true en présentant les étapes précédentes - cela masque les échecs réels.
  • sh en mode strict. Démarrez le script bash de chaque bloc sh par #!/usr/bin/env bash et set -euo pipefail. Le shell Jenkins par défaut est /bin/sh, qui ne prend pas en charge pipefail. Voir Modèles de script — Options shell strictes.
  • Chaînes multilignes au format URL. Préférez les chaînes à triple guillemet ('''...''') pour les corps du shell — elles n'interrogent pas $VAR, de sorte que la variable est développée par bash plutôt que par Gourly. Cela évite une classe courante de bogues « la variable est vide». Pour les valeurs que vous souhaitez que Goin se termine au moment de la compilation du pipeline, utilisez ${env.SOME_VAR} explicitement.

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