diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6bef6a..2b9b625 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: - dotnet-version: '8.0.x' + dotnet-version: '10.0.x' - run: dotnet build - run: dotnet test tests diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index b9cbee6..f39e3f3 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -26,7 +26,7 @@ jobs: python-version: '3.11' - uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: - dotnet-version: '8.0.x' + dotnet-version: '10.0.x' - name: Test JavaScript working-directory: javascript run: | diff --git a/TECHNICAL.md b/TECHNICAL.md index ca23e87..239c94b 100644 --- a/TECHNICAL.md +++ b/TECHNICAL.md @@ -74,7 +74,7 @@ and choose the newest stable tag ending in your language ID. Each language relea | Language | Release tag | Contents | | --- | --- | --- | | JavaScript | `epp-packages---javascript` | Node.js 22 application and production dependencies | -| .NET | `epp-packages---dotnet` | Framework-dependent .NET 8 Linux x64 publish output, including Azure Functions metadata and extensions | +| .NET | `epp-packages---dotnet` | Framework-dependent .NET 10 Linux x64 publish output, including Azure Functions metadata and extensions | | Python | `epp-packages---python` | Python 3.11 application with Linux x64 dependencies in `.python_packages/lib/site-packages` | Deploy the ZIP to an Azure Functions v4 app on Linux x64 with the matching language runtime. @@ -93,7 +93,7 @@ Run one packaging script from the repository root. It creates a local ZIP withou | Language | Root-level script | Prerequisites | ZIP in `artifacts/` | | --- | --- | --- | --- | | JavaScript | [package-javascript.ps1](package-javascript.ps1) | PowerShell 7+, Node.js 20 or 22 with npm, npm registry access | `javascript/released-package.zip` | -| .NET | [package-dotnet.ps1](package-dotnet.ps1) | PowerShell 7+, .NET 8 SDK, and NuGet feed access to build the ZIP | `dotnet/released-package.zip` | +| .NET | [package-dotnet.ps1](package-dotnet.ps1) | PowerShell 7+, .NET 10 SDK, and NuGet feed access to build the ZIP | `dotnet/released-package.zip` | | Python | [package-python.ps1](package-python.ps1) | Linux x64, PowerShell 7+, Python 3.11 with pip, and PyPI access to build the ZIP | `python/released-package.zip` | ```powershell diff --git a/dotnet/README.md b/dotnet/README.md index f019b43..aa5060c 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -5,7 +5,7 @@ [Documentation](../docs/README.md) | [Settings](#environment-configuration) | [Request behavior](#request-behavior) | [Source](#source) Implements the shared [contract](../docs/CONTRACT.md) with one provider per deployment. -Target: .NET 8 isolated worker, Azure Functions v4. +Target: .NET 10 isolated worker, Azure Functions v4. ## Setup and deployment @@ -14,6 +14,10 @@ Target: .NET 8 isolated worker, Azure Functions v4. **Custom package development:** follow these steps from `dotnet/`: +Install the .NET 10 SDK and current Azure Functions Core Tools v4. +On Linux, use Flex Consumption or Premium hosting; .NET 10 is not supported on the legacy +Linux Consumption plan. + 1. Create the [local settings below](#environment-configuration). Select an adapter's fixed `Name` from [Providers/](Src/Providers/), configure it, and complete [provider authentication](../docs/ONBOARDING.md#complete-provider-authentication). diff --git a/dotnet/dotnet.csproj b/dotnet/dotnet.csproj index 0ce9ce4..09e0063 100644 --- a/dotnet/dotnet.csproj +++ b/dotnet/dotnet.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 v4 Exe enable diff --git a/dotnet/tests/Epp.Otp.Tests.csproj b/dotnet/tests/Epp.Otp.Tests.csproj index 5194b48..3e88c50 100644 --- a/dotnet/tests/Epp.Otp.Tests.csproj +++ b/dotnet/tests/Epp.Otp.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable false @@ -16,7 +16,6 @@ - diff --git a/package-dotnet.ps1 b/package-dotnet.ps1 index fcbb568..0f3ff08 100644 --- a/package-dotnet.ps1 +++ b/package-dotnet.ps1 @@ -23,7 +23,7 @@ try { [IO.Compression.ZipFile]::CreateFromDirectory($stage, $zip) New-Item -ItemType Directory -Path (Split-Path $archive) -Force | Out-Null [IO.File]::Move($zip, $archive) - Write-Host 'Framework-dependent .NET 8 Linux x64 ZIP created.' + Write-Host 'Framework-dependent .NET 10 Linux x64 ZIP created.' Get-Item -LiteralPath $archive | Select-Object FullName, Length } finally { if (Test-Path -LiteralPath $temporary) { Remove-Item -LiteralPath $temporary -Recurse -Force } diff --git a/setup/docs/README.md b/setup/docs/README.md index 14bc88e..0403292 100644 --- a/setup/docs/README.md +++ b/setup/docs/README.md @@ -227,7 +227,7 @@ Interactive setup can install missing Bicep. | Choice | Azure runtime | Package contents | | --- | --- | --- | | JavaScript | Node.js 22, Functions v4 | Application and production dependencies | -| C# | .NET 8 isolated, Functions v4 | Framework-dependent Linux x64 publish output, Function metadata, and extensions | +| C# | .NET 10 isolated, Functions v4 | Framework-dependent Linux x64 publish output, Function metadata, and extensions | | Python | Python 3.11, Functions v4 | Application and Linux x64 dependencies in `.python_packages/lib/site-packages` | Setup verifies and publishes the selected ZIP, recording its SHA-256 in the deployment summary. diff --git a/setup/docs/Troubleshooting.md b/setup/docs/Troubleshooting.md index 50e137c..8071276 100644 --- a/setup/docs/Troubleshooting.md +++ b/setup/docs/Troubleshooting.md @@ -259,9 +259,9 @@ a full SHA avoids branch-resolution API rate limits. Private raw downloads are u ## .NET package fails to load -**Expected:** guided setup downloads `released-package.zip` from the `-dotnet` release, containing framework-dependent .NET 8 +**Expected:** guided setup downloads `released-package.zip` from the `-dotnet` release, containing framework-dependent .NET 10 Linux x64 publish output, Function metadata, and `.azurefunctions` extension assemblies. -Confirm the Function uses .NET 8 isolated and align the selected +Confirm the Function uses .NET 10 isolated on Flex Consumption or Premium, not legacy Linux Consumption, and align the selected [source/package versions](README.md#source-versioning). For custom packaging errors, see [build prerequisites and commands](../../TECHNICAL.md#build-zips-locally). diff --git a/setup/infra/resources.bicep b/setup/infra/resources.bicep index 3407d8d..8cc4991 100644 --- a/setup/infra/resources.bicep +++ b/setup/infra/resources.bicep @@ -22,8 +22,8 @@ var runtimes = { } dotnet: { worker: 'dotnet-isolated' - stack: 'DOTNET-ISOLATED|8.0' - version: '8.0' + stack: 'DOTNET-ISOLATED|10.0' + version: '10.0' } python: { worker: 'python' diff --git a/setup/tests/ServicePlans.Tests.ps1 b/setup/tests/ServicePlans.Tests.ps1 index d439b42..8a23fb6 100644 --- a/setup/tests/ServicePlans.Tests.ps1 +++ b/setup/tests/ServicePlans.Tests.ps1 @@ -294,6 +294,9 @@ try { $inner = ($template.resources | Where-Object type -eq 'Microsoft.Resources/deployments').properties.template Assert (($inner.parameters.servicePlan.allowedValues -join ',') -ceq 'FC1,EP1') 'Bicep must restrict service plans to the two offered SKUs.' Assert ($inner.variables.isFlexConsumption -ceq "[equals(parameters('servicePlan'), 'FC1')]") 'The Flex condition must use the selected SKU.' + $dotnetRuntime = $inner.variables.runtimes.dotnet + Assert ($dotnetRuntime.worker -ceq 'dotnet-isolated' -and $dotnetRuntime.stack -ceq 'DOTNET-ISOLATED|10.0' -and + $dotnetRuntime.version -ceq '10.0') 'Both hosting plans must target .NET 10 isolated.' $plan = $inner.resources | Where-Object type -eq 'Microsoft.Web/serverfarms' Assert ($plan.sku -ceq "[if(variables('isFlexConsumption'), createObject('name', 'FC1', 'tier', 'FlexConsumption'), createObject('name', 'EP1', 'tier', 'ElasticPremium', 'capacity', 1))]") 'Bicep must deploy the selected SKU, tier, and Premium capacity.' $settings = ($inner.resources | Where-Object { $_.type -eq 'Microsoft.Web/sites/config' -and $_.name -like '*appsettings*' }).properties @@ -305,9 +308,11 @@ try { Assert ($site.serverFarmId -ceq "[resourceId('Microsoft.Web/serverfarms', parameters('resourceNames').hostingPlan)]") 'The hosting-plan ID must be explicit without a runtime reference.' Assert ($site.httpsOnly -eq $true -and $site.publicNetworkAccess -ceq 'Disabled') 'The Function must retain HTTPS-only access and initially disabled public ingress.' Assert ($site.keyVaultReferenceIdentity -ceq 'SystemAssigned') 'Certificate references must use the Function system identity, not the outbound identity.' + Assert ($site.siteConfig.Contains("'linuxFxVersion', variables('runtime').stack")) 'Premium must use the selected runtime stack.' $functionAppConfig = $site.functionAppConfig Assert ($functionAppConfig -is [string] -and $functionAppConfig.StartsWith("[if(variables('isFlexConsumption'), ") -and $functionAppConfig.EndsWith(', null())]')) 'Only functionAppConfig must be conditional on FC1, with no Flex configuration for EP1.' Assert ($functionAppConfig.Contains("'deployment', createObject('storage', createObject('type', 'blobContainer'") -and $functionAppConfig.Contains("reference(resourceId('Microsoft.Storage/storageAccounts', parameters('resourceNames').storageAccount), '2023-05-01').primaryEndpoints.blob")) 'Flex must retain its deployment container and storage endpoint lookup.' + Assert ($functionAppConfig.Contains("'runtime', createObject('name', variables('runtime').worker, 'version', variables('runtime').version)")) 'Flex must use the selected runtime name and version.' Assert ($functionAppConfig.Contains("'instanceMemoryMB', 2048, 'maximumInstanceCount', 40, 'alwaysReady', createArray()") -and $functionAppConfig.Contains("'type', 'SystemAssignedIdentity'")) 'Flex must retain 2048 MB, up to 40 on-demand instances, zero always-ready instances, and managed-identity deployment storage.' } } $directory $TemplatePath