Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7a357da
Add Python IPC library (uipath-ipc) with server and client
eduard-dumitru Mar 31, 2026
cb91b01
python taking shape
eduard-dumitru Mar 31, 2026
9bab3ae
Add .NET interop test and fix named pipe concurrent I/O
eduard-dumitru Mar 31, 2026
6447210
Move existing Python attempt to _attempt0/
eduard-dumitru May 27, 2026
81f2c10
Scaffold uipath-ipc Python client package
eduard-dumitru May 27, 2026
87eb6a7
Add Visual Studio project file for uipath-ipc
eduard-dumitru May 27, 2026
51fe9b1
Wire up pytest test scaffolding
eduard-dumitru May 27, 2026
e2dd701
Switch uipath-ipc pyproj to glob-based file enumeration
eduard-dumitru May 28, 2026
f96ca15
Add wire DTOs and round-trip tests
eduard-dumitru May 28, 2026
0b36250
Add wire framing layer
eduard-dumitru May 28, 2026
b30455b
Add NamedPipeClientTransport
eduard-dumitru May 28, 2026
5c391b1
Add IpcConnection — request/response dispatcher
eduard-dumitru May 28, 2026
fca5df3
Add IpcClient + dynamic proxy
eduard-dumitru May 28, 2026
2c7abe6
Refine RemoteException — message/type/stack/chain mapping
eduard-dumitru May 28, 2026
ac0fd75
Forward caller cancellation to the server
eduard-dumitru May 28, 2026
c328cb0
Add per-client request timeout
eduard-dumitru May 28, 2026
1a2412f
Auto-reconnect on transport disconnect
eduard-dumitru May 28, 2026
2feb512
Add TcpClientTransport
eduard-dumitru May 28, 2026
2392e23
Polish: README, py.typed, explicit wheel packaging, smoke checks
eduard-dumitru May 28, 2026
3fd4eb7
Add gated .NET interop tests
eduard-dumitru May 28, 2026
3dfbf3a
Flip integration tests to opt-out
eduard-dumitru May 28, 2026
4a50117
Retry briefly on FileNotFoundError when connecting a named pipe
eduard-dumitru May 28, 2026
2d9689f
Add dedicated .NET test server and fix wire serialization
eduard-dumitru May 28, 2026
b48e3cc
Add debugpy to dev extras
eduard-dumitru May 28, 2026
b3cdd0e
Wire CI for project-scoped npm feed and bypass Safe Chain Guard
eduard-dumitru May 28, 2026
ad36ce6
Parameterize CI: opt-in publish stages, reuseArtifactsFromBuildId
eduard-dumitru May 28, 2026
5260b42
Publish NPM to uipath-ipc-deps as primary; GitHub Packages best-effort
eduard-dumitru May 28, 2026
2b93f16
Fix Npm@1 publish param name: publishFeed (not publishFeedCombined)
eduard-dumitru May 28, 2026
26ef0fd
Add Python build, test, and publish to the pipeline (Pass 2)
eduard-dumitru May 28, 2026
fb7d06a
Apply Windows-style FileNotFoundError retry to POSIX connect too
eduard-dumitru May 28, 2026
05009da
Default reuseArtifactsFromBuildId to '0' (no-reuse sentinel)
eduard-dumitru May 28, 2026
41bf13f
Bind Python package version to the same source as NuGet/NPM
eduard-dumitru May 28, 2026
7e441e2
Split Build into per-technology stages (NuGet / NPM / Python)
eduard-dumitru May 28, 2026
402e9ec
Add opt-out build parameters (buildNuGet / buildNpm / buildPython)
eduard-dumitru May 28, 2026
1411701
Add server-to-client callback support (uipath-ipc 0.2.0)
eduard-dumitru May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions src/CI/azp-dotnet-dist.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ steps:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactType: 'Container'

- task: DotNetCoreCLI@2
displayName: 'dotnet push to UiPath-Internal'
condition: succeeded()
inputs:
command: push
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg'
publishVstsFeed: 'Public.Feeds/UiPath-Internal'
# The `dotnet nuget push` step previously lived here and fired on every
# build (condition: succeeded). It now lives in
# `azp-nuget.publish.steps.yaml` under the Publish_NuGet stage, gated on
# the `publishNuGet` pipeline parameter so publishing is opt-in.

