UiPath Documentation
uipath-cli
latest
false
重要 :
请注意,此内容已使用机器翻译进行了本地化。 新发布内容的本地化可能需要 1-2 周的时间才能完成。

UiPath CLI 用户指南

CI/CD 秘钥:GitLab CI

此页为您提供完整的.gitlab-ci.yml ,用于安装 CLI,使用外部应用程序进行身份验证,打包并发布 UiPath 解决方案,将其部署到跨多个租户的 Orchestrator(通过矩阵),并运行 Test Manager 套件。将其拖放到存储库的根目录中,设置三个 CI/CD 变量,然后它就会运行。

有关基本原则(身份验证、缓存、工具预安装、版本固定),请参阅操作方法:从 CI 部署到 Orchestrator 。本页面重点介绍 GitLab 语法,包括 GitLab 特定功能(具有键定作用域的缓存, parallel: matrix )。

先决条件

在复制以下 YAML 之前:

  1. 在 UiPath 中使用管道所需的OR.*作用域创建外部应用程序。请参阅身份验证 — 流程2
  2. 将密码存储为 CI/CD 变量:
    • 项目→设置→CI/CD→变量
    • 添加UIPATH_CLIENT_IDUIPATH_CLIENT_SECRET 。将两者标记为“已掩码”“已保护” (因此它们仅在受保护的分支/标签上公开)。
    • 添加UIPATH_TENANT_DEVUIPATH_TENANT_STAGEUIPATH_TENANT_PROD以及租户名称(未掩码 — 租户名称不敏感)。
  3. 如果您需要测试作业,请配置 Test Manager 项目和测试集。将TEST_SET_KEYPROJECT_KEY添加为常规变量。

.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

演练

顶级设置

  • image: node:20 — 每个作业都在官方 Node.js 20 映像中运行。CLI 要求 Node 18 及更高版本。如果您的 GitLab 运行器已安装 Node,并且您不需要容器,则可以删除其并改用shell执行程序。
  • variables: — 管道范围内的值。SOLUTION_VERSION$CI_PIPELINE_IID进行插值(项目作用域内的增量管道编号 — 比$CI_JOB_ID更适合版本控制,后者是全局性的非单调元素)。
  • .install-uip锚点— GitLab 不允许您直接锚点script:块,但您可以锚点包含 shell 字符串的 YAML 节点,并将其与- *install-uip拼接。安装防护与其他秘钥相同:工作区本地前缀、条件 CLI 安装。工具会在首次使用时自动安装,因此锚点仅处理主机。
  • cache: — 密钥uip-$CLI_VERSION可确保 CLI 版本提升会使缓存完全失效。policy: pull-push在入口处读取,在作业成功退出时写入。如果您大规模运行并希望缩短每个作业的秒数,请拆分为一个专用的“为缓存设定种子”作业,该作业运行pull-push ,并让所有其他作业仅使用policy: pull

打包作业

  • 通过共享锚点安装 CLI
  • 具有显式版本的uip solution pack — 请参阅uip solution pack
  • artifacts:.zip带到下一阶段。路径为通配符$OUTPUT_DIR/*.zip路径,因此系统会选取uip solution pack生成的任何文件名。expire_in: 30 days阻止 GitLab 的工件存储无限增长;如果您需要更长的可追溯性,则可以颠倒它。

使用并行部署作业:矩阵

矩阵展开为三个作业—— deploy: [dev, UIPATH_TENANT_DEV]deploy: [stage, UIPATH_TENANT_STAGE]deploy: [prod, UIPATH_TENANT_PROD] ——这三个作业并行运行。每个都具有不同的$ENVIRONMENT$TENANT_VAR ,并使用 bash 间接扩展 ( ${!TENANT_VAR} ) 从右侧的 CI/CD 变量读取每个环境的租户。

  • environment: name: uipath/$ENVIRONMENT — GitLab 在“环境”视图中跟踪部署,因此每个租户都会获得每个环境的历史记录,并带有回滚按钮。
  • rules: — 第一条规则阻止prod不受保护的分支。结合设置 → 存储库 → 受保护的分支(您可以在其中将main标记为“受保护”),这是阻止功能分支意外部署到生产的方法。UIPATH_CLIENT_*变量也应标记为“受保护” ,以便仅解析受保护的引用。
  • uip login --client-id env.UIPATH_CLIENT_ID --client-secret env.UIPATH_CLIENT_SECRET — 支持使用env.VAR_NAME前缀将密码传递给 CLI,而无需密码出现在 Shell 命令行中。当标记为“掩码”时,GitLab 会掩码日志中的变量,但无论怎样, env.前缀都是一种纵深防御措施。请参阅身份验证 — env.VAR_NAME 前缀
  • 部署名称$SOLUTION_NAME-$ENVIRONMENT-$CI_PIPELINE_IID使每个部署可追踪到特定管道运行和环境。
备注:

在并行矩阵作业中,如果一条分支出现故障,默认情况下其他分支会继续运行。如果您希望 Prod 等待开发和阶段,请将矩阵转换为三个连续的作业(或在它们之间使用needs: )。

测试作业

  • needs:通过扩展名称引用矩阵分支"deploy: [dev, UIPATH_TENANT_DEV]" 。如果rules:块跳过了开发阶段,则optional: true会使依赖项成为非严重。
  • 未设置rules:时, TEST_SET_KEY会跳过作业,模式与其他模式相同。
  • 启动 → 等待 → 验证操作方法:从 CLI 运行测试中的规范测试模式。从2退出uip tm wait意味着超时(非身份验证失败)。

常见变体

使用手动门进行序列提升

如果您希望 Prod 需要手动单击而不是受保护的分支门控,请将矩阵拆分为三个作业,并将when: manual添加到 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…

回滚

通过单独的作业使用管道变量手动触发:

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

CI/CD → 管道 → 运行管道启动管道,并将ROLLBACK_VERSION设置为目标版本(例如1.1.9 )。有关破坏性回滚(卸载并删除工件),请参阅操作方法:打包并发布解决方案 — 回滚

跳过测试

未设置 CI/CD 变量中的TEST_SET_KEYtest作业的rules:块会完全跳过该作业。

常见错误

  • 已掩码 != 受保护。掩码变量隐藏日志中的值,但仍然在所有分支(包括短期功能分支)上可用。受保护的变量仅在受保护的引用上公开。两者都需要用于身份验证密码,否则推送的功能分支可能会在生产环境中运行uip login
  • 间接扩展需要 bash。${!TENANT_VAR}是一项 bash 功能;某些最小映像中的默认sh不支持。默认情况下, node:20映像包含 bash;在基于alpine映像上,在显式的每个环境变量上添加apk add bash或切换到 case 语句。
  • Matrix 作业名称包含空格。needs: - job: "deploy: [dev, UIPATH_TENANT_DEV]" — 名称中包含: [ ,因此请在 YAML 中将其引用。
  • 缓存路径是相对于工作区的。缓存条目.npm-global/lib/node_modules可以正常运行,因为NPM_PREFIX="$CI_PROJECT_DIR/.npm-global"会将其放置在工作区中。如果将前缀移出,缓存将停止工作。
  • set -euo pipefail必须位于每个多行脚本的顶部。如果没有它,打包失败后可以“成功”发布过时的工件。请参阅脚本编写模式—严格 shell 选项

另请参阅

此页面有帮助吗?

连接

需要帮助? 支持

想要了解详细内容? UiPath Academy

有问题? UiPath 论坛

保持更新