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
61 changes: 61 additions & 0 deletions .github/workflows/sdk_v2/Foundry Local Core SDK Build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#################################################################################
# OneBranch Pipelines #
# This pipeline was created by EasyStart from a sample located at: #
# https://aka.ms/obpipelines/easystart/samples #
# Documentation: https://aka.ms/obpipelines #
# Yaml Schema: https://aka.ms/obpipelines/yaml/schema #
# Retail Tasks: https://aka.ms/obpipelines/tasks #
# Support: https://aka.ms/onebranchsup #
#################################################################################

trigger: none # https://aka.ms/obpipelines/triggers

parameters: # parameters are shown up in ADO UI in a build queue time
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: 'isRelease'
displayName: 'Release build'
type: boolean
default: false

variables:
CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning
BUILD_ID: $[counter(variables['Build.SourceBranchName'], 0)] # branch-specific counter that resets for each new branch
DEBIAN_FRONTEND: noninteractive
LinuxContainerImage: 'mcr.microsoft.com/onebranch/azurelinux/build:3.0' # https://eng.ms/docs/products/onebranch/infrastructureandimages/containerimages/linuximages/marinerazurelinux/azurelinux
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' # https://aka.ms/obpipelines/containers
VERSION: '0.9.0.$(BUILD_ID)'
PRERELEASE_IDENTIFIER: 'dev'

resources:
repositories:
- repository: templates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main

extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@templates # https://aka.ms/obpipelines/templates
parameters:
git:
fetchDepth: 1
featureFlags:
EnableCDPxPAT: false
WindowsHostVersion: '1ESWindows2022'
globalSdl:
tsa:
enabled: false
stages:
- template: templates/stages-build-cs.yml
parameters:
version: $(VERSION)
isRelease: ${{ parameters.isRelease }}
prereleaseIdentifier: $(PRERELEASE_IDENTIFIER)

- template: templates/stages-build-js.yml
parameters:
version: $(VERSION)
isRelease: ${{ parameters.isRelease }}
prereleaseIdentifier: $(PRERELEASE_IDENTIFIER)
63 changes: 63 additions & 0 deletions .github/workflows/sdk_v2/Foundry Local Core SDK WinML Build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#################################################################################
# OneBranch Pipelines #
# This pipeline was created by EasyStart from a sample located at: #
# https://aka.ms/obpipelines/easystart/samples #
# Documentation: https://aka.ms/obpipelines #
# Yaml Schema: https://aka.ms/obpipelines/yaml/schema #
# Retail Tasks: https://aka.ms/obpipelines/tasks #
# Support: https://aka.ms/onebranchsup #
#################################################################################

trigger: none # https://aka.ms/obpipelines/triggers

parameters: # parameters are shown up in ADO UI in a build queue time
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: 'isRelease'
displayName: 'Release build'
type: boolean
default: false

variables:
CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning
BUILD_ID: $[counter(variables['Build.SourceBranchName'], 0)] # branch-specific counter that resets for each new branch
DEBIAN_FRONTEND: noninteractive
LinuxContainerImage: 'mcr.microsoft.com/onebranch/azurelinux/build:3.0' # https://eng.ms/docs/products/onebranch/infrastructureandimages/containerimages/linuximages/marinerazurelinux/azurelinux
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' # https://aka.ms/obpipelines/containers
VERSION: '0.9.0.$(BUILD_ID)'
PRERELEASE_IDENTIFIER: 'dev'

resources:
repositories:
- repository: templates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main

extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@templates # https://aka.ms/obpipelines/templates
parameters:
git:
fetchDepth: 1
featureFlags:
EnableCDPxPAT: false
WindowsHostVersion: '1ESWindows2022'
globalSdl:
tsa:
enabled: false
stages:
- template: templates/stages-build-cs.yml
parameters:
version: $(VERSION)
isRelease: ${{ parameters.isRelease }}
prereleaseIdentifier: $(PRERELEASE_IDENTIFIER)
isWinML: true

