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: GitLab CI

Esta página te ofrece una .gitlab-ci.yml completa que instala la CLI, se autentica con una aplicación externa, empaqueta y publica una solución de UiPath, la implementa en Orchestrator en varios tenants (a través de una matriz) y ejecuta una suite de Test Manager. Suéltalo en la raíz de tu repositorio, establece tres variables CI/CD y 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 GitLab, incluidas las características (caché con un ámbito con clave, parallel: matrix) que son específicas de GitLab.

Requisitos previos

Antes de copiar el siguiente YAML:

  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 como variables CI/CD:
    • Proyecto → Configuración → CI/CD → Variables.
    • Añade UIPATH_CLIENT_ID y UIPATH_CLIENT_SECRET. Marca ambos como Enmascarados y Protegidos (para que solo se expongan en ramas/etiquetas protegidas).
    • Añade UIPATH_TENANT_DEV, UIPATH_TENANT_STAGE, UIPATH_TENANT_PROD con los nombres de los tenants (no enmascarados: los nombres de los tenants no son confidenciales).
  3. Aprovisiona un proyecto de Test Manager y un conjunto de pruebas si quieres el trabajo de prueba. Añade TEST_SET_KEY y PROJECT_KEY como variables regulares.

.gitlab-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

Tutorial

Configuración de nivel superior

  • image: node:20 : cada trabajo se ejecuta en la imagen oficial de Node.js 20. La CLI requiere Node 18+. Si tu ejecutor de GitLab ya tiene Node instalado y no necesitas un contenedor, puedes eliminarlo y utilizar un ejecutor shell en su lugar.
  • variables: : los valores de todo el proceso. SOLUTION_VERSION interpola $CI_PIPELINE_IID (el número de proceso incremental en el ámbito del proyecto, mejor para el control de versiones que $CI_JOB_ID, que es global y no monótono).
  • Anclaje.install-uip : GitLab no te permite anclar bloques script: directamente, pero puedes anclar un nodo YAML que contenga una cadena de shell y empalmarlo con - *install-uip. La misma protección de instalación que las otras recetas: prefijo local del espacio de trabajo, instalación CLI condicional. Las herramientas se instalan automáticamente en el primer uso, por lo que el anclaje solo maneja el host.
  • cache: : la clave uip-$CLI_VERSION garantiza que un aumento de la versión CLI invalide la caché de forma limpia. policy: pull-push lee en la entrada y escribe en la salida del trabajo con éxito. Si ejecutas a escala y quieres ahorrar segundos en cada trabajo, divídelo en un trabajo dedicado a "sembrar la caché" que se ejecute pull-push y haz que todos los demás trabajos utilicen solo policy: pull .

