From 3004375f40f8f510e23c60b179eb78a8897b2f91 Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Tue, 8 Oct 2024 22:31:43 +0330 Subject: [PATCH 1/7] Add Public Api Analyzers --- .editorconfig | 1 + Directory.Build.props | 5 ++ Directory.Packages.props | 3 ++ eng/apicompat/PublicApiAnalyzer.props | 8 +++ eng/apicompat/PublicApiAnalyzer.targets | 8 +++ eng/apicompat/mark-shipped.cmd | 2 + eng/apicompat/mark-shipped.ps1 | 49 +++++++++++++++++++ eng/apicompat/readme.md | 12 +++++ examples/Directory.Build.props | 8 +++ ...Toolkit.Hosting.Azure.StaticWebApps.csproj | 3 ++ .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 19 +++++++ .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 35 +++++++++++++ .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 7 +++ .../OllamaResourceBuilderExtensions.cs | 17 ------- .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 19 +++++++ .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 11 +++++ tests/Directory.Build.props | 4 ++ 22 files changed, 199 insertions(+), 17 deletions(-) create mode 100644 eng/apicompat/PublicApiAnalyzer.props create mode 100644 eng/apicompat/PublicApiAnalyzer.targets create mode 100644 eng/apicompat/mark-shipped.cmd create mode 100644 eng/apicompat/mark-shipped.ps1 create mode 100644 eng/apicompat/readme.md create mode 100644 examples/Directory.Build.props create mode 100644 src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Shipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Unshipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Shipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Unshipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Shipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Unshipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Shipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt create mode 100644 src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Shipped.txt create mode 100644 src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Unshipped.txt diff --git a/.editorconfig b/.editorconfig index 0dba85e7..c3952afb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -38,6 +38,7 @@ indent_size = 2 # C# files [*.cs] +dotnet_public_api_analyzer.require_api_files = true #### .NET Coding Conventions #### # Organize usings diff --git a/Directory.Build.props b/Directory.Build.props index 2b686253..b4e9df32 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,7 @@ + + + net8.0 @@ -12,5 +15,7 @@ 1.9.0 false + true + true diff --git a/Directory.Packages.props b/Directory.Packages.props index 2ec36416..6d46db56 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,5 +31,8 @@ + + + \ No newline at end of file diff --git a/eng/apicompat/PublicApiAnalyzer.props b/eng/apicompat/PublicApiAnalyzer.props new file mode 100644 index 00000000..48e25308 --- /dev/null +++ b/eng/apicompat/PublicApiAnalyzer.props @@ -0,0 +1,8 @@ + + + + + $(WarningsAsErrors);RS0016;RS0017;RS0022;RS0024;RS0025;RS0026;RS0027;RS0036;RS0037 + + + \ No newline at end of file diff --git a/eng/apicompat/PublicApiAnalyzer.targets b/eng/apicompat/PublicApiAnalyzer.targets new file mode 100644 index 00000000..c3649d16 --- /dev/null +++ b/eng/apicompat/PublicApiAnalyzer.targets @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/eng/apicompat/mark-shipped.cmd b/eng/apicompat/mark-shipped.cmd new file mode 100644 index 00000000..ed286804 --- /dev/null +++ b/eng/apicompat/mark-shipped.cmd @@ -0,0 +1,2 @@ +@echo off +powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0mark-shipped.ps1" \ No newline at end of file diff --git a/eng/apicompat/mark-shipped.ps1 b/eng/apicompat/mark-shipped.ps1 new file mode 100644 index 00000000..71d90979 --- /dev/null +++ b/eng/apicompat/mark-shipped.ps1 @@ -0,0 +1,49 @@ +[CmdletBinding(PositionalBinding=$false)] +param () + +Set-StrictMode -version 2.0 +$ErrorActionPreference = "Stop" + +function MarkShipped([string]$dir) { + $shippedFilePath = Join-Path $dir "PublicAPI.Shipped.txt" + $shipped = @() + $shipped += Get-Content $shippedFilePath + + $unshippedFilePath = Join-Path $dir "PublicAPI.Unshipped.txt" + $unshipped = Get-Content $unshippedFilePath + $removed = @() + $removedPrefix = "*REMOVED*"; + Write-Host "Processing $dir" + + foreach ($item in $unshipped) { + if ($item.Length -gt 0) { + if ($item.StartsWith($removedPrefix)) { + $item = $item.Substring($removedPrefix.Length) + $removed += $item + } + else { + $shipped += $item + } + } + } + + $shipped | Sort-Object -Unique |Where-Object { -not $removed.Contains($_) } | Out-File $shippedFilePath -Encoding Ascii + "#nullable enable`r`n" | Out-File $unshippedFilePath -Encoding Ascii +} + +try { + Push-Location $PSScriptRoot\..\.. + + foreach ($file in Get-ChildItem -re -in "PublicApi.Shipped.txt") { + $dir = Split-Path -parent $file + MarkShipped $dir + } +} +catch { + Write-Host $_ + Write-Host $_.Exception + exit 1 +} +finally { + Pop-Location +} \ No newline at end of file diff --git a/eng/apicompat/readme.md b/eng/apicompat/readme.md new file mode 100644 index 00000000..5f780139 --- /dev/null +++ b/eng/apicompat/readme.md @@ -0,0 +1,12 @@ +# Mark-Shipped Tool +======== + +This tool should be run after every supported release that has API changes. It will +merge the collection of PublicApi.Shipped.txt files with the PublicApi.Unshipped.txt +versions. This will take into account `*REMOVED*` elements when updating the files. + +Usage: + +``` cmd +mark-shipped.cmd +``` \ No newline at end of file diff --git a/examples/Directory.Build.props b/examples/Directory.Build.props new file mode 100644 index 00000000..803b4f14 --- /dev/null +++ b/examples/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + false + + + \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj index ad5aae2c..3d3632c8 100644 --- a/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj +++ b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj @@ -3,4 +3,7 @@ hosting-azure-static-web-apps.md azure staticwebapps hosting + + + diff --git a/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Shipped.txt b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Shipped.txt new file mode 100644 index 00000000..ab058de6 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..f087e543 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/PublicAPI.Unshipped.txt @@ -0,0 +1,19 @@ +Aspire.Hosting.ApplicationModel.SwaApiEndpointAnnotation +Aspire.Hosting.ApplicationModel.SwaApiEndpointAnnotation.Endpoint.get -> string! +Aspire.Hosting.ApplicationModel.SwaApiEndpointAnnotation.SwaApiEndpointAnnotation(Aspire.Hosting.ApplicationModel.IResourceBuilder! resource) -> void +Aspire.Hosting.ApplicationModel.SwaAppEndpointAnnotation +Aspire.Hosting.ApplicationModel.SwaAppEndpointAnnotation.Endpoint.get -> string! +Aspire.Hosting.ApplicationModel.SwaAppEndpointAnnotation.SwaAppEndpointAnnotation(Aspire.Hosting.ApplicationModel.IResourceBuilder! resource) -> void +Aspire.Hosting.ApplicationModel.SwaResource +Aspire.Hosting.ApplicationModel.SwaResource.SwaResource(string! name, string! workingDirectory) -> void +Aspire.Hosting.SwaAppHostingExtension +Aspire.Hosting.SwaResourceOptions +Aspire.Hosting.SwaResourceOptions.DevServerTimeout.get -> int +Aspire.Hosting.SwaResourceOptions.DevServerTimeout.set -> void +Aspire.Hosting.SwaResourceOptions.Port.get -> int +Aspire.Hosting.SwaResourceOptions.Port.set -> void +Aspire.Hosting.SwaResourceOptions.SwaResourceOptions() -> void +static Aspire.Hosting.SwaAppHostingExtension.AddSwaEmulator(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.SwaAppHostingExtension.AddSwaEmulator(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, Aspire.Hosting.SwaResourceOptions! options) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.SwaAppHostingExtension.WithApiResource(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, Aspire.Hosting.ApplicationModel.IResourceBuilder! apiResource) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.SwaAppHostingExtension.WithAppResource(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, Aspire.Hosting.ApplicationModel.IResourceBuilder! appResource) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Shipped.txt b/src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Shipped.txt new file mode 100644 index 00000000..ab058de6 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..2483caa0 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Java/PublicAPI.Unshipped.txt @@ -0,0 +1,35 @@ +Aspire.Hosting.ApplicationModel.JavaAppContainerResource +Aspire.Hosting.ApplicationModel.JavaAppContainerResource.JavaAppContainerResource(string! name, string? entrypoint = null) -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.Args.get -> string![]? +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.Args.set -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.ContainerImageName.get -> string? +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.ContainerImageName.set -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.ContainerImageTag.get -> string! +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.ContainerImageTag.set -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.ContainerRegistry.get -> string? +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.ContainerRegistry.set -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.JavaAppContainerResourceOptions() -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.OtelAgentPath.get -> string? +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.OtelAgentPath.set -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.Port.get -> int +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.Port.set -> void +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.TargetPort.get -> int +Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions.TargetPort.set -> void +Aspire.Hosting.ApplicationModel.JavaAppExecutableResource +Aspire.Hosting.ApplicationModel.JavaAppExecutableResource.JavaAppExecutableResource(string! name, string! command, string! workingDirectory) -> void +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.ApplicationName.get -> string? +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.ApplicationName.set -> void +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.Args.get -> string![]? +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.Args.set -> void +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.JavaAppExecutableResourceOptions() -> void +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.OtelAgentPath.get -> string? +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.OtelAgentPath.set -> void +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.Port.get -> int +Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions.Port.set -> void +Aspire.Hosting.JavaAppHostingExtension +static Aspire.Hosting.JavaAppHostingExtension.AddJavaApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions! options) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.JavaAppHostingExtension.AddJavaApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! workingDirectory, Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions! options) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.JavaAppHostingExtension.AddSpringApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, Aspire.Hosting.ApplicationModel.JavaAppContainerResourceOptions! options) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.JavaAppHostingExtension.AddSpringApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! workingDirectory, Aspire.Hosting.ApplicationModel.JavaAppExecutableResourceOptions! options) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Shipped.txt b/src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Shipped.txt new file mode 100644 index 00000000..ab058de6 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..45a54671 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions/PublicAPI.Unshipped.txt @@ -0,0 +1,7 @@ +Aspire.Hosting.NodeJSHostingExtensions +static Aspire.Hosting.NodeJSHostingExtensions.AddPnpmApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! workingDirectory, string! scriptName = "start", string![]? args = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.NodeJSHostingExtensions.AddViteApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string? workingDirectory = null, string! packageManager = "npm") -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.NodeJSHostingExtensions.AddYarnApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! workingDirectory, string! scriptName = "start", string![]? args = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.NodeJSHostingExtensions.WithNpmPackageInstallation(this Aspire.Hosting.ApplicationModel.IResourceBuilder! resource) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.NodeJSHostingExtensions.WithPnpmPackageInstallation(this Aspire.Hosting.ApplicationModel.IResourceBuilder! resource) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.NodeJSHostingExtensions.WithYarnPackageInstallation(this Aspire.Hosting.ApplicationModel.IResourceBuilder! resource) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs b/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs index 472ae32f..947adc63 100644 --- a/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs +++ b/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs @@ -33,23 +33,6 @@ public static IResourceBuilder AddOllama(this IDistributedApplic .ExcludeFromManifest(); } - /// - /// Adds the Ollama container to the application model. - /// - /// The . - /// The name of the resource. This name will be used as the connection string name when referenced in a dependency. - /// An optional fixed port to bind to the Ollama container. This will be provided randomly by Aspire if not set. - /// The name of the LLM to download on initial startup. llama3 by default. This can be set to null to not download any models. - /// A reference to the . - /// This is to maintain compatibility with the Raygun.Aspire.Hosting.Ollama package and will be removed in the next major release. - [Obsolete("Use AddOllama without a model name, and then the AddModel extension method to add models.")] - public static IResourceBuilder AddOllama(this IDistributedApplicationBuilder builder, - string name = "Ollama", int? port = null, string modelName = "llama3") - { - return builder.AddOllama(name, port) - .AddModel(modelName); - } - /// /// Adds a data volume to the Ollama container. /// diff --git a/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Shipped.txt b/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Shipped.txt new file mode 100644 index 00000000..ab058de6 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..bf0116f7 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt @@ -0,0 +1,19 @@ +Aspire.Hosting.ApplicationModel.OllamaResource +Aspire.Hosting.ApplicationModel.OllamaResource.AddModel(string! modelName) -> void +Aspire.Hosting.ApplicationModel.OllamaResource.ConnectionStringExpression.get -> Aspire.Hosting.ApplicationModel.ReferenceExpression! +Aspire.Hosting.ApplicationModel.OllamaResource.DefaultModel.get -> string? +Aspire.Hosting.ApplicationModel.OllamaResource.Models.get -> System.Collections.Generic.IReadOnlyList! +Aspire.Hosting.ApplicationModel.OllamaResource.OllamaResource(string! name) -> void +Aspire.Hosting.ApplicationModel.OllamaResource.PrimaryEndpoint.get -> Aspire.Hosting.ApplicationModel.EndpointReference! +Aspire.Hosting.ApplicationModel.OllamaResource.SetDefaultModel(string! modelName) -> void +Aspire.Hosting.ApplicationModel.OpenWebUIResource +Aspire.Hosting.ApplicationModel.OpenWebUIResource.ConnectionStringExpression.get -> Aspire.Hosting.ApplicationModel.ReferenceExpression! +Aspire.Hosting.ApplicationModel.OpenWebUIResource.OpenWebUIResource(string! name) -> void +Aspire.Hosting.ApplicationModel.OpenWebUIResource.PrimaryEndpoint.get -> Aspire.Hosting.ApplicationModel.EndpointReference! +Aspire.Hosting.OllamaResourceBuilderExtensions +static Aspire.Hosting.OllamaResourceBuilderExtensions.AddModel(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string! modelName) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.OllamaResourceBuilderExtensions.AddOllama(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, int? port = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.OllamaResourceBuilderExtensions.WithDataVolume(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string? name = null, bool isReadOnly = false) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.OllamaResourceBuilderExtensions.WithDefaultModel(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string! modelName) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.OllamaResourceBuilderExtensions.WithOpenWebUI(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, System.Action!>? configureContainer = null, string? containerName = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.OllamaResourceBuilderExtensions.WithReference(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, Aspire.Hosting.ApplicationModel.IResourceBuilder! ollama) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Shipped.txt b/src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Shipped.txt new file mode 100644 index 00000000..ab058de6 --- /dev/null +++ b/src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..ae1c48cd --- /dev/null +++ b/src/Aspire.CommunityToolkit.OllamaSharp/PublicAPI.Unshipped.txt @@ -0,0 +1,11 @@ +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.ConnectionString.get -> string? +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.ConnectionString.set -> void +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.Models.get -> System.Collections.Generic.IReadOnlyList! +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.Models.set -> void +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.OllamaSharpSettings() -> void +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.SelectedModel.get -> string? +Aspire.CommunityToolkit.OllamaSharp.OllamaSharpSettings.SelectedModel.set -> void +Microsoft.Extensions.Hosting.AspireOllamaSharpExtensions +static Microsoft.Extensions.Hosting.AspireOllamaSharpExtensions.AddKeyedOllamaApiClient(this Microsoft.Extensions.Hosting.IHostApplicationBuilder! builder, string! connectionName, System.Action? configureSettings = null) -> void +static Microsoft.Extensions.Hosting.AspireOllamaSharpExtensions.AddOllamaApiClient(this Microsoft.Extensions.Hosting.IHostApplicationBuilder! builder, string! connectionName, System.Action? configureSettings = null) -> void \ No newline at end of file diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index a20e51fc..8cef0811 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -1,6 +1,10 @@ + + false + + From b5929b3cde09dd2fc3c81f32e60dc01e2fec5d1b Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Wed, 9 Oct 2024 09:04:07 +0330 Subject: [PATCH 2/7] Add golang hosting to public api files --- .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Shipped.txt create mode 100644 src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Unshipped.txt diff --git a/src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Shipped.txt b/src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Shipped.txt new file mode 100644 index 00000000..7dc5c581 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..57f57500 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Hosting.Golang/PublicAPI.Unshipped.txt @@ -0,0 +1,4 @@ +Aspire.Hosting.ApplicationModel.GolangAppExecutableResource +Aspire.Hosting.ApplicationModel.GolangAppExecutableResource.GolangAppExecutableResource(string! name, string! workingDirectory) -> void +Aspire.Hosting.GolangAppHostingExtension +static Aspire.Hosting.GolangAppHostingExtension.AddGolangApp(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! workingDirectory, int port = 8080, string![]? args = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file From 1a607dfd0ae44f8561a4b2aa6b1d47bae3f9651b Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Wed, 9 Oct 2024 14:18:52 +0330 Subject: [PATCH 3/7] Disable test --- .../AppHostTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Aspire.CommunityToolkit.Hosting.Golang.Tests/AppHostTests.cs b/tests/Aspire.CommunityToolkit.Hosting.Golang.Tests/AppHostTests.cs index 424ad700..faa7c331 100644 --- a/tests/Aspire.CommunityToolkit.Hosting.Golang.Tests/AppHostTests.cs +++ b/tests/Aspire.CommunityToolkit.Hosting.Golang.Tests/AppHostTests.cs @@ -6,7 +6,7 @@ namespace Aspire.CommunityToolkit.Hosting.Golang.Tests; #pragma warning disable CTASPIRE001 public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture> { - [Theory] + [Theory(Skip = "https://github.com/CommunityToolkit/Aspire/issues/85")] [InlineData("golang")] public async Task ResourceStartsAndRespondsOk(string appName) { From 106697dad64de2b07a9c5691a3f1328fe68acf9e Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Thu, 10 Oct 2024 09:04:06 +0330 Subject: [PATCH 4/7] add doc --- docs/images/public-api-warning-example.png | Bin 0 -> 53223 bytes docs/public-api.md | 62 +++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 docs/images/public-api-warning-example.png create mode 100644 docs/public-api.md diff --git a/docs/images/public-api-warning-example.png b/docs/images/public-api-warning-example.png new file mode 100644 index 0000000000000000000000000000000000000000..853eab02004f68e8fc5b17b9d1c57460d4ddacf8 GIT binary patch literal 53223 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 L6N7U7Ct?2w!#{c_ literal 0 HcmV?d00001 diff --git a/docs/public-api.md b/docs/public-api.md new file mode 100644 index 00000000..793c568c --- /dev/null +++ b/docs/public-api.md @@ -0,0 +1,62 @@ +# Public API Management with Microsoft.CodeAnalysis.PublicApiAnalyzers + +We use `Microsoft.CodeAnalysis.PublicApiAnalyzers` in this repository. By using this analyzer, we can keep track of changes to the public API. + +## Integration Packages + +We have several packages called integration. For each of these packages, we add a public API. Each package should have the following files: +- `PublicAPI.Shipped.txt` +- `PublicAPI.Unshipped.txt` + +## Creating/Updating Public API Files + +### Steps for Contributors + + +1. **Create these two files**: + +- `PublicAPI.Shipped.txt` +- `PublicAPI.Unshipped.txt` + +If you're using nullable reference types, then add the following line at the top of each `PublicAPI.*.txt` file: +``` +#nullable enable +``` + +2. **Add New Public API**: + + - In `PublicAPI.Shipped.txt`, list all the public APIs you've given out. + - In `PublicAPI.Unshipped.txt`, list any preview or soon-to-change APIs. For example, if an API will soon be removed (marked with `[Obsolete]`), add it here so you remember to take it out later. + + - Consider the following representative C# public class: + ```csharp + namespace Demo; + + public class MyClass + { + public Task DoSomethingAsync(Uri uri, CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + } + + ``` + + Warnings issued by the Microsoft.CodeAnalysis.PublicApiAnalyzers package: + + ![](/images/public-api-warning-example.png) + + You can use `. + Ctrl` to open intellisense and see the available options. In this case, the warning is suggesting that we should add the `MyClass` type to the `PublicAPI.*.txt` files. +3. **Update Existing Public API**: + - If you modify existing public API members, update the `PublicAPI.Unshipped.txt` file accordingly. + - Ensure that the changes reflect the new API surface. + +4. **Shipping Public API**: + - Once a version is released,We move the entries from `PublicAPI.Unshipped.txt` to `PublicAPI.Shipped.txt`. + - This indicates that the API changes are now part of a shipped version. + +By following these steps, we can maintain a consistent and accurate record of our public API changes. + +Additional resources: +- [Microsoft.CodeAnalysis.PublicApiAnalyzers documentation.](https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) +- [Microsoft.CodeAnalysis.PublicApiAnalyzers list of analysis rules.](https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/Microsoft.CodeAnalysis.PublicApiAnalyzers.md) \ No newline at end of file From 4bcd952e377f957effd7b2f4a97d0c1ce2b05ed2 Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Thu, 10 Oct 2024 09:04:40 +0330 Subject: [PATCH 5/7] remove unwanted item group --- .../Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj index 3d3632c8..ad5aae2c 100644 --- a/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj +++ b/src/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj @@ -3,7 +3,4 @@ hosting-azure-static-web-apps.md azure staticwebapps hosting - - - From a1303ff947840bd25b739614a59cb1ae96804277 Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Thu, 10 Oct 2024 09:11:42 +0330 Subject: [PATCH 6/7] Revert removing obsolete API --- .../OllamaResourceBuilderExtensions.cs | 18 ++++++++++++++++++ .../PublicAPI.Unshipped.txt | 1 + 2 files changed, 19 insertions(+) diff --git a/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs b/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs index 947adc63..0ee47215 100644 --- a/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs +++ b/src/Aspire.CommunityToolkit.Hosting.Ollama/OllamaResourceBuilderExtensions.cs @@ -33,6 +33,24 @@ public static IResourceBuilder AddOllama(this IDistributedApplic .ExcludeFromManifest(); } + /// + /// Adds the Ollama container to the application model. + /// + /// The . + /// The name of the resource. This name will be used as the connection string name when referenced in a dependency. + /// An optional fixed port to bind to the Ollama container. This will be provided randomly by Aspire if not set. + /// The name of the LLM to download on initial startup. llama3 by default. This can be set to null to not download any models. + /// A reference to the . + /// This is to maintain compatibility with the Raygun.Aspire.Hosting.Ollama package and will be removed in the next major release. + [Obsolete("Use AddOllama without a model name, and then the AddModel extension method to add models.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "")] + public static IResourceBuilder AddOllama(this IDistributedApplicationBuilder builder, + string name = "Ollama", int? port = null, string modelName = "llama3") + { + return builder.AddOllama(name, port) + .AddModel(modelName); + } + /// /// Adds a data volume to the Ollama container. /// diff --git a/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt b/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt index bf0116f7..c13099f3 100644 --- a/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt +++ b/src/Aspire.CommunityToolkit.Hosting.Ollama/PublicAPI.Unshipped.txt @@ -12,6 +12,7 @@ Aspire.Hosting.ApplicationModel.OpenWebUIResource.OpenWebUIResource(string! name Aspire.Hosting.ApplicationModel.OpenWebUIResource.PrimaryEndpoint.get -> Aspire.Hosting.ApplicationModel.EndpointReference! Aspire.Hosting.OllamaResourceBuilderExtensions static Aspire.Hosting.OllamaResourceBuilderExtensions.AddModel(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string! modelName) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.OllamaResourceBuilderExtensions.AddOllama(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name = "Ollama", int? port = null, string! modelName = "llama3") -> Aspire.Hosting.ApplicationModel.IResourceBuilder! static Aspire.Hosting.OllamaResourceBuilderExtensions.AddOllama(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, int? port = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! static Aspire.Hosting.OllamaResourceBuilderExtensions.WithDataVolume(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string? name = null, bool isReadOnly = false) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! static Aspire.Hosting.OllamaResourceBuilderExtensions.WithDefaultModel(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string! modelName) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! From 83d491c92a68bb5413deba028c0f01095768e060 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Thu, 10 Oct 2024 09:12:46 +0330 Subject: [PATCH 7/7] Apply suggestions from code review Co-authored-by: Aaron Powell --- docs/public-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/public-api.md b/docs/public-api.md index 793c568c..5f92885f 100644 --- a/docs/public-api.md +++ b/docs/public-api.md @@ -44,9 +44,9 @@ If you're using nullable reference types, then add the following line at the top Warnings issued by the Microsoft.CodeAnalysis.PublicApiAnalyzers package: - ![](/images/public-api-warning-example.png) + ![Example warning from analyzer](/images/public-api-warning-example.png) - You can use `. + Ctrl` to open intellisense and see the available options. In this case, the warning is suggesting that we should add the `MyClass` type to the `PublicAPI.*.txt` files. + You can use `. + Ctrl` to open the code actions and see the available options. In this case, the warning is suggesting that we should add the `MyClass` type to the `PublicAPI.*.txt` files. 3. **Update Existing Public API**: - If you modify existing public API members, update the `PublicAPI.Unshipped.txt` file accordingly. - Ensure that the changes reflect the new API surface.