Migration: pipeline examples
Before/after pipeline snippets for the four common CI platforms. Each example is the auth + pack + deploy core — the shortest portable shape. For full working pipelines (caching, stages, approvals, test stage), cross-link to the CI/CD recipes.
Read Command map and Flag renames first if you have not — this page shows the ported result, not the mapping rules.
Azure DevOps (YAML)
Before: a pipeline using the UiPath.CLI NuGet package and uipcli.exe via a Command Line task.
# Before — azure-pipelines.yml using legacy .NET CLI
trigger: [ main ]
pool:
vmImage: 'windows-2022'
variables:
UIPCLI_VERSION: '25.10.9401.39120'
ORCH_URL: 'https://cloud.uipath.com/'
ORCH_TENANT: 'DefaultTenant'
steps:
- task: NuGetCommand@2
displayName: 'Install UiPath.CLI.Windows'
inputs:
command: 'custom'
arguments: 'install UiPath.CLI.Windows -Version $(UIPCLI_VERSION) -OutputDirectory $(Agent.ToolsDirectory)\uipcli'
- script: |
set UIPCLI_PATH=$(Agent.ToolsDirectory)\uipcli\UiPath.CLI.Windows.$(UIPCLI_VERSION)\tools\uipcli.exe
"%UIPCLI_PATH%" package pack "$(Build.SourcesDirectory)\MyProject\project.json" ^
-o "$(Build.ArtifactStagingDirectory)" ^
--autoVersion --traceLevel Information
displayName: 'Pack project'
- script: |
set UIPCLI_PATH=$(Agent.ToolsDirectory)\uipcli\UiPath.CLI.Windows.$(UIPCLI_VERSION)\tools\uipcli.exe
"%UIPCLI_PATH%" package deploy "$(Build.ArtifactStagingDirectory)" ^
"$(ORCH_URL)" "$(ORCH_TENANT)" ^
-A "$(UIPATH_ORG)" ^
-I "$(UIPATH_CLIENT_ID)" ^
-S "$(UIPATH_CLIENT_SECRET)" ^
--applicationScope "OR.Folders OR.Execution OR.Assets" ^
--identityUrl "$(ORCH_URL)identity" ^
-o "Shared" ^
--processName "MyProcess" ^
--entryPointsPath "Main.xaml" ^
--traceLevel Information
displayName: 'Deploy package'
env:
UIPATH_CLIENT_ID: $(UIPATH_CLIENT_ID)
UIPATH_CLIENT_SECRET: $(UIPATH_CLIENT_SECRET)
After: the same flow with uip, running on ubuntu-latest. A full end-to-end Azure Pipelines recipe (caching, deployment stages with approvals, Test Manager stage) lives in CI/CD recipe: Azure Pipelines.
# After — azure-pipelines.yml using uip
trigger: [ main ]
pool:
vmImage: 'ubuntu-latest'
variables:
- group: uipath-prod # holds UIPATH_CLIENT_ID, UIPATH_CLIENT_SECRET
- name: CLI_VERSION
value: '1.0.0'
- name: UIPATH_TENANT
value: 'DefaultTenant'
steps:
- task: NodeTool@0
displayName: 'Use Node.js 20'
inputs:
versionSpec: '20.x'
- script: |
set -euo pipefail
npm install -g "@uipath/cli@$(CLI_VERSION)"
uip tools install or # pre-install the Orchestrator tool
uip tools install rpa # for rpa pack / analyze / restore
uip --version
displayName: 'Install UiPath CLI'
- script: |
set -euo pipefail
uip rpa pack ./MyProject --output ./dist --version "$(Build.BuildNumber)"
# See `uip rpa pack --help` for the complete flag list.
displayName: 'Pack project'
- script: |
set -euo pipefail
uip login \
--client-id env.UIPATH_CLIENT_ID \
--client-secret env.UIPATH_CLIENT_SECRET \
--tenant "$UIPATH_TENANT"
# Discover the packed file — version flows through from the pack step
PACKAGE=$(ls ./MyProject.*.nupkg | head -1)
# Upload to the tenant feed
uip or packages upload "$PACKAGE"
# Extract the uploaded package key (format: "PackageId:Version")
PKG_KEY=$(uip or packages upload "$PACKAGE" \
--output-filter 'Data[0].body' --output plain)
PKG_ID=${PKG_KEY%:*}
PKG_VER=${PKG_KEY#*:}
# Create or update the process
uip or processes create \
--name "MyProcess" \
--package-key "$PKG_ID" \
--package-version "$PKG_VER" \
--folder-path "Shared" \
--entry-point "Main.xaml"
displayName: 'Deploy package'
env:
UIPATH_CLIENT_ID: $(UIPATH_CLIENT_ID)
UIPATH_CLIENT_SECRET: $(UIPATH_CLIENT_SECRET)
UIPATH_TENANT: $(UIPATH_TENANT)
Key differences to review:
- Agent image.
ubuntu-latestworks now because the CLI is a Node tool. If you have other Windows-only pipeline steps, keepwindows-2022—uipruns on both. - Auth flag shape.
--client-id env.UIPATH_CLIENT_IDresolves from the environment without expanding onto the command line. Theenv:block at the step level wires the variable-group secret into the process environment. See Breaking changes — implicit env-var reading. - Pack + deploy split. Legacy
package deploy <folder>uploaded every.nupkgin the folder and created processes in one call.uipsplits upload (uip or packages upload) from create (uip or processes create). Capture the package key from the upload response to chain them cleanly. set -euo pipefail. Multi-line bash steps need strict mode so a pack failure aborts the step before deploy runs. See Scripting patterns — strict shell options.- No
--traceLevel. The new CLI uses--log-level(defaultinfo). Logs go to stderr and stay out of the JSON payload on stdout.
Cross-link: CI/CD recipe: Azure Pipelines — full stages, variable groups, deployment jobs with approvals, and a Test Manager stage.
Jenkins (declarative)
Before: a Windows-agent pipeline unpacking the UiPath.CLI.Windows NuGet and invoking uipcli.exe.
// Before — Jenkinsfile using legacy .NET CLI
pipeline {
agent { label 'windows' }
environment {
UIPCLI_VERSION = '25.10.9401.39120'
UIPCLI_PATH = "${env.WORKSPACE}\\uipcli\\UiPath.CLI.Windows.${UIPCLI_VERSION}\\tools\\uipcli.exe"
ORCH_URL = 'https://cloud.uipath.com/'
ORCH_TENANT = 'DefaultTenant'
}
stages {
stage('Install CLI') {
steps {
bat '''
curl -L -O https://www.nuget.org/api/v2/package/UiPath.CLI.Windows/%UIPCLI_VERSION%
tar -xf UiPath.CLI.Windows.%UIPCLI_VERSION%.nupkg -C uipcli
'''
}
}
stage('Pack') {
steps {
bat '"%UIPCLI_PATH%" package pack "%WORKSPACE%\\MyProject\\project.json" -o "%WORKSPACE%\\dist" --autoVersion'
}
}
stage('Deploy') {
steps {
withCredentials([
string(credentialsId: 'UIPATH_CLIENT_ID', variable: 'UIPATH_CLIENT_ID'),
string(credentialsId: 'UIPATH_CLIENT_SECRET', variable: 'UIPATH_CLIENT_SECRET')
]) {
bat '''
"%UIPCLI_PATH%" package deploy "%WORKSPACE%\\dist" "%ORCH_URL%" "%ORCH_TENANT%" ^
-A "%UIPATH_ORG%" -I "%UIPATH_CLIENT_ID%" -S "%UIPATH_CLIENT_SECRET%" ^
--applicationScope "OR.Folders OR.Execution OR.Assets" ^
--identityUrl "%ORCH_URL%identity" ^
-o "Shared" ^
--processName "MyProcess"
'''
}
}
}
}
}
After: Linux agent, npm install, session auth. A full Jenkinsfile with a Test Manager stage lives in CI/CD recipe: Jenkins.
// After — Jenkinsfile using uip
pipeline {
agent { label 'linux' }
environment {
CLI_VERSION = '1.0.0'
UIPATH_TENANT = 'DefaultTenant'
NPM_PREFIX = "${env.WORKSPACE}/.npm-global"
}
stages {
stage('Install CLI') {
steps {
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}"
uip tools install or
uip tools install rpa
fi
uip --version
'''
}
}
stage('Pack') {
steps {
sh '''#!/usr/bin/env bash
set -euo pipefail
export PATH="$NPM_PREFIX/bin:$PATH"
uip rpa pack ./MyProject
'''
}
}
stage('Deploy') {
steps {
withCredentials([
string(credentialsId: 'UIPATH_CLIENT_ID', variable: 'UIPATH_CLIENT_ID'),
string(credentialsId: 'UIPATH_CLIENT_SECRET', variable: 'UIPATH_CLIENT_SECRET')
]) {
sh '''#!/usr/bin/env bash
set -euo pipefail
export PATH="$NPM_PREFIX/bin:$PATH"
uip login \
--client-id env.UIPATH_CLIENT_ID \
--client-secret env.UIPATH_CLIENT_SECRET \
--tenant "$UIPATH_TENANT"
PACKAGE=$(ls ./MyProject.*.nupkg | head -1)
PKG_KEY=$(uip or packages upload "$PACKAGE" \
--output-filter "Data[0].body" --output plain)
PKG_ID=${PKG_KEY%:*}
PKG_VER=${PKG_KEY#*:}
uip or processes create \
--name "MyProcess" \
--package-key "$PKG_ID" \
--package-version "$PKG_VER" \
--folder-path "Shared" \
--entry-point "Main.xaml"
'''
}
}
}
}
}
Key differences to review:
withCredentials→env.prefix. Jenkins'withCredentialsblock exports the secret into the process environment; on the CLI side, reference it asenv.UIPATH_CLIENT_SECRETso it never expands onto the command line. Do not use--client-secret "$UIPATH_CLIENT_SECRET".- Agent label.
linux+ Node 18+ is the common case. If you must run on Windows,agent { label 'windows' }andbat '''npm install -g @uipath/cli …'''work — Node is cross-platform. NPM_PREFIXworkaround. Thenpm install -gtarget defaults to a path that may need root. SettingNPM_PREFIXto a workspace-local directory avoids the need forsudo. Cached by Jenkins between builds if the workspace is preserved.
Cross-link: CI/CD recipe: Jenkins — full declarative pipeline with stash/unstash, archiveArtifacts, test stage, and agent variations.
GitHub Actions
Before: a Windows runner installing UiPath.CLI.Windows from NuGet. Condensed to the deploy step for brevity.
# Before — .github/workflows/deploy.yml using legacy .NET CLI
jobs:
deploy:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install uipcli
run: |
nuget install UiPath.CLI.Windows -Version 25.10.9401.39120 -OutputDirectory $env:RUNNER_TEMP\uipcli
echo "UIPCLI_PATH=$env:RUNNER_TEMP\uipcli\UiPath.CLI.Windows.25.10.9401.39120\tools\uipcli.exe" >> $env:GITHUB_ENV
- name: Deploy
run: |
& "$env:UIPCLI_PATH" package deploy "${{ github.workspace }}\dist" `
"${{ vars.ORCH_URL }}" "${{ vars.ORCH_TENANT }}" `
-I "${{ secrets.UIPATH_CLIENT_ID }}" `
-S "${{ secrets.UIPATH_CLIENT_SECRET }}" `
--applicationScope "OR.Folders OR.Execution" `
-o "Shared" --processName "MyProcess"
After: Ubuntu runner, npm install, session auth.
# After — .github/workflows/deploy.yml using uip
jobs:
deploy:
runs-on: ubuntu-latest
env:
CLI_VERSION: '1.0.0'
UIPATH_TENANT: 'DefaultTenant'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install UiPath CLI
run: |
set -euo pipefail
npm install -g "@uipath/cli@${CLI_VERSION}"
uip tools install or
uip tools install rpa
- name: Pack
run: |
set -euo pipefail
uip rpa pack ./MyProject
- name: Deploy
env:
UIPATH_CLIENT_ID: ${{ secrets.UIPATH_CLIENT_ID }}
UIPATH_CLIENT_SECRET: ${{ secrets.UIPATH_CLIENT_SECRET }}
run: |
set -euo pipefail
uip login \
--client-id env.UIPATH_CLIENT_ID \
--client-secret env.UIPATH_CLIENT_SECRET \
--tenant "$UIPATH_TENANT"
PACKAGE=$(ls ./MyProject.*.nupkg | head -1)
PKG_KEY=$(uip or packages upload "$PACKAGE" \
--output-filter "Data[0].body" --output plain)
PKG_ID=${PKG_KEY%:*}
PKG_VER=${PKG_KEY#*:}
uip or processes create \
--name "MyProcess" \
--package-key "$PKG_ID" \
--package-version "$PKG_VER" \
--folder-path "Shared" \
--entry-point "Main.xaml"
Key differences:
env:at step level,env.VAR_NAMEin flags. GitHub Actions secrets are injected through the step'senv:block; the CLI reads them through--client-id env.UIPATH_CLIENT_ID. Never use--client-secret "${{ secrets.X }}"— that expands the secret literal into the workflow log.actions/setup-node@v4replaces every .NET / NuGet setup step.
Cross-link: CI/CD recipe: GitHub Actions — full workflow with matrix builds, artifact upload, and a test job.
GitLab CI
Before: a dotnet-sdk image unpacking UiPath.CLI from NuGet.
# Before — .gitlab-ci.yml using legacy .NET CLI
image: mcr.microsoft.com/dotnet/sdk:6.0
variables:
UIPCLI_VERSION: '25.10.9401.39120'
deploy:
script:
- |
dotnet tool install -g UiPath.CLI --version $UIPCLI_VERSION
uipcli package deploy "./dist" \
"$ORCH_URL" "$ORCH_TENANT" \
-I "$UIPATH_CLIENT_ID" -S "$UIPATH_CLIENT_SECRET" \
--applicationScope "OR.Folders OR.Execution" \
-o "Shared" --processName "MyProcess"
After: Node image, session auth, explicit env. references.
# After — .gitlab-ci.yml using uip
image: node:20
variables:
CLI_VERSION: '1.0.0'
UIPATH_TENANT: 'DefaultTenant'
deploy:
script:
- set -euo pipefail
- npm install -g "@uipath/cli@$CLI_VERSION"
- uip tools install or
- uip tools install rpa
- uip rpa pack ./MyProject
- |
uip login \
--client-id env.UIPATH_CLIENT_ID \
--client-secret env.UIPATH_CLIENT_SECRET \
--tenant "$UIPATH_TENANT"
- |
PACKAGE=$(ls ./MyProject.*.nupkg | head -1)
PKG_KEY=$(uip or packages upload "$PACKAGE" \
--output-filter "Data[0].body" --output plain)
PKG_ID=${PKG_KEY%:*}
PKG_VER=${PKG_KEY#*:}
uip or processes create \
--name "MyProcess" \
--package-key "$PKG_ID" \
--package-version "$PKG_VER" \
--folder-path "Shared" \
--entry-point "Main.xaml"
GitLab CI variables defined under the project's CI/CD settings (UIPATH_CLIENT_ID, UIPATH_CLIENT_SECRET, marked Masked and Protected) appear in the job's environment automatically, so the env. prefix on the CLI flags resolves without extra wiring.
Cross-link: CI/CD recipe: GitLab CI — full .gitlab-ci.yml with stages, artifacts, manual deploy gates, and a test stage.
Checklist for a clean port
Run through this before you commit the first pass:
-
uipcli.exeis no longer referenced anywhere in the pipeline files. -
UiPath.CLI/UiPath.CLI.WindowsNuGet install steps are removed. -
.NETordotnet-sdksetup is removed (unless other pipeline steps still need it). - Auth flags (
-u,-p,-t,-a,-I,-S,-A) are gone from every command. -
uip login --client-id env.X --client-secret env.Y --tenant Zis the single auth entry point. -
--identityUrlis renamed to--authority(only used for non-Automation-Cloud environments). -
--traceLevelis replaced by--log-level(or dropped). - Every shell parse of legacy
uipclitext stdout is replaced with--output-filter ... --output plainorjq. - Downstream expectations of
.nupkgfor Solutions are updated to.zip. - Exit-code branches (
case $?) use only0/1/2/3/4/130, withuip tm wait's timeout-reuses-2 handled explicitly. -
UIPATH_TELEMETRY_DISABLED=1is set if your org prohibits outbound telemetry.
See also
- Command map — verb-for-verb mapping.
- Flag renames — flag-for-flag mapping.
- Breaking changes — semantic differences behind the rename.
- CI/CD recipe: Azure Pipelines, Jenkins, GitHub Actions, GitLab CI — full recipes with caching, tests, promotion.
- Your first pipeline — hands-on walkthrough for new users.