diff --git a/Directory.Build.props b/Directory.Build.props index eb1cf9e957..8bdc553d9f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,11 +9,14 @@ 2.0.5 2.1.0 preview5 + 1.0.0 + 1.0.0 + preview.0 1.0.0-preview09 1.1.0-preview3 10.0 $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) - $(DefineConstants);PREVIEW;ENCRYPTIONPREVIEW + $(DefineConstants);PREVIEW;ENCRYPTIONPREVIEW;COSMOSAIPREVIEW diff --git a/Microsoft.Azure.Cosmos.AI/Directory.Build.props b/Microsoft.Azure.Cosmos.AI/Directory.Build.props new file mode 100644 index 0000000000..571dacd01a --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/Directory.Build.props @@ -0,0 +1,4 @@ + + + + diff --git a/Microsoft.Azure.Cosmos.AI/README.md b/Microsoft.Azure.Cosmos.AI/README.md new file mode 100644 index 0000000000..1dddbc68b5 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/README.md @@ -0,0 +1,36 @@ +# Azure Cosmos DB .NET SDK AI Extension Library + +`Microsoft.Azure.Cosmos.AI` is an optional, provider-style extension package for the [Azure Cosmos DB .NET SDK](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/) that adds AI-powered capabilities to applications built on Azure Cosmos DB for NoSQL. + +> **Status:** This package is in early development. It currently ships as a scaffold only — no public APIs are exposed yet. The first capability (an `AzureOpenAIEmbeddingGenerator` provider for automatic vector embedding generation in hybrid and vector search queries) is tracked in [#5842](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/5842). Breaking changes may occur prior to GA. + +## Why a Separate Package + +- **Zero cost for non-AI workloads.** Applications that don't use AI features pull in no AI dependencies. `Azure.AI.OpenAI` and related dependencies are only present for customers who explicitly opt in to this package. +- **Independent versioning.** This package ships on its own cadence, allowing rapid iteration on AI capabilities without coupling to the core SDK release cycle. +- **Established extensibility model.** Follows the same pattern proven by `Microsoft.Azure.Cosmos.Encryption` — a separate, optional, provider-style package that extends the core SDK without polluting it. +- **Clear separation of concerns.** The core SDK owns the data plane. This package owns AI service integration. + +## Planned Capabilities + +- **Automatic vector embedding generation** — provide raw text to vector / hybrid search queries; the SDK calls a configured embedding service (e.g., Azure OpenAI) on your behalf. +- **Semantic re-ranking** — re-rank query results using AI services. +- **AI-assisted query construction** — generate Cosmos DB queries from natural language. +- Additional AI-powered features as the landscape evolves. + +## Getting Started + +Once the first capability lands in a published preview, install from NuGet: + +```bash +dotnet add package Microsoft.Azure.Cosmos.AI --prerelease +``` + +Usage examples will be added here as APIs ship. + +## Related Links + +- [Azure Cosmos DB documentation](https://learn.microsoft.com/azure/cosmos-db/) +- [Azure Cosmos DB .NET SDK on NuGet](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/) +- [Changelog](./changelog.md) +- [Repository](https://github.com/Azure/azure-cosmos-dotnet-v3) diff --git a/Microsoft.Azure.Cosmos.AI/changelog.md b/Microsoft.Azure.Cosmos.AI/changelog.md new file mode 100644 index 0000000000..c42bbd9d15 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/changelog.md @@ -0,0 +1,9 @@ +Preview features are treated as a separate branch and will not be included in the official release until the feature is ready. Each preview release lists all the additional features that are enabled. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +### Unreleased + +#### Added +- Initial scaffold of the `Microsoft.Azure.Cosmos.AI` extension package. No public APIs are shipped in this release; the package serves as the home for AI-powered Cosmos DB capabilities (automatic embedding generation, semantic ranking, and future AI integrations) that ship in subsequent releases. diff --git a/Microsoft.Azure.Cosmos.AI/src/AssemblyInfo.cs b/Microsoft.Azure.Cosmos.AI/src/AssemblyInfo.cs new file mode 100644 index 0000000000..62d35de124 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/src/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.AI.Tests" + Microsoft.Azure.Cosmos.AI.AssemblyKeys.TestPublicKey)] diff --git a/Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj b/Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj new file mode 100644 index 0000000000..ee048fab64 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj @@ -0,0 +1,83 @@ + + + netstandard2.0 + Microsoft.Azure.Cosmos.AI + Microsoft.Azure.Cosmos.AI + $(LangVersion) + $(CosmosAIOfficialVersion) + $(CosmosAIPreviewVersion) + $(CosmosAIPreviewSuffixVersion) + $(CosmosAIVersion) + $(CosmosAIVersion)-$(CosmosAIVersionSuffix) + $([System.DateTime]::Now.ToString(yyyyMMdd)) + Microsoft Corporation + Microsoft + AI extensions library for Azure Cosmos DB for NoSQL. Provides an Azure OpenAI / Foundry-backed embedding provider for automatic vector embedding generation in hybrid and vector search queries. Designed to be extensible for broader AI scenarios including semantic re-ranking, OCR, and model integrations. For more information, refer to https://aka.ms/CosmosDB + © Microsoft Corporation. All rights reserved. + Microsoft Azure Cosmos DB AI extension library + Microsoft.Azure.Cosmos.AI + true + MIT + https://github.com/Azure/azure-cosmos-dotnet-v3 + The change log for this SDK is made available at https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.AI/changelog.md at the time of release. + README.md + false + true + true + microsoft;azure;cosmos;cosmosdb;documentdb;nosql;azureofficial;dotnetcore;netcore;netstandard;ai;embedding;vector;openai;semanticranking + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Product + true + true + ..\..\35MSSharedLib1024.snk + + + + true + + + + $(DefineConstants);SDKPROJECTREF + + diff --git a/Microsoft.Azure.Cosmos.AI/src/Mirrored/AssemblyKeys.cs b/Microsoft.Azure.Cosmos.AI/src/Mirrored/AssemblyKeys.cs new file mode 100644 index 0000000000..85866355c9 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/src/Mirrored/AssemblyKeys.cs @@ -0,0 +1,12 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.AI +{ + internal static class AssemblyKeys + { + /// TestPublicKey is an unsupported strong key for testing and internal use only. + internal const string TestPublicKey = ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100197c25d0a04f73cb271e8181dba1c0c713df8deebb25864541a66670500f34896d280484b45fe1ff6c29f2ee7aa175d8bcbd0c83cc23901a894a86996030f6292ce6eda6e6f3e6c74b3c5a3ded4903c951e6747e6102969503360f7781bf8bf015058eb89b7621798ccc85aaca036ff1bc1556bb7f62de15908484886aa8bbae"; + } +} diff --git a/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Contracts/ContractEnforcementTests.cs b/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Contracts/ContractEnforcementTests.cs new file mode 100644 index 0000000000..8e617b8a51 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Contracts/ContractEnforcementTests.cs @@ -0,0 +1,32 @@ +namespace Microsoft.Azure.Cosmos.AI.Tests +{ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestCategory("Windows")] + [TestCategory("UpdateContract")] + [TestClass] + public class ContractEnforcementTests + { + /// + /// Locks the public API surface of Microsoft.Azure.Cosmos.AI against a + /// versioned baseline so accidental renames, visibility changes, or removals + /// surface at PR review time instead of shipping to a preview NuGet. + /// + /// IMPORTANT: Because tests can run on multiple .NET versions, the contract + /// validation uses framework-specific baselines to ensure consistency: + /// + /// - When running on net8.0: validates against DotNetSDKCosmosAIAPI.net8.json + /// + /// To update baselines, run: UpdateContracts.ps1 from the repository root. + /// + [TestMethod] + public void ContractChanges() + { + Cosmos.Tests.Contracts.ContractEnforcement.ValidateContract( + dllName: "Microsoft.Azure.Cosmos.AI", + contractType: Cosmos.Tests.Contracts.ContractType.Standard, + baselinePattern: "DotNetSDKCosmosAIAPI", + breakingChangesPattern: "DotNetSDKCosmosAIAPIChanges"); + } + } +} diff --git a/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Contracts/DotNetSDKCosmosAIAPI.net8.json b/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Contracts/DotNetSDKCosmosAIAPI.net8.json new file mode 100644 index 0000000000..adcef32362 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Contracts/DotNetSDKCosmosAIAPI.net8.json @@ -0,0 +1,44 @@ +{ + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Boolean System.Object.Equals(System.Object, System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Boolean System.Object.Equals(System.Object, System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Boolean System.Object.ReferenceEquals(System.Object, System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Boolean System.Object.ReferenceEquals(System.Object, System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String ToString()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String ToString();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Type GetType()[System.Runtime.CompilerServices.NullableContextAttribute((Byte)1)]-[System.Runtime.CompilerServices.IntrinsicAttribute()]": { + "Type": "Method", + "Attributes": [ + "IntrinsicAttribute", + "NullableContextAttribute" + ], + "MethodInfo": "System.Type GetType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "Void .ctor()" + } + }, + "NestedTypes": {} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Microsoft.Azure.Cosmos.AI.Tests.csproj b/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Microsoft.Azure.Cosmos.AI.Tests.csproj new file mode 100644 index 0000000000..e8a3029310 --- /dev/null +++ b/Microsoft.Azure.Cosmos.AI/tests/Microsoft.Azure.Cosmos.AI.Tests/Microsoft.Azure.Cosmos.AI.Tests.csproj @@ -0,0 +1,49 @@ + + + + true + true + AnyCPU + net8.0 + false + false + Microsoft.Azure.Cosmos.AI.Tests + $(LangVersion) + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + true + true + ..\..\..\testkey.snk + + + + x64 + true + + + diff --git a/Microsoft.Azure.Cosmos.sln b/Microsoft.Azure.Cosmos.sln index cec2d9a5f4..52752097e6 100644 --- a/Microsoft.Azure.Cosmos.sln +++ b/Microsoft.Azure.Cosmos.sln @@ -39,6 +39,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FaultInjectionTests", "Micr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests", "Microsoft.Azure.Cosmos.Encryption.Custom\tests\Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests\Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests.csproj", "{CE4D6DA8-148D-4A98-943B-D8C2D532E1DC}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AI", "AI", "{701B153E-380B-4452-9120-3975C59DC296}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Cosmos.AI", "Microsoft.Azure.Cosmos.AI\src\Microsoft.Azure.Cosmos.AI.csproj", "{60C02F10-7DE4-4BF0-BA28-732ABAF0A343}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Cosmos.AI.Tests", "Microsoft.Azure.Cosmos.AI\tests\Microsoft.Azure.Cosmos.AI.Tests\Microsoft.Azure.Cosmos.AI.Tests.csproj", "{80F63801-FFB4-4D8E-9466-A44C1F0C4946}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Cover|Any CPU = Cover|Any CPU @@ -193,6 +199,30 @@ Global {CE4D6DA8-148D-4A98-943B-D8C2D532E1DC}.Release|Any CPU.Build.0 = Release|Any CPU {CE4D6DA8-148D-4A98-943B-D8C2D532E1DC}.Release|x64.ActiveCfg = Release|Any CPU {CE4D6DA8-148D-4A98-943B-D8C2D532E1DC}.Release|x64.Build.0 = Release|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Cover|Any CPU.ActiveCfg = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Cover|Any CPU.Build.0 = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Cover|x64.ActiveCfg = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Cover|x64.Build.0 = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Debug|x64.ActiveCfg = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Debug|x64.Build.0 = Debug|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Release|Any CPU.Build.0 = Release|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Release|x64.ActiveCfg = Release|Any CPU + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343}.Release|x64.Build.0 = Release|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Cover|Any CPU.ActiveCfg = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Cover|Any CPU.Build.0 = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Cover|x64.ActiveCfg = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Cover|x64.Build.0 = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Debug|x64.ActiveCfg = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Debug|x64.Build.0 = Debug|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Release|Any CPU.Build.0 = Release|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Release|x64.ActiveCfg = Release|Any CPU + {80F63801-FFB4-4D8E-9466-A44C1F0C4946}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -205,6 +235,8 @@ Global {F87719DB-BB52-4B12-9D9C-F6AE30BAB3D7} = {51F858D8-707E-4F21-BCC6-4D6123832E4F} {B5B3631D-AC2F-4257-855D-D6FE12F20B60} = {51F858D8-707E-4F21-BCC6-4D6123832E4F} {CE4D6DA8-148D-4A98-943B-D8C2D532E1DC} = {51F858D8-707E-4F21-BCC6-4D6123832E4F} + {60C02F10-7DE4-4BF0-BA28-732ABAF0A343} = {701B153E-380B-4452-9120-3975C59DC296} + {80F63801-FFB4-4D8E-9466-A44C1F0C4946} = {701B153E-380B-4452-9120-3975C59DC296} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C6A1D820-CB03-4DE6-87D1-46EF476F0040} diff --git a/azure-pipelines-cosmosai-official.yml b/azure-pipelines-cosmosai-official.yml new file mode 100644 index 0000000000..4f1c67cda3 --- /dev/null +++ b/azure-pipelines-cosmosai-official.yml @@ -0,0 +1,27 @@ +trigger: none + +pr: none + +variables: + ReleaseArguments: ' --filter "TestCategory!=Quarantine" --verbosity normal ' + VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops + BuildConfiguration: Release + Packaging.EnableSBOMSigning: true + +stages: +- stage: + displayName: CosmosAI Release Gates + jobs: + - template: templates/static-tools-cosmosai.yml + parameters: + BuildConfiguration: '${{ variables.BuildConfiguration }}' + +- stage: + displayName: Build, Pack and Publish + jobs: + - template: templates/cosmosai-nuget-pack.yml + parameters: + BuildConfiguration: Release + ReleasePackage: true + OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos.AI' + BlobVersion: $(BlobVersion) diff --git a/azure-pipelines-cosmosai.yml b/azure-pipelines-cosmosai.yml new file mode 100644 index 0000000000..24b382e188 --- /dev/null +++ b/azure-pipelines-cosmosai.yml @@ -0,0 +1,33 @@ +# CI pipeline for Microsoft.Azure.Cosmos.AI — runs on every PR touching the AI package. +# Validates the three-build parity strategy (NuGet ref, SdkProjectRef, parity check) +# before changes reach main, complementing the manual release-gate in +# azure-pipelines-cosmosai-official.yml. +trigger: none + +pr: + branches: + include: + - main + - releases/* + paths: + include: + - 'Microsoft.Azure.Cosmos.AI/**' + - 'templates/cosmosai-nuget-pack.yml' + - 'templates/static-tools-cosmosai.yml' + - 'azure-pipelines-cosmosai.yml' + - 'azure-pipelines-cosmosai-official.yml' + - 'Directory.Build.props' + +variables: + BuildConfiguration: Release + +jobs: +- template: templates/static-tools-cosmosai.yml + parameters: + BuildConfiguration: '${{ variables.BuildConfiguration }}' + +- template: templates/cosmosai-nuget-pack.yml + parameters: + BuildConfiguration: '${{ variables.BuildConfiguration }}' + ReleasePackage: false + OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos.AI' diff --git a/templates/cosmosai-nuget-pack.yml b/templates/cosmosai-nuget-pack.yml new file mode 100644 index 0000000000..d364bdc8a9 --- /dev/null +++ b/templates/cosmosai-nuget-pack.yml @@ -0,0 +1,76 @@ +# File: templates/cosmosai-nuget-pack.yml + +parameters: + - name: BuildConfiguration + type: string + default: '' + - name: Arguments + type: string + default: '' + - name: OutputPath + type: string + default: '' + - name: BlobVersion + type: string + default: '' + - name: ReleasePackage + type: boolean + default: false + - name: CleanupFolder + type: boolean + default: false + +jobs: +- job: GenerateNugetPackages + displayName: Generate Nuget packages + pool: + name: 'OneES' + + steps: + - task: DotNetCoreCLI@2 + displayName: Build Microsoft.Azure.Cosmos.AI + inputs: + command: build + configuration: $(BuildConfiguration) + nugetConfigPath: NuGet.config + projects: Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj + arguments: --configuration ${{ parameters.BuildConfiguration }} -p:Optimize=true ${{ parameters.Arguments }} + versioningScheme: OFF + + - task: DotNetCoreCLI@2 + displayName: 'Create AI NuGet Package' + inputs: + command: custom + projects: 'Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj' + custom: pack + arguments: '-v detailed -c ${{ parameters.BuildConfiguration }} --no-build ${{ parameters.Arguments }} --no-restore -o "${{ parameters.OutputPath }}"' + + - ${{ if eq(parameters.ReleasePackage, true) }}: + - task: DotNetCoreCLI@2 + displayName: 'Create AI NuGet Symbols Package' + inputs: + command: custom + projects: 'Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj' + custom: pack + arguments: '-v detailed -c ${{ parameters.BuildConfiguration }} --no-build --include-symbols /p:SymbolPackageFormat=snupkg ${{ parameters.Arguments }} --no-restore -o "${{ parameters.OutputPath }}"' + - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + inputs: + BuildDropPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos.AI' + + - ${{ if ne(parameters.BlobVersion, '') }}: + - task: AzureFileCopy@6 + displayName: 'Copy Artifacts to Azure SDK Release blob storage' + condition: succeeded() + inputs: + SourcePath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos.AI/**' + azureSubscription: azuresdkpartnerdrops + Destination: AzureBlob + storage: azuresdkpartnerdrops + ContainerName: 'drops' + BlobPrefix: 'cosmosdb/csharp/cosmosai/$(BlobVersion)' + CleanTargetBeforeCopy: ${{ parameters.CleanupFolder }} + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifacts: Microsoft.Azure.Cosmos.AI' + inputs: + artifactName: Microsoft.Azure.Cosmos.AI diff --git a/templates/static-tools-cosmosai.yml b/templates/static-tools-cosmosai.yml new file mode 100644 index 0000000000..9a56a3dde3 --- /dev/null +++ b/templates/static-tools-cosmosai.yml @@ -0,0 +1,137 @@ +# File: templates\static-tools-cosmosai.yml + +parameters: + BuildConfiguration: '' + +jobs: +- job: + displayName: Static Analysis + pool: + name: 'OneES' + + steps: + - checkout: self # self represents the repo where the initial Pipelines YAML file was found + clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching + + # Build using the Microsoft.Azure.Cosmos NuGet reference declared in the .csproj. + # This matches what customers consume and guards against regressions on the + # released SDK surface (the default release pipeline build path). + - task: DotNetCoreCLI@2 + displayName: Build Microsoft.Azure.Cosmos.AI (NuGet SDK reference) + inputs: + command: build + nugetConfigPath: NuGet.config + projects: Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj + arguments: '-p:Optimize=true --configuration Release' + versioningScheme: OFF + + # Build using a ProjectReference to the Microsoft.Azure.Cosmos source in this + # repo (SdkProjectRef=True / SDKPROJECTREF). This catches mismatches between + # the AI package and the latest SDK surface in main that would otherwise only + # surface at customer runtime as TypeLoadException once a newer SDK NuGet is released. + - task: DotNetCoreCLI@2 + displayName: Build Microsoft.Azure.Cosmos.AI (SDKREF - main SDK source) + inputs: + command: build + nugetConfigPath: NuGet.config + projects: Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj + arguments: '-p:Optimize=true -p:IsPreview=true -p:SdkProjectRef=true --configuration Release' + versioningScheme: OFF + + # Parity check: build against main SDK source WITHOUT defining SDKPROJECTREF. + # This matches the exact preprocessor surface the shipped NuGet package is + # built with (PREVIEW on, SDKPROJECTREF off) while still linking against the + # latest SDK abstractions. + - task: DotNetCoreCLI@2 + displayName: Build Microsoft.Azure.Cosmos.AI (NuGet-surface parity vs main SDK source) + inputs: + command: build + nugetConfigPath: NuGet.config + projects: Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj + arguments: '-p:Optimize=true -p:IsPreview=true -p:SdkProjectRef=true -p:DefineSdkProjectRefSymbol=false --configuration Release' + versioningScheme: OFF + + # GA-surface parity check: same as above but with IsPreview unset, so + # neither PREVIEW nor COSMOSAIPREVIEW is defined. This matches the + # exact preprocessor surface the shipped GA NuGet is built with. The + # preview-only parity step above does NOT cover this surface because + # IsPreview=true defines COSMOSAIPREVIEW (Directory.Build.props), which + # pulls in #if COSMOSAIPREVIEW-gated members that do not ship in the + # GA NuGet. See PR #5825 (FFCF GA promotion) for a miss the preview-only + # parity build let through; static-tools-encryption.yml added the + # equivalent step for the same reason. + - task: DotNetCoreCLI@2 + displayName: Build Microsoft.Azure.Cosmos.AI (GA NuGet-surface parity vs main SDK source) + inputs: + command: build + nugetConfigPath: NuGet.config + projects: Microsoft.Azure.Cosmos.AI/src/Microsoft.Azure.Cosmos.AI.csproj + arguments: '-p:Optimize=true -p:SdkProjectRef=true -p:DefineSdkProjectRefSymbol=false --configuration Release' + versioningScheme: OFF + + # TODO(#5845): The Guardian tasks below (BinSkim, CredScan, PoliCheck, + # PostAnalysis) inherit a years-old "condition: eq(1,2) #disabling as nuget + # repo failing" gate from static-tools-encryption.yml. Re-enable on this + # brand-new package once the OneES NuGet feed access for these tasks is + # confirmed green; CredScan in particular has real value here because AI + # scenarios commonly handle endpoint URIs and token credentials. Tracking + # work consolidated under PR #5845 follow-up; remove the eq(1,2) gates and + # this comment once validated. + - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@4 + displayName: 'BinSkim' + condition: eq(1,2) # TODO(#5845): re-enable once OneES nuget feed access verified + inputs: + AnalyzeTargetGlob: $(Build.SourcesDirectory)\Microsoft.Azure.Cosmos.AI\src\bin\Release\netstandard2.0\Microsoft.Azure.Cosmos.AI.dll + AnalyzeRecurse: true + AnalyzeVerbose: true + AnalyzeHashes: false + AnalyzeStatistics: false + AnalyzeEnvironment: false + + # Analyze source and build output text files for credentials + - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3 + displayName: 'CredScan' + condition: eq(1,2) # TODO(#5845): re-enable; CredScan matters for AI endpoint URIs / tokens + inputs: + toolMajorVersion: V2 + scanFolder: $(Build.SourcesDirectory) + suppressionsFile: CredScanSuppressions.json + debugMode: false + verboseOutput: false + + # Scan text elements including code, code comments, and content/web pages, for sensitive terms based on legal, cultural, or geopolitical reasons + - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2 + displayName: 'PoliCheck' + condition: eq(1,2) # TODO(#5845): re-enable once OneES nuget feed access verified + inputs: + targetType: F + optionsFC: 0 + + # AntiMalware scan + - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@4 + displayName: 'AntiMalware' + continueOnError: true # signature refresh failing resulting in tasks failures + inputs: + EnableServices: true + + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: 'Component Governance Detection' #https://docs.opensource.microsoft.com/tools/cg.html + inputs: + alertWarningLevel: Medium + failOnAlert: true + + # Publish Analysis Results (position after all tools ran) + - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@3 + displayName: 'Publish Security Analysis Logs' + + # The Post-Analysis build task will analyze the log files produced by the tools, and introduce a build break + - task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@2 + displayName: 'Post Analysis' + condition: eq(1,2) # TODO(#5845): re-enable alongside BinSkim / CredScan / PoliCheck + inputs: + GdnBreakFast: true + GdnBreakAllTools: false + GdnBreakGdnToolCredScan: true + GdnBreakGdnToolBinSkim: true + GdnBreakGdnToolPoliCheck: true + GdnBreakGdnToolPoliCheckSeverity: Error