Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
113 changes: 113 additions & 0 deletions .pipelines/templates/fetch-test-data-from-blob.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Download test model data from blob storage into a local directory.
# Uses azcopy with AZCLI auth so the agent identity can read from storage.

parameters:
- name: destinationPath
type: string
default: '$(Build.SourcesDirectory)/test-data-shared'

steps:
- task: AzureCLI@2
displayName: 'Fetch test data from blob'
inputs:
azureSubscription: 'ortcibuild_readonly_mi2-ONNX Runtime-AIFoundryLocal'
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$ErrorActionPreference = 'Stop'

$destination = '${{ parameters.destinationPath }}'
$storageAccount = 'foundrylocalmodels'
$container = 'models'
$prefix = 'foundrylocal/models'

if (-not (Get-Command azcopy -ErrorAction SilentlyContinue)) {
if ($IsMacOS) {
Write-Host 'azcopy not found on macOS agent. Installing via Homebrew...'
if (-not (Get-Command brew -ErrorAction SilentlyContinue)) {
throw 'Homebrew is required to install azcopy on macOS agents, but brew was not found.'
}

brew update --quiet
brew install --quiet azcopy
} else {
throw 'azcopy is not installed on this agent.'
}
}

azcopy --version

New-Item -ItemType Directory -Path $destination -Force | Out-Null
$publisherRoot = Join-Path $destination 'Microsoft'
New-Item -ItemType Directory -Path $publisherRoot -Force | Out-Null

function Invoke-AzCopy {
param(
[string]$Source,
[string]$Target
)

$parent = Split-Path -Path $Target -Parent
if (-not [string]::IsNullOrEmpty($parent)) {
New-Item -ItemType Directory -Path $parent -Force | Out-Null
}

$args = @('copy', $Source, $Target, '--recursive')

& azcopy @args
if ($LASTEXITCODE -ne 0) {
throw "azcopy failed downloading test data from $Source"
}
}

# The active SDK tests resolve versioned model aliases in cache.
# Keep one target alias per source model to avoid duplicate copies.
$modelMappings = @(
@{
SourcePath = 'qwen2.5-0.5b-instruct'
TargetAlias = 'qwen2.5-0.5b-instruct-generic-cpu-4'
},
@{
SourcePath = 'openai-whisper-tiny'
TargetAlias = 'openai-whisper-tiny-generic-cpu-4'
},
@{
SourcePath = 'nemotron-speech-streaming-en-0.6b'
TargetAlias = 'nemotron-speech-streaming-en-0.6b-generic-cpu-3'
},
@{
SourcePath = 'qwen3-embedding-0.6b'
TargetAlias = 'qwen3-embedding-0.6b-generic-cpu-1'
},
@{
SourcePath = 'qwen3.5-0.8b'
TargetAlias = 'qwen3.5-0.8b-generic-cpu-2'
},
@{
SourcePath = 'deepseek-r1-distill-qwen-14b'
TargetAlias = 'deepseek-r1-distill-qwen-14b-generic-cpu-4'
}
)

foreach ($model in $modelMappings) {
$requestedUrl = "https://$storageAccount.blob.core.windows.net/$container/$prefix/$($model.SourcePath)/onnx/cpu_and_mobile/*"
Write-Host "Requested blob URL: $requestedUrl"

$target = Join-Path $publisherRoot $model.TargetAlias
Invoke-AzCopy -Source $requestedUrl -Target $target
}

$count = @(Get-ChildItem -Path $destination -Recurse -File).Count

if ($count -eq 0) {
throw "Downloaded test data is empty at $destination"
}

Write-Host "Downloaded $count files into $destination"
Write-Host "Cache directory contents for $destination"
(Get-ChildItem -Path $destination -Recurse -Force |
Select-Object FullName, Length |
Format-Table -AutoSize |
Out-String).TrimEnd() | Write-Host
env:
AZCOPY_AUTO_LOGIN_TYPE: AZCLI
19 changes: 3 additions & 16 deletions .pipelines/v2/templates/stages-cs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ stages:
steps:
- checkout: self
clean: true
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-cs.yml
parameters:
flNugetDir: '$(Pipeline.Workspace)/cpp-nuget'
Expand Down Expand Up @@ -98,9 +96,7 @@ stages:
steps:
- checkout: self
clean: true
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-cs.yml
parameters:
flNugetDir: '$(Pipeline.Workspace)/cpp-nuget'
Expand Down Expand Up @@ -128,16 +124,7 @@ stages:
steps:
- checkout: self
clean: true
- bash: |
set -euo pipefail
if ! command -v git-lfs >/dev/null 2>&1; then
brew install git-lfs
fi
git lfs install
displayName: 'Install git-lfs (macOS)'
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-cs.yml
parameters:
flNugetDir: '$(Pipeline.Workspace)/cpp-nuget'
Expand Down
25 changes: 6 additions & 19 deletions .pipelines/v2/templates/stages-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,12 @@ stages:
steps:
- checkout: self
clean: true
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-js.yml
parameters:
rid: 'win-x64'
prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-win-x64'
testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared'
testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared/Microsoft'

- stage: js_test_linux_x64
displayName: 'JS SDK: Test Linux x64'
Expand All @@ -224,14 +222,12 @@ stages:
steps:
- checkout: self
clean: true
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-js.yml
parameters:
rid: 'linux-x64'
prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-linux-x64'
testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared'
testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared/Microsoft'

- stage: js_test_osx_arm64
displayName: 'JS SDK: Test macOS ARM64'
Expand All @@ -252,21 +248,12 @@ stages:
steps:
- checkout: self
clean: true
- bash: |
set -euo pipefail
if ! command -v git-lfs >/dev/null 2>&1; then
brew install git-lfs
fi
git lfs install
displayName: 'Install git-lfs (macOS)'
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-js.yml
parameters:
rid: 'osx-arm64'
prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-osx-arm64'
testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared'
testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared/Microsoft'

# =====================================================================
# Pack stage — runs after all four builds. Pure packaging on Windows.
Expand Down
15 changes: 2 additions & 13 deletions .pipelines/v2/templates/stages-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,7 @@ stages:
steps:
- checkout: self
clean: true
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-python.yml
parameters:
wheelDir: '$(Pipeline.Workspace)/python-sdk-linux-x64'
Expand All @@ -216,16 +214,7 @@ stages:
steps:
- checkout: self
clean: true
- bash: |
set -euo pipefail
if ! command -v git-lfs >/dev/null 2>&1; then
brew install git-lfs
fi
git lfs install
displayName: 'Install git-lfs (macOS)'
- template: ../../templates/checkout-steps.yml@self
parameters:
repoName: test-data-shared
- template: ../../templates/fetch-test-data-from-blob.yml@self
- template: steps-test-python.yml
parameters:
wheelDir: '$(Pipeline.Workspace)/python-sdk-osx-arm64'
Expand Down
5 changes: 2 additions & 3 deletions .pipelines/v2/templates/steps-build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ steps:
displayName: 'Append version define'

- ${{ if eq(parameters.runTests, true) }}:
- template: ../../templates/checkout-steps.yml@self
- template: ../../templates/fetch-test-data-from-blob.yml@self
parameters:
repoName: test-data-shared
basePath: '$(Agent.BuildDirectory)'
destinationPath: '$(Agent.BuildDirectory)/test-data-shared'

- bash: |
set -euo pipefail
Expand Down
5 changes: 2 additions & 3 deletions .pipelines/v2/templates/steps-build-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,9 @@ steps:
displayName: 'Append version define'

- ${{ if eq(parameters.runTests, true) }}:
- template: ../../templates/checkout-steps.yml@self
- template: ../../templates/fetch-test-data-from-blob.yml@self
parameters:
repoName: test-data-shared
basePath: '$(Agent.BuildDirectory)'
destinationPath: '$(Agent.BuildDirectory)/test-data-shared'

- bash: |
set -euo pipefail
Expand Down
5 changes: 2 additions & 3 deletions .pipelines/v2/templates/steps-build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ steps:

# Tests need shared model files.
- ${{ if eq(parameters.runTests, true) }}:
- template: ../../templates/checkout-steps.yml@self
- template: ../../templates/fetch-test-data-from-blob.yml@self
parameters:
repoName: test-data-shared
basePath: '$(Agent.BuildDirectory)'
destinationPath: '$(Agent.BuildDirectory)/test-data-shared'

- ${{ if eq(parameters.arch, 'x64') }}:
- script: >-
Expand Down
4 changes: 2 additions & 2 deletions .pipelines/v2/templates/steps-test-cs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# (FoundryLocal.Tests). The caller is responsible for:
# - placing the Foundry Local Runtime nupkg in `flNugetDir`
# - downloading the `version-info` pipeline artifact
# - checking out `test-data-shared` at `testDataSharedDir`
# - populating the model cache directory at `testDataSharedDir`

parameters:
- name: flNugetDir
type: string
displayName: 'Path to directory containing the Foundry Local Runtime .nupkg'
- name: testDataSharedDir
type: string
displayName: 'Absolute path to a checked-out test-data-shared working tree'
displayName: 'Absolute path to the model cache directory used by tests'
- name: additionalTestArgs
type: string
default: ''
Expand Down
2 changes: 1 addition & 1 deletion .pipelines/v2/templates/steps-test-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ parameters:
displayName: 'Path to the downloaded js-prebuild-<rid> artifact directory (root with prebuilds/ inside)'
- name: testDataSharedDir
type: string
displayName: 'Path to the checked-out test-data-shared repo'
displayName: 'Path to the model cache directory used by tests'

steps:

Expand Down
2 changes: 1 addition & 1 deletion .pipelines/v2/templates/steps-test-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# The caller is responsible for:
# * placing the built wheel (.whl) under `wheelDir`
# * checking out test-data-shared at `testDataSharedDir`
# * populating the model cache directory at `testDataSharedDir`

parameters:
- name: wheelDir
Expand Down
18 changes: 18 additions & 0 deletions sdk_v2/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ pwsh ./build_and_test_all.ps1 -ContinueOnError

See `pwsh ./build_and_test_all.ps1 -?` for the full parameter list.

## Model cache for tests

Model-dependent sdk_v2 tests require `FOUNDRY_TEST_DATA_DIR` to point to a
local model cache directory.

In CI, sdk_v2 pipelines download model data from blob storage into this path.
For local runs, set it explicitly before invoking test commands.

Example:

```powershell
$env:FOUNDRY_TEST_DATA_DIR = 'C:\path\to\model-cache'
pwsh ./build_and_test_all.ps1
```

The directory can have any name. What matters is that it already contains the
model files expected by the tests you are running.

## Troubleshooting

* **`cl.exe ... HostX86\x86\cl.exe` during pip install** — your shell has
Expand Down
Loading
Loading