- task: PublishSymbols@2
displayName: 'Publish Symbols to UiPath Azure Artifacts Symbol Server'
Expand All @@ -29,4 +26,4 @@ steps:
symbolsFolder: $(Build.SourcesDirectory)
searchPattern: '**/UiPath.CoreIpc/bin/**/UiPath.CoreIpc.pdb'
symbolServerType: teamServices
indexSources: false
indexSources: false
77 changes: 71 additions & 6 deletions src/CI/azp-js.publish-npm.steps.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
parameters:
- name: reuseArtifactsFromBuildId
type: string
default: ''

steps:
- checkout: none

- download: current
artifact: 'NPM package'
# The destination path is $(Pipeline.Workspace)
# Pull the NPM artifact: from the current run by default, or from a
# previously-completed build if `reuseArtifactsFromBuildId` is a real id.
# '0' (default) and '' both mean "no reuse — pull from current run".
- ${{ if in(parameters.reuseArtifactsFromBuildId, '0', '') }}:
- download: current
artifact: 'NPM package'
- ${{ if not(in(parameters.reuseArtifactsFromBuildId, '0', '')) }}:
- task: DownloadPipelineArtifact@2
displayName: 'Download NPM package from build ${{ parameters.reuseArtifactsFromBuildId }}'
inputs:
buildType: specific
project: $(System.TeamProject)
pipeline: $(System.DefinitionId)
buildVersionToDownload: specific
buildId: ${{ parameters.reuseArtifactsFromBuildId }}
artifactName: 'NPM package'
targetPath: '$(Pipeline.Workspace)/NPM package'

- task: NodeTool@0
- task: NodeTool@0
displayName: 'Use Node.js 20.11.0'
inputs:
versionSpec: '20.11.0'
Expand All @@ -17,15 +36,61 @@ steps:
destinationFolder: '$(System.DefaultWorkingDirectory)/unzipped'
cleanDestinationFolder: true

# ---------------------------------------------------------------------
# Primary target: project-scoped Azure Artifacts feed `uipath-ipc-deps`.
# ---------------------------------------------------------------------
# Authenticated via the pipeline's built-in identity (already an
# administrator on the feed — see CoreIpc/_artifacts/feed/uipath-ipc-deps).
# No PAT, no service connection, no rotation policy to fight with.
# ---------------------------------------------------------------------
- task: Npm@1
displayName: 'Publish to Azure Artifacts (uipath-ipc-deps) — NodeJS'
inputs:
command: 'publish'
workingDir: '$(System.DefaultWorkingDirectory)/unzipped/dist/prepack/node'
publishRegistry: 'useFeed'
publishFeed: 'CoreIpc/9a5bdfb1-0ab4-40b9-b9d2-de4cf6c011eb'

- task: Npm@1
displayName: 'Publish to Azure Artifacts (uipath-ipc-deps) — Web'
inputs:
command: 'publish'
workingDir: '$(System.DefaultWorkingDirectory)/unzipped/dist/prepack/web'
publishRegistry: 'useFeed'
publishFeed: 'CoreIpc/9a5bdfb1-0ab4-40b9-b9d2-de4cf6c011eb'

# ---------------------------------------------------------------------
# Secondary target: GitHub Packages (best-effort, currently expected to fail)
# ---------------------------------------------------------------------
# Following the May 11–12, 2026 npm supply-chain incident (Mini Shai-Hulud
# / TanStack), UiPath revoked classic GitHub PATs org-wide and is migrating
# everyone to fine-grained PATs. Fine-grained PATs don't have the Packages
# permission available at org level for UiPath — so the existing
# `PublishNPM` service connection can no longer authenticate.
#
# Per Liviu Bud's #dev announcement on 2026-05-25, a sanctioned pipeline-
# auth replacement is being worked on but not yet available:
# https://uipath.enterprise.slack.com/archives/CMDRA3VFH/p1779699547818419
#
# We leave the GitHub Packages publish wired up with continueOnError so
# (a) the run doesn't fail when the publish fails on policy, and
# (b) the publish resumes automatically the moment the service connection
# is updated with whatever the platform team ships.
#
# Each Publish_NPM run will be marked "Succeeded with issues" until then.
# Revert continueOnError when the publish path is healthy again.
# ---------------------------------------------------------------------
- task: Npm@1
displayName: 'Publish NPM (NodeJS)'
displayName: 'Publish to GitHub Packages — NodeJS (best-effort)'
continueOnError: true
inputs:
command: 'publish'
workingDir: '$(System.DefaultWorkingDirectory)/unzipped/dist/prepack/node'
publishEndpoint: PublishNPM

- task: Npm@1
displayName: 'Publish NPM (Web)'
displayName: 'Publish to GitHub Packages — Web (best-effort)'
continueOnError: true
inputs:
command: 'publish'
workingDir: '$(System.DefaultWorkingDirectory)/unzipped/dist/prepack/web'
Expand Down
54 changes: 53 additions & 1 deletion src/CI/azp-nodejs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,63 @@