- template: templates/stages-build-js.yml
parameters:
version: $(VERSION)
isRelease: ${{ parameters.isRelease }}
prereleaseIdentifier: $(PRERELEASE_IDENTIFIER)
isWinML: true
41 changes: 41 additions & 0 deletions .github/workflows/sdk_v2/templates/sdk-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
parameters:
- name: version
type: string
- name: isRelease
type: boolean
default: false
- name: prereleaseIdentifier
type: string
default: ''

steps:
- task: PowerShell@2
displayName: 'Generate Custom Version'
inputs:
targetType: 'inline'
script: |
$baseVersion = "${{ parameters.version }}"
$isRelease = [System.Convert]::ToBoolean("${{ parameters.isRelease }}")
$prereleaseId = "${{ parameters.prereleaseIdentifier }}".Trim()

if ($isRelease -and [string]::IsNullOrEmpty($prereleaseId)) {
# Official release: 0.0.1
$customVersion = $baseVersion
Write-Host "Official release version: $customVersion"
} elseif ($isRelease -and -not [string]::IsNullOrEmpty($prereleaseId)) {
# Prerelease: 0.0.1-beta.timestamp.commit
$timestamp = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmss")
$shortCommitId = "$(Build.SourceVersion)".Substring(0, 8)
$customVersion = "$baseVersion-$prereleaseId.$timestamp.$shortCommitId"
Write-Host "Prerelease version ($prereleaseId): $customVersion"
} else {
# Dev build: 0.0.1-timestamp.commit
$timestamp = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmss")
$shortCommitId = "$(Build.SourceVersion)".Substring(0, 8)
$customVersion = "$baseVersion-$timestamp.$shortCommitId"
Write-Host "Development version: $customVersion"
}

Write-Host "Generated custom version: $customVersion"
Write-Host "##vso[task.setvariable variable=ProjectVersion]$customVersion"
# vso[task.setvariable...] sets ProjectVersion as a pipeline variable to be used in subsequent tasks
172 changes: 172 additions & 0 deletions .github/workflows/sdk_v2/templates/stages-build-cs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
parameters:
- name: version
type: string
- name: isRelease
type: boolean
default: false
- name: prereleaseIdentifier
type: string
default: ''
- name: isWinML
type: boolean
default: false

stages:
- stage: cs
jobs:
- job: cs
pool:
type: windows
vmImage: 'windows-latest'
variables:
ob_outputDirectory: '$(Build.SourcesDirectory)/out'
buildConfiguration: 'Release'
steps:
- checkout: self
clean: true

- task: UseDotNet@2
displayName: 'Use .NET 9 SDK'
inputs:
packageType: 'sdk'
version: '9.0.x'
installationPath: '$(Agent.ToolsDirectory)\dotnet'

- template: sdk-version.yml
parameters:
version: ${{ parameters.version }}
isRelease: ${{ parameters.isRelease }}
prereleaseIdentifier: ${{ parameters.prereleaseIdentifier }}