Empaquetar trabajo

  • Instala la CLI a través del anclaje compartido.
  • uip solution pack con una versión explícita — consulta uip solution pack.
  • artifacts: lleva .zip a la siguiente etapa. La ruta es un global ($OUTPUT_DIR/*.zip), por lo que recoge cualquier nombre de archivo que produzca uip solution pack . expire_in: 30 days evita que el almacenamiento de artefactos de GitLab crezca sin límites; elimínelo si necesita una trazabilidad más larga.

implementar trabajo con paralelo: matriz

La matriz se expande en tres trabajos, deploy: [dev, UIPATH_TENANT_DEV], deploy: [stage, UIPATH_TENANT_STAGE], deploy: [prod, UIPATH_TENANT_PROD] , que se ejecutan en paralelo. Cada uno obtiene un $ENVIRONMENT y $TENANT_VAR diferentes, y utiliza la expansión indirecta de bash (${!TENANT_VAR}) para leer el tenant por entorno de la variable CI/CD derecha.

  • environment: name: uipath/$ENVIRONMENT — GitLab realiza un seguimiento de las implementaciones en su vista de Entornos, por lo que cada tenant obtiene un historial por entorno con botones de reversión.
  • rules: : la primera regla bloquea prod de las ramas no protegidas. Combinado con Configuración → Repositorio → Ramas protegidas (donde marcas main protegido), así es como evitas que una rama de características se implemente accidentalmente en producción. Las variables UIPATH_CLIENT_* también deben marcarse como Protegidas para que solo se resuelvan en referencias protegidas.
  • uip login --client-id env.UIPATH_CLIENT_ID --client-secret env.UIPATH_CLIENT_SECRET — el prefijo env.VAR_NAME es la forma admitida de pasar un secreto a la CLI sin que aparezca nunca en la línea de comandos del shell. GitLab enmascara las variables en los registros cuando se marcan como Enmascaradas, pero el prefijo env. es una defensa en profundidad de todos modos. Consulta Autenticación: el prefijo env.VAR_NAME.
  • Nombre de la implementación : $SOLUTION_NAME-$ENVIRONMENT-$CI_PIPELINE_IID hace que cada implementación sea rastreable a una ejecución y entorno de proceso específicos.
Nota:

En los trabajos de matriz paralela, si falla un tramo, los demás siguen ejecutándose de forma predeterminada. Si quieres que producción espere a dev y etapa, convierte la matriz en tres trabajos secuenciales (o utiliza needs: entre ellos) en su lugar.

trabajo de prueba

  • needs: hace referencia a la rama de la matriz por su nombre expandido: "deploy: [dev, UIPATH_TENANT_DEV]". optional: true hace que la dependencia no sea grave si el bloque rules: omite la etapa de desarrollo.
  • rules: omite el trabajo cuando TEST_SET_KEY no está configurado, el mismo patrón que las otras recetas.
  • Iniciar → esperar → verificar : el patrón de prueba canónico de Tutorial: ejecutar pruebas desde la CLI. La salida 2 de uip tm wait significa tiempo de espera (no fallo de autenticación).

Variaciones comunes

Promoción en serie con puerta manual

Si quieres que prod requiera un clic manual en lugar de una activación de rama protegida, divide la matriz en tres trabajos y añade when: manual al de 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…

Reversión

Desencadenador manual a través de un trabajo independiente con una variable de proceso:

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

Inicia el proceso desde CI/CD → Procesos → Ejecutar proceso y establece ROLLBACK_VERSION en la versión de destino (por ejemplo, 1.1.9). Para la reversión destructiva (desinstalar + eliminar artefacto), consulta Tutorial: empaquetar y publicar una solución: reversión.

Omitir pruebas

Deja TEST_SET_KEY sin establecer en las variables CI/CD. El bloque rules: en el trabajo test lo omite limpiamente.

Errores comunes

  • Enmascarado != Protegido. Una variable enmascarada oculta el valor en los registros, pero sigue estando disponible en todas las ramas (incluidas las ramas de características de corta duración). Una variable protegida solo se expone en referencias protegidas. Quieres ambos para los secretos de autenticación; de lo contrario, una rama de característica insertada podría ejecutarse uip login en prod.
  • La expansión indirecta necesita bash. ${!TENANT_VAR} es una característica bash; el sh predeterminado en algunas imágenes mínimas no lo admite. La imagen node:20 incluye bash de forma predeterminada; en imágenes basadas en alpine , añade apk add bash o cambia a una declaración de caso sobre variables explícitas por entorno.
  • Los nombres de trabajos de matriz contienen espacios. needs: - job: "deploy: [dev, UIPATH_TENANT_DEV]" : el nombre incluye : [, así que cítalo en YAML.
  • Las rutas de caché son relativas al espacio de trabajo. La entrada de caché .npm-global/lib/node_modules funciona porque NPM_PREFIX="$CI_PROJECT_DIR/.npm-global" la coloca dentro del espacio de trabajo. Si mueves el prefijo fuera, la caché deja de funcionar.
  • set -euo pipefail debe estar en la parte superior de cada script multilínea. Sin él, un paquete fallido puede ser seguido por una publicación "correcta" de un artefacto obsoleto. Consulta Patrones de scripts: opciones de shell estrictas.

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