UiPath Documentation
uipath-cli
latest
false
Importante :
Este contenido se ha traducido mediante traducción automática. La localización de contenidos recién publicados puede tardar entre una y dos semanas en estar disponible.

Guía del usuario de UiPath CLI

Receta CI/CD: Jenkins

Esta página te ofrece un Jenkinsfiledeclarativo completo que instala la CLI, se autentica con una aplicación externa, empaqueta y publica una solución de UiPath, la implementa en Orchestrator y ejecuta una suite de Test Manager. Colócalo en la raíz de tu repositorio, crea una entrada de credenciales de Jenkins coincidente y el proceso se ejecuta.

Para conocer los principios subyacentes (autenticación, almacenamiento en caché, preinstalación de herramientas, fijación de versiones), consulta Cómo: implementar en Orchestrator desde CI. Esta página se centra en la sintaxis de Jenkins, incluidos los bits (withCredentials, stash / unstash, selección de agente) que son específicos de Jenkins.

Requisitos previos

Antes de copiar el archivo Jenkins:

  1. Cree una aplicación externa en UiPath con los OR.* ámbitos que necesita su proceso. Consulta Autenticación: flujo 2.
  2. Almacena los secretos en las credenciales de Jenkins:
    • Gestionar Jenkins → Credenciales → Sistema → Credenciales globales (sin restricciones).
    • Añade dos entradas de texto Secreto con los ID UIPATH_CLIENT_ID y UIPATH_CLIENT_SECRET.
    • Añade una entrada de Texto sin formato o Texto secreto con ID UIPATH_TENANT (el nombre del tenant; no es estrictamente secreto, pero las credenciales son el lugar más portátil).
  3. Requisitos del agente. El proceso asume un agente etiquetado linux con Node.js 18+ y npm en la RUTA. Consulta las opciones de agente alternativas a continuación si ejecutas en Windows o en un contenedor.
  4. Aprovisiona un proyecto de Test Manager y un conjunto de pruebas si quieres la etapa de prueba. Añade TEST_SET_KEY y PROJECT_KEY como credenciales adicionales (o como parámetros del proceso).

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

Tutorial

Configuración de nivel superior

  • agent none en la parte superior declara que el proceso no tiene agente predeterminado; cada etapa elige la suya con agent { label 'linux' }. Esto te permite poner la compilación en un agente de alta capacidad y la implementación en un agente bloqueado si tu infraestructura los separa de esa manera.
  • optionstimestamps() añade prefijos [2026-04-24T10:30:12] a cada línea de la consola, lo que facilita mucho la depuración de ejecuciones largas. disableConcurrentBuilds() evita que dos implementaciones compitan en la misma carpeta de Orchestrator.
  • Bloqueenvironment : el mismo patrón que las otras recetas: fijar CLI_VERSION, calcular SOLUTION_VERSION desde BUILD_NUMBER y enrutar el prefijo global de npm al espacio de trabajo para que las instalaciones sean por compilación y no necesiten sudo.

Fase de compilación

  • checkout scm — Jenkins lo necesita explícitamente en un proceso declarativo.
  • Paso de instalación : el mismo if ! command -v uip guard que en otras plataformas. El prefijo npm local del espacio de trabajo ($NPM_PREFIX) significa que cada compilación comienza limpia; sin almacenamiento en caché en las ejecuciones. Si tus agentes de Jenkins son persistentes y deseas almacenar en caché la CLI, utiliza el complemento Job Cacher o establece NPM_PREFIX en una ruta en el agente en lugar de ${env.WORKSPACE}.
  • Paso de paquete : uip solution pack directo con una versión explícita.
  • stash name: 'solution-zip' : esta es la pieza específica de Jenkins. A diferencia de los artefactos de GitHub Actions o los publish Procesos de Azure, un stash tiene como ámbito la ejecución del proceso y sobrevive en todas las etapas sin necesidad de que el espacio de trabajo persista. El alijo utiliza un global (${OUTPUT_DIR}/*.zip), por lo que recoge cualquier nombre de archivo que produzca uip solution pack . Cada etapa que necesita las llamadas .zip unstash 'solution-zip' en su inicio. Consulta los documentos de Jenkins en stash / unstash.
  • archiveArtifacts : también aparece una copia de .zip en la página de compilación para que los humanos la descarguen. fingerprint: true permite a Jenkins realizar un seguimiento en todos los trabajos.

Etapa de implementación

  • unstash 'solution-zip' restaura .zip al espacio de trabajo. Combinado con un agente nuevo, esto separa claramente el "contexto de creación" del "contexto de implementación".
  • withCredentials vincula tres entradas de credenciales a variables de entorno visibles para el bloque sh . El cierre es el límite de seguridad de las credenciales: los valores se enmascaran en el registro de la consola y no se filtran a ningún paso fuera de este bloque. Usa esto para cada llamada uip que hable con Orchestrator.
  • uip login utiliza env.UIPATH_CLIENT_ID / env.UIPATH_CLIENT_SECRET : el prefijo env.VAR_NAME lee la variable establecida por withCredentials. Consulta Autenticación: el prefijo env.VAR_NAME. Nunca interpoles el secreto en la línea de comandos directamente (--client-secret "$UIPATH_CLIENT_SECRET"), que lo incrusta en el comando de shell renderizado y, en algunas configuraciones de registro, en la salida de la consola.
  • Publicar e implementar : uip solution publish y luego uip solution deploy run. --name "${SOLUTION_NAME}-${BUILD_NUMBER}" hace que cada implementación sea rastreable hasta su compilación de Jenkins.

Etapa de prueba

Cerrado por when { expression { return env.TEST_SET_KEY?.trim() } } : si no estableces la credencial TEST_SET_KEY (o la dejas vacía), se omite la etapa. El bloque de shell es el patrón canónico de lanzamiento → esperar → verificar de Tutorial: ejecutar pruebas desde la CLI:

  1. uip tm testsets run inicia y devuelve un ExecutionId.
  2. uip tm wait se bloquea hasta que la ejecución alcanza un estado terminal. El wait, el código de salida 2 significa tiempo de espera (no fallo de autenticación: es una reutilización del código específica del dominio).
  3. uip tm report get lee Data.Failed y el shell cierra 1 cuando falla cualquier prueba.

publicar { siempre }

Mejor esfuerzo uip logout. En agentes efímeros esto es innecesario; en un agente persistente, borra la carpeta local del espacio de trabajo .uipath/ para que un trabajo posterior en el mismo espacio de trabajo no reutilice una sesión obsoleta. || true se traga el error si uip nunca se instaló (la compilación falló antes de la instalación).

Variaciones comunes

Variaciones de agente

  • Agente de Windows : reemplaza sh por bat, traduce los scripts bash a cmd.exe o PowerShell. El prefijo env. y todos los comandos uip son idénticos; solo cambia el shell circundante. Consulta Instalar UiPath CLI: Windows.
  • Agente de Docker : agent { docker { image 'node:20' } } te ofrece un nuevo runtime de Node por compilación sin configuración de agente. Añade args '-u root' si necesitas instalaciones globales de npm sin sudo en una imagen raíz; de lo contrario, configura el prefijo NPM en $WORKSPACE/.npm-global como se indica arriba y omite el baile de privilegios.
  • Complemento de Kubernetes : utiliza una plantilla de pod con un contenedor node:20 y monta /root/.npm-global como PVC para almacenar en caché la CLI entre compilaciones.

Promocionar en todos los entornos

Convierte cada entorno en su propia etapa, reutilizando el mismo 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...'
    }
  }
}

El paso input detiene el proceso hasta que un humano haga clic en Implementar. Utiliza la estrategia de autorización de matriz de Jenkins para restringir quién puede aprobar. Cobertura más profunda en Tutorial: empaquetar y publicar una solución: promocionar un paquete entre tenants.

Reversión

Añade un trabajo parametrizado — Jenkins → Nuevo elemento → Proceso → Este proyecto está parametrizado → Añadir parámetro (cadena) → "ROLLBACK_VERSION" — y añade una etapa vigilada:

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

Desencadenador desde la página de compilación con Crear con parámetros. Para la reversión destructiva (desinstalar + eliminar artefacto), consulta Tutorial: empaquetar y publicar una solución: reversión.

Errores comunes

  • withCredentials ámbito. Las credenciales solo están disponibles dentro del cierre. Si llamas uip login dentro de withCredentials y uip solution publish fuera, el segundo comando no tiene sesión. Mantén todo el bloque CLI dentro de un withCredentials.
  • stash antes de cambiar de agente. Un stash declarado en una etapa solo se puede utilizar en etapas posteriores si el paso de ocultación se ejecutó hasta completarse antes de que el agente cambiara. Si el bloque de shell de la etapa Build sale con un valor distinto de cero antes de stash, las etapas posteriores fallarán en unstash. Poner stash fuera del bloque sh , como en esta receta, garantiza que se ejecute en un agente limpio independientemente del resultado del shell.
  • || true en el momento equivocado. El uip logout || true en post es seguro porque el único modo de error es "uip nunca se instaló". No salpiques || true a través de etapas anteriores: oculta fallos reales.
  • modosh . Inicia cada script bash del bloque sh con #!/usr/bin/env bash y set -euo pipefail. El shell predeterminado de Jenkins es /bin/sh, que no admite pipefail. Consulta Patrones de scripts: opciones de shell estrictas.
  • Cadenas multilínea en Groovy. Prefiere las cadenas triples entre comillas simples ('''...''') para los cuerpos de shell: no interpolan $VAR, por lo que la variable se expande por bash en lugar de por Groovy. Esto evita una clase común de errores de "variable está vacía". Para los valores que deseas que Groovy rellene en el momento de compilar el proceso, utiliza ${env.SOME_VAR} explícitamente.

Ver también

¿Te ha resultado útil esta página?

Conectar

¿Necesita ayuda? Soporte

¿Quiere aprender? UiPath Academy

¿Tiene alguna pregunta? Foro de UiPath

Manténgase actualizado