- task: Npm@1
displayName: 'Npm Install'
# ---------------------------------------------------------------------
# Safe Chain Guard (SCG) bypass — see azp-start.yaml SCG_KILL_SWITCH
# ---------------------------------------------------------------------
# The UiPath DevOps team rolled out an organization-wide pipeline
# decorator that injects pre/post steps installing the Aikido Safe
# Chain shims (https://www.aikido.dev/blog/introducing-safe-chain).
# The decorator replaces /usr/bin/npm (and npx, python, etc.) with
# /home/vsts/.safe-chain/shims/* so every install goes through a
# malware-scanning proxy that also blocks packages younger than 2 days.
#
# In practice the shim has had recurring interop issues with both
# Azure Artifacts feeds and GitHub Packages downloads — it surfaces
# them as opaque 400/403 errors whose text mentions Azure Storage SAS
# signatures, which sends you on a long wild-goose chase before you
# realize the shim is what's failing, not the registry. The DevOps
# team ships SCG_KILL_SWITCH as the designed escape hatch (lives in
# the pipeline-level `variables:` block in azp-start.yaml — it MUST
# be at pipeline scope; setting it as task `env:` is too late, the
# shim is installed in pre-job before any task env is read).
#
# Short story for whoever's debugging this next:
# - CI for the CoreIpc Python-client PR (#125) started failing on
# `npm install` with `npm ERR! code E403 ... Server failed to
# authenticate the request. Make sure the value of Authorization
# header is formed correctly including the signature.` while
# pulling yocto-queue-0.1.0.tgz.
# - The error appeared to be Azure-Storage-side (the URL in the
# log was a *.blob.core.windows.net SAS URL).
# - Switching from the org-level `npm-packages` feed to a project-
# scoped `uipath-ipc-deps` feed didn't help — same blob, same
# symptom.
# - Eventually traced via #devops Slack threads to the SCG shim
# being the real culprit. SCG_KILL_SWITCH=true (pipeline scope!)
# unblocks it.
#
# References:
# - SCG rollout announcement by Russell Boley (2026-04-24, #devops):
# https://uipath.enterprise.slack.com/archives/CMCKWF5TR/p1777039233780949
# - Stefan Botan reporting an analogous SCG-induced npm failure on
# a SemanticProxy build, with SCG_KILL_SWITCH workaround
# confirmed by the DevOps team (2026-05-13, #devops):
# https://uipath.enterprise.slack.com/archives/CMCKWF5TR/p1778680523566469
#
# Trade-off: the kill switch opts this pipeline out of SCG-side
# malware scanning across npm, npx, pip, poetry, python — every
# shim SCG installs. Acceptable here — the CoreIpc deps are a
# narrow, stable set, and SCG keeps malfunctioning. Revisit when
# the DevOps fix lands.
inputs:
command: 'install'
workingDir: $(NodeJS_ProjectPath)
customRegistry: 'useFeed'
customFeed: '424ca518-1f12-456b-a4f6-888197fc15ee'
# Project-scoped feed `uipath-ipc-deps` (CoreIpc) mirroring
# npmjs.org. Project-owned so the CoreIpc team controls retention,
# permissions, and which upstreams are allowed. (See the rename
# from `EddiesExperimentalFeed` in the same conversation.)
customFeed: 'CoreIpc/9a5bdfb1-0ab4-40b9-b9d2-de4cf6c011eb'

- task: CmdLine@2
displayName: 'Npm Run Build'
Expand Down
32 changes: 32 additions & 0 deletions src/CI/azp-nuget.publish.steps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
parameters:
- name: reuseArtifactsFromBuildId
type: string
default: ''

steps:
- checkout: none

# Pull the NuGet artifact: from the current run by default, or from a
# previously-completed build if `reuseArtifactsFromBuildId` is a real id.
# '0' (default) and '' both mean "no reuse — pull from current run".
- ${{ if in(parameters.reuseArtifactsFromBuildId, '0', '') }}:
- download: current
artifact: 'NuGet package'
- ${{ if not(in(parameters.reuseArtifactsFromBuildId, '0', '')) }}:
- task: DownloadPipelineArtifact@2
displayName: 'Download NuGet package from build ${{ parameters.reuseArtifactsFromBuildId }}'
inputs:
buildType: specific
project: $(System.TeamProject)
pipeline: $(System.DefinitionId)
buildVersionToDownload: specific
buildId: ${{ parameters.reuseArtifactsFromBuildId }}
artifactName: 'NuGet package'
targetPath: '$(Pipeline.Workspace)/NuGet package'

- task: DotNetCoreCLI@2
displayName: 'dotnet push to UiPath-Internal'
inputs:
command: push
packagesToPush: '$(Pipeline.Workspace)/NuGet package/**/*.nupkg'
publishVstsFeed: 'Public.Feeds/UiPath-Internal'
27 changes: 27 additions & 0 deletions src/CI/azp-python-dist.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
steps:
# Bind the Python package version to the same source NuGet/NPM use
# ($(FullVersion), computed in azp-initialization.yaml). Maps the .NET-
# style pre-release suffix to a PEP 440 local-version segment.
- script: python $(Build.SourcesDirectory)/src/CI/stamp-python-version.py "$(FullVersion)" "$(Build.SourcesDirectory)/src/Clients/python/uipath-ipc/pyproject.toml"
displayName: 'Python: stamp $(FullVersion) into pyproject.toml'

- script: python -m build
displayName: 'Python: build wheel + sdist'
workingDirectory: '$(Build.SourcesDirectory)/src/Clients/python/uipath-ipc'

- task: CopyFiles@2
displayName: 'Python: stage wheel + sdist'
inputs:
SourceFolder: 'src/Clients/python/uipath-ipc/dist'
Contents: |
*.whl
*.tar.gz
TargetFolder: '$(Build.ArtifactStagingDirectory)/python'
CleanTargetFolder: true

- task: PublishBuildArtifacts@1
displayName: 'Python: publish the Python package artifact'
inputs:
ArtifactName: 'Python package'
PathtoPublish: '$(Build.ArtifactStagingDirectory)/python'
ArtifactType: 'Container'
45 changes: 45 additions & 0 deletions src/CI/azp-python.publish.steps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
parameters:
- name: reuseArtifactsFromBuildId
type: string
default: ''

steps:
- checkout: none

# Pull the Python artifact: from the current run by default, or from a
# previously-completed build if `reuseArtifactsFromBuildId` is a real id.
# '0' (default) and '' both mean "no reuse — pull from current run".
- ${{ if in(parameters.reuseArtifactsFromBuildId, '0', '') }}:
- download: current
artifact: 'Python package'
- ${{ if not(in(parameters.reuseArtifactsFromBuildId, '0', '')) }}:
- task: DownloadPipelineArtifact@2
displayName: 'Download Python package from build ${{ parameters.reuseArtifactsFromBuildId }}'
inputs:
buildType: specific
project: $(System.TeamProject)
pipeline: $(System.DefinitionId)
buildVersionToDownload: specific
buildId: ${{ parameters.reuseArtifactsFromBuildId }}
artifactName: 'Python package'
targetPath: '$(Pipeline.Workspace)/Python package'

- task: UsePythonVersion@0
displayName: 'Use Python 3.12'
inputs:
versionSpec: '3.12'
addToPath: true

- script: python -m pip install --upgrade twine
displayName: 'Install twine'

# TwineAuthenticate writes a .pypirc with the Azure Artifacts feed's auth
# and exports PYPIRC_PATH for the next step to consume.
- task: TwineAuthenticate@1
displayName: 'Authenticate twine with uipath-ipc-deps'
inputs:
artifactFeed: 'CoreIpc/uipath-ipc-deps'

- script: |
python -m twine upload -r uipath-ipc-deps --config-file $(PYPIRC_PATH) "$(Pipeline.Workspace)/Python package/"*
displayName: 'Upload wheel + sdist to uipath-ipc-deps'
26 changes: 26 additions & 0 deletions src/CI/azp-python.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.12'
inputs:
versionSpec: '3.12'
addToPath: true
architecture: x64

- script: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]" build
displayName: 'Python: install package + dev extras + build'
workingDirectory: '$(Build.SourcesDirectory)/src/Clients/python/uipath-ipc'

- script: python -m pytest -v --junitxml=$(Build.SourcesDirectory)/python-test-results.xml
displayName: 'Python: run tests (unit + integration)'
workingDirectory: '$(Build.SourcesDirectory)/src/Clients/python/uipath-ipc'

- task: PublishTestResults@2
displayName: 'Python: publish test results'
condition: succeededOrFailed()
inputs:
testResultsFormat: JUnit
testResultsFiles: 'python-test-results.xml'
searchFolder: '$(Build.SourcesDirectory)'
testRunTitle: 'Python tests ($(Agent.OS) $(Agent.OSArchitecture))'
Loading