- task: DotNetCoreCLI@2
displayName: 'Restore dependencies'
inputs:
command: 'restore'
projects: $(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj
feedsToUse: 'config'
nugetConfigPath: '$(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\NuGet.config'
restoreArguments: '/p:UseWinML=${{ parameters.isWinML }}'
# No TargetFramework override: we want to restore for all frameworks in the project (net8.0 is the minimum supported)

- task: DotNetCoreCLI@2
displayName: 'Build solution'
inputs:
command: 'build'
projects: $(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj
arguments: '--no-restore --configuration $(buildConfiguration) /p:UseWinML=${{ parameters.isWinML }}'
# No TargetFramework override: we want to build for all frameworks in the project (net8.0 is the minimum supported)

- checkout: git://windows.ai.toolkit/test-data-shared
displayName: 'Checkout test-data-shared for Chat/Audio Client Tests'
lfs: true
persistCredentials: true

- task: PowerShell@2
displayName: 'Checkout specific commit in test-data-shared'
inputs:
targetType: 'inline'
workingDirectory: '$(Build.SourcesDirectory)/test-data-shared'
script: |
Write-Host "Current directory: $(Get-Location)"
git checkout 231f820fe285145b7ea4a449b112c1228ce66a41
if ($LASTEXITCODE -ne 0) {
Write-Error "Git checkout failed."
exit 1
}
Write-Host "`nDirectory contents:"
Get-ChildItem -Recurse -Depth 2 | ForEach-Object { Write-Host " $($_.FullName)" }

- task: DotNetCoreCLI@2
displayName: 'Run Foundry Local Core tests'
inputs:
command: 'test'
projects: $(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\test\FoundryLocal.Tests\Microsoft.AI.Foundry.Local.Tests.csproj
arguments: '--verbosity normal /p:UseWinML=${{ parameters.isWinML }}'
workingDirectory: '$(Build.SourcesDirectory)'

# Sign DLLs after building but before packing
- task: PowerShell@2
displayName: 'Find target framework directory'
inputs:
targetType: 'inline'
script: |
$basePath = "$(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\src\bin\$(buildConfiguration)"
Write-Host "Searching in base path: $basePath"
Write-Host "Directory contents:"
Get-ChildItem -Path $basePath | ForEach-Object { Write-Host " $($_.Name)" }

$targetDir = Get-ChildItem -Path $basePath -Directory -Filter "net8.0*" | Select-Object -First 1
Write-Host "Target framework name: $($targetDir.Name)"
Write-Host "##vso[task.setvariable variable=TargetFramework]$($targetDir.Name)"

# NOTE: Manual pack using PowerShell with --no-build instead of DotNetCoreCLI@2 task
#
# When UseWinML=true, the project's TargetFramework changes from 'net8.0' to 'net8.0-windows10.0.26100.0'
# causing build outputs to be placed in a different directory (e.g., bin/Release/net8.0-windows10.0.26100.0/).
#
# The DotNetCoreCLI@2 pack task with various parameter combinations failed to locate the signed DLLs
# in the WinML target framework directory. Using 'dotnet pack --no-build' directly with /p:UseWinML
# allows the pack operation to correctly resolve the output path based on the project's UseWinML
# condition evaluation, ensuring it finds the signed binaries in the correct location.
#
# This approach works for both standard (net8.0) and WinML (net8.0-windows10.0.26100.0) builds
# by letting the project naturally evaluate UseWinML and determine the correct target framework path.
- task: PowerShell@2
displayName: 'Pack NuGet package'
inputs:
targetType: 'inline'
script: |
$projectPath = "$(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj"
$outputDir = "$(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\bin"
$version = "$(ProjectVersion)"
$config = "$(buildConfiguration)"
$useWinML = "${{ parameters.isWinML }}"

Write-Host "Packing project: $projectPath"
Write-Host "Output directory: $outputDir"
Write-Host "Version: $version"
Write-Host "Configuration: $config"
Write-Host "UseWinML: $useWinML"

& dotnet pack $projectPath --no-build --configuration $config --output $outputDir /p:PackageVersion=$version /p:UseWinML=$useWinML /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg --verbosity normal

if ($LASTEXITCODE -ne 0) {
Write-Error "dotnet pack failed with exit code $LASTEXITCODE"
exit $LASTEXITCODE
}

Write-Host "Pack completed successfully"
Write-Host "Generated packages:"
Get-ChildItem -Path $outputDir -Filter "*.nupkg" | ForEach-Object { Write-Host " $($_.Name)" }
Get-ChildItem -Path $outputDir -Filter "*.snupkg" | ForEach-Object { Write-Host " $($_.Name)" }

- task: CopyFiles@2
displayName: 'Copy signed NuGet package files'
inputs:
SourceFolder: '$(Build.SourcesDirectory)\foundry-local-sdk\sdk_v2\cs\bin'
Contents: |
*.nupkg
*.snupkg
TargetFolder: '$(ob_outputDirectory)'

# Optional
- task: PowerShell@2
displayName: 'Verify NuGet package signatures'
inputs:
targetType: 'inline'
script: |
$packages = Get-ChildItem -Path "$(ob_outputDirectory)" -Filter "*.nupkg"
foreach ($package in $packages) {
Write-Host "Verifying signature for: $($package.FullName)"
try {
nuget verify -signature "$($package.FullName)"
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ Signature verified successfully for: $($package.Name)" -ForegroundColor Green
} else {
Write-Warning "⚠ Signature verification returned non-zero exit code for: $($package.Name)"
}
}
catch {
Write-Warning "⚠ Could not verify signature for: $($package.Name) - Error: $_"
}
}
Loading