Add custom test targets to the build process, support for .NET 8. (#2410)

The goal is to reduce the overall number of builds, stop using end of life platforms in the build pipeline and to support
build of future/deprecated build targets in a custom build step, which is also triggered weekly in the ci builds.

In addition:
- added a doc which describes the release and versioning strategy of this project
- produce the Nuget packges with .NET 8 assemblies.
- produce a Docker build based on a .NET 8 based container.
- add custom test targets to test outdated platforms. Need a manual step to enable for VS or command line.
- bug fixes: the latest move to an alternate crypto library for Bouncy Castle, which is only used for the GDS support and  .NET Framework 4.6.2./netstandard2.0, revealed already a few issues which were previously not found. 
- only .NET8/.NET6/.NET Framework 4.8 are tested in Pull requests. Remaining builds in weekly scheduled builds.
This commit is contained in:
Martin Regen
2023-12-07 12:03:37 +01:00
committed by GitHub
parent 5fbfc578cf
commit 343f7b0fbc
28 changed files with 467 additions and 234 deletions
+2 -2
View File
@@ -34,10 +34,10 @@ jobs:
value: '.azurepipelines/signlist${{parameters.config}}.txt'
steps:
- task: UseDotNet@2
displayName: 'Install .NET 6.0'
displayName: 'Install .NET 8.0'
inputs:
packageType: 'sdk'
version: '6.0.x'
version: '8.0.x'
includePreviewVersions: false
- task: DownloadSecureFile@1
name: strongnamefile
+10
View File
@@ -2,38 +2,48 @@ Stack\Opc.Ua.Core\bin\Debug\netstandard2.0\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Debug\netstandard2.1\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Debug\net48\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Debug\net6.0\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Debug\net8.0\Opc.Ua.Core.dll
Stack\Opc.Ua.Bindings.Https\bin\Debug\netstandard2.0\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Debug\netcoreapp3.1\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Debug\net48\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Debug\net6.0\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Debug\net8.0\Opc.Ua.Bindings.Https.dll
Libraries\Opc.Ua.Server\bin\Debug\netstandard2.0\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Debug\netstandard2.1\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Debug\net48\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Debug\net6.0\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Debug\net8.0\Opc.Ua.Server.dll
Libraries\Opc.Ua.Client\bin\Debug\netstandard2.0\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Debug\netstandard2.1\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Debug\net48\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Debug\net6.0\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Debug\net8.0\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\netstandard2.1\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net48\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net6.0\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net8.0\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Configuration\bin\Debug\netstandard2.0\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Debug\netstandard2.1\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Debug\net48\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Debug\net6.0\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Debug\net8.0\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\netstandard2.0\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\netstandard2.1\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net48\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net6.0\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net8.0\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\netstandard2.0\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\netstandard2.1\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net48\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net6.0\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net8.0\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Security.Certificates\bin\Debug\netstandard2.0\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Debug\netstandard2.1\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Debug\net48\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Debug\net6.0\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Debug\net8.0\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.PubSub\bin\Debug\netstandard2.0\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Debug\netstandard2.1\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Debug\net48\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Debug\net6.0\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Debug\net8.0\Opc.Ua.PubSub.dll
+10
View File
@@ -2,38 +2,48 @@ Stack\Opc.Ua.Core\bin\Release\netstandard2.0\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Release\netstandard2.1\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Release\net48\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Release\net6.0\Opc.Ua.Core.dll
Stack\Opc.Ua.Core\bin\Release\net8.0\Opc.Ua.Core.dll
Stack\Opc.Ua.Bindings.Https\bin\Release\netstandard2.0\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Release\netcoreapp3.1\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Release\net48\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Release\net6.0\Opc.Ua.Bindings.Https.dll
Stack\Opc.Ua.Bindings.Https\bin\Release\net8.0\Opc.Ua.Bindings.Https.dll
Libraries\Opc.Ua.Server\bin\Release\netstandard2.0\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Release\netstandard2.1\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Release\net48\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Release\net6.0\Opc.Ua.Server.dll
Libraries\Opc.Ua.Server\bin\Release\net8.0\Opc.Ua.Server.dll
Libraries\Opc.Ua.Client\bin\Release\netstandard2.0\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Release\netstandard2.1\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Release\net48\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Release\net6.0\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client\bin\Release\net8.0\Opc.Ua.Client.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\netstandard2.1\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net48\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net6.0\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net8.0\Opc.Ua.Client.ComplexTypes.dll
Libraries\Opc.Ua.Configuration\bin\Release\netstandard2.0\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Release\netstandard2.1\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Release\net48\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Release\net6.0\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Configuration\bin\Release\net8.0\Opc.Ua.Configuration.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Release\netstandard2.0\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Release\netstandard2.1\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net48\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net6.0\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net8.0\Opc.Ua.Gds.Client.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Release\netstandard2.0\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Release\netstandard2.1\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net48\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net6.0\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net8.0\Opc.Ua.Gds.Server.Common.dll
Libraries\Opc.Ua.Security.Certificates\bin\Release\netstandard2.0\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Release\netstandard2.1\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Release\net48\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Release\net6.0\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.Security.Certificates\bin\Release\net8.0\Opc.Ua.Security.Certificates.dll
Libraries\Opc.Ua.PubSub\bin\Release\netstandard2.0\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Release\netstandard2.1\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Release\net48\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Release\net6.0\Opc.Ua.PubSub.dll
Libraries\Opc.Ua.PubSub\bin\Release\net8.0\Opc.Ua.PubSub.dll
+14 -9
View File
@@ -6,6 +6,7 @@ parameters:
framework: net6.0
agents: '@{}'
jobnamesuffix: ''
customtestarget: ''
jobs:
- job: testprep${{ parameters.jobnamesuffix }}
displayName: Prepare Test Jobs ${{ parameters.configuration }} (${{ parameters.framework }})
@@ -30,21 +31,25 @@ jobs:
variables:
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
CustomTestTarget: ${{ parameters.customtestarget }}
${{ if eq( parameters.customtestarget, '' ) }}:
DotCliCommandline: '--framework ${{ parameters.framework }}'
${{ else }}:
DotCliCommandline: '/p:CustomTestTarget=${{ parameters.customtestarget }}'
pool:
vmImage: $(poolImage)
steps:
- task: UseDotNet@2
displayName: 'Install .NET Core 3.1'
condition: eq('${{parameters.framework}}', 'netcoreapp3.1')
inputs:
packageType: 'sdk'
version: '3.1.x'
- task: UseDotNet@2
displayName: 'Install .NET 6.0'
condition: or(eq('${{parameters.framework}}', 'netcoreapp3.1'), and(eq('${{parameters.framework}}', 'net6.0'), ne(variables['poolImage'], 'windows-2022')))
condition: eq('${{parameters.framework}}', 'net6.0')
inputs:
packageType: 'sdk'
version: '6.0.x'
- task: UseDotNet@2
displayName: 'Install .NET 8.0'
inputs:
packageType: 'sdk'
version: '8.0.x'
- task: NuGetToolInstaller@1
inputs:
versionSpec: '>=5.8.x'
@@ -58,11 +63,11 @@ jobs:
inputs:
command: restore
projects: '**/*.Tests.csproj'
arguments: '--framework ${{ parameters.framework }} --configuration ${{ parameters.configuration }}'
arguments: '${{ variables.DotCliCommandline }} --configuration ${{ parameters.configuration }}'
- task: DotNetCoreCLI@2
displayName: Test ${{ parameters.configuration }}
timeoutInMinutes: 45
inputs:
command: test
projects: '**/*.Tests.csproj'
arguments: '--no-restore --framework ${{ parameters.framework }} --configuration ${{ parameters.configuration }}'
arguments: '--no-restore ${{ variables.DotCliCommandline }} --configuration ${{ parameters.configuration }}'
+14 -4
View File
@@ -7,6 +7,7 @@ parameters:
agent: 'linux'
poolImage: 'ubuntu-22.04'
jobnamesuffix: 'net60cc'
customtestarget: ''
jobs:
- job: testcc${{ parameters.jobnamesuffix }}
displayName: Coverage ${{ parameters.agent }} ${{ parameters.configuration }}
@@ -14,16 +15,25 @@ jobs:
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
disable.coverage.autogenerate: true
CustomTestTarget: ${{ parameters.customtestarget }}
${{ if eq( parameters.customtestarget, '' ) }}:
DotCliCommandline: '--framework ${{ parameters.framework }}'
${{ else }}:
DotCliCommandline: '/p:CustomTestTarget=${{ parameters.customtestarget }}'
pool:
vmImage: ${{ parameters.poolImage }}
steps:
- task: UseDotNet@2
displayName: 'Install .NET 6.0'
condition: and(eq('${{parameters.framework}}', 'net6.0'), ne(variables['poolImage'], 'windows-2022'))
condition: eq('${{parameters.framework}}', 'net6.0')
inputs:
packageType: 'sdk'
version: '6.0.x'
includePreviewVersions: true
- task: UseDotNet@2
displayName: 'Install .NET 8.0'
inputs:
packageType: 'sdk'
version: '8.0.x'
- task: NuGetToolInstaller@1
inputs:
versionSpec: '>=5.8.x'
@@ -37,7 +47,7 @@ jobs:
inputs:
command: restore
projects: 'UA Core Library.sln'
arguments: '--framework ${{ parameters.framework }} --configuration ${{ parameters.configuration }}'
arguments: '${{ variables.DotCliCommandline }} --configuration ${{ parameters.configuration }}'
- task: DotNetCoreCLI@2
displayName: Test ${{ parameters.framework }}
timeoutInMinutes: 45
@@ -45,7 +55,7 @@ jobs:
command: test
projects: 'UA Core Library.sln'
# note: /p:CollectCoverage=true is only used to disable deterministc builds
arguments: '--no-restore --framework ${{ parameters.framework }} --configuration ${{ parameters.configuration }} /p:CollectCoverage=true --collect:"XPlat Code Coverage" --settings ./Tests/coverlet.runsettings.xml --results-directory $(Agent.TempDirectory)'
arguments: '--no-restore ${{ variables.DotCliCommandline }} --configuration ${{ parameters.configuration }} /p:CollectCoverage=true --collect:"XPlat Code Coverage" --settings ./Tests/coverlet.runsettings.xml --results-directory $(Agent.TempDirectory)'
publishTestResults: false
- script: |
bash <(curl -s https://codecov.io/bash) -s $(Agent.TempDirectory)
+6 -5
View File
@@ -1,4 +1,4 @@
name: Build and Test .NET 6.0
name: Build and Test .NET 8.0
on:
push:
@@ -25,9 +25,10 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest]
csproj: [Security.Certificates, Core, Server, Client, Client.ComplexTypes, PubSub, Configuration, Gds]
include:
- framework: 'net6.0'
dotnet-version: '6.0.x'
- framework: 'net8.0'
dotnet-version: '8.0.x'
configuration: 'Release'
customtesttarget: net8.0
env:
OS: ${{ matrix.os }}
@@ -52,11 +53,11 @@ jobs:
run: ./.azurepipelines/set-version.ps1
- name: Build
run: dotnet build ${{ env.CSPROJECT }} --force --framework ${{ matrix.framework }} --configuration ${{ matrix.configuration }}
run: dotnet build ${{ env.CSPROJECT }} --force --framework ${{ matrix.framework }} --configuration ${{ matrix.configuration }} /p:CustomTestTarget=${{ matrix.customtesttarget }}
- name: Test
# note: /p:CollectCoverage=true is only used to disable deterministc builds
run: dotnet test ${{ env.CSPROJECT }} --no-build --framework ${{ matrix.framework }} --logger trx --configuration ${{ matrix.configuration }} /p:CollectCoverage=true --collect:"XPlat Code Coverage" --settings ./Tests/coverlet.runsettings.xml --results-directory ${{ env.TESTRESULTS }}
run: dotnet test ${{ env.CSPROJECT }} --no-build --framework ${{ matrix.framework }} --logger trx --configuration ${{ matrix.configuration }} /p:CollectCoverage=true /p:CustomTestTarget=${{ matrix.customtesttarget }} --collect:"XPlat Code Coverage" --settings ./Tests/coverlet.runsettings.xml --results-directory ${{ env.TESTRESULTS }}
- name: Upload test results
uses: actions/upload-artifact@v3
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
- name: Set up .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.x'
dotnet-version: '8.x'
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild.exe
+3 -3
View File
@@ -38,10 +38,10 @@ jobs:
with:
fetch-depth: 0
- name: Set up .NET 6
- name: Set up .NET 8
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.x'
dotnet-version: '8.x'
- name: Set Version
shell: pwsh
@@ -113,7 +113,7 @@ jobs:
InformationalVersion=${{ env.NBGV_AssemblyInformationalVersion }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ env.TAG_BRANCH }},${{ env.TAG_LATEST }}${{ env.TAG_RELEASE }}
platforms: linux/amd64,linux/arm64
platforms: linux/amd64,linux/arm64/v8
file: ./Applications/ConsoleReferenceServer/Dockerfile
labels: ${{ steps.meta.outputs.labels }}
provenance: false
@@ -1,7 +1,7 @@
FROM mcr.microsoft.com/dotnet/runtime:6.0-bullseye-slim AS base
FROM mcr.microsoft.com/dotnet/runtime:8.0-jammy AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim AS build
FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS build
WORKDIR /src
# copy csproj and restore as distinct layers
@@ -12,16 +12,18 @@ COPY ["Libraries/Opc.Ua.Security.Certificates/Opc.Ua.Security.Certificates.cspro
COPY ["Libraries/Opc.Ua.Configuration/Opc.Ua.Configuration.csproj", "Libraries/Opc.Ua.Configuration/"]
COPY ["Libraries/Opc.Ua.Server/Opc.Ua.Server.csproj", "Libraries/Opc.Ua.Server/"]
COPY ["Applications/Quickstarts.Servers/Quickstarts.Servers.csproj", "Applications/Quickstarts.Servers/"]
RUN dotnet restore "Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj" --force -p:NoHttps=true
ENV DOTNET_EnableWriteXorExecute=0
RUN dotnet restore "Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj" --force -p:NoHttps=true -p:CustomTestTarget=net8.0
COPY . .
WORKDIR "/src/Applications/ConsoleReferenceServer"
ARG Version
ARG SimpleVersion
ARG InformationalVersion
ENV OPTIONS="-c Release -f net6.0 -p:NoHttps=true -p:Dockerbuild=true -p:Version=${Version} -p:AssemblyVersion=${SimpleVersion} -p:FileVersion=${Version} -p:InformationalVersion=${InformationalVersion}"
ENV OPTIONS="-c Release -f net8.0 -p:NoHttps=true -p:Dockerbuild=true -p:Version=${Version} -p:AssemblyVersion=${SimpleVersion} -p:FileVersion=${Version} -p:InformationalVersion=${InformationalVersion} -p:CustomTestTarget=net8.0"
FROM build AS publish
ENV DOTNET_EnableWriteXorExecute=0
RUN dotnet publish "ConsoleReferenceServer.csproj" --no-restore ${OPTIONS} -o /app/publish
FROM base AS final
+107
View File
@@ -0,0 +1,107 @@
## .NET Platform support and Nuget package releases
The following Nuget packages are released in a monthly cadence, unless security issues require hotfixes.
[OPCFoundation.NetStandard.Opc.Ua](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua/)
[OPCFoundation.NetStandard.Opc.Ua.Core](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Core/)
[OPCFoundation.NetStandard.Opc.Ua.Security.Certificates](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/)
[OPCFoundation.NetStandard.Opc.Ua.Configuration](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Configuration/)
[OPCFoundation.NetStandard.Opc.Ua.Server](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Server/)
[OPCFoundation.NetStandard.Opc.Ua.Client](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client/)
[OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes/)
[OPCFoundation.NetStandard.Opc.Ua.Bindings.Https](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Bindings.Https/)
[OPCFoundation.NetStandard.Opc.Ua.PubSub](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.PubSub/) (Beta)
The OPCFoundation prefix is reserved and the assemblies and the Nuget packages are signed by the OPC Foundation.
For the licenses please see the information in the packages.
In addition to the released packages on Nuget.org, for every successful build in main there are preview packages available on a [preview feed](https://opcfoundation.visualstudio.com/opcua-netstandard/_artifacts/feed/opcua-preview) in Azure DevOps.
The versioning scheme is not compatible to the [Semantic Versioning](https://semver.org/) standard, due to some baggage that the releases are based on in the OPC UA specification.
The first two digits of the Nuget package version represent the spec version of the embedded Nodeset from the UA specification:
- 1.3.x.x --> spec V1.03 released in 2015
- 1.4.x.x --> spec V1.04 released in 2017
- 1.5.x.x --> spec V1.05 released in 2022
The OPC UA spec is committed to backward compatibility, so the 1.04 releases work also with 1.03 certified servers and clients.
Once the UA working group releases the spec V1.05.03, the Nuget packages will be updated to be based on a 1.05 Nodeset (ETA Q1 2024), which can still be used to certify a V1.04 UA application.
The next digits in the Nuget package version represent the API level and the build number.
An API level is mapped to a dedicated branch for a release, e.g. [release/1.4.372](https://github.com/OPCFoundation/UA-.NETStandard/tree/release/1.4.372).
Thus for hotfixes, a released API level can easily receive cherry picks or security updates from the main branch.
An API level remains in itself consistent, that it should not receive breaking changes that would require code changes in applications.
However, internal improvements or even small features which extend existing APIs that may not require application changes may be included in build updates.
In fact the versioning doesn't map to the MAJOR.MINOR.PATCH semantic versioning. The build number corresponds to a mix of MINOR and PATCH, the API level corresponds to MAJOR (breaking changes). The spec version prefix however is guaranteed to be downwards compatible, and it should be possible to certify a UA Server that is built with a 1.5 library with a 1.4 certification test.
Currently the released Nuget packages support a wide variety of .NET platforms:
The following .NET versions are currently supported by the class libraries
- .NET Standard 2.0
- .NET Standard 2.1
- .NET Framework 4.8 *
- .NET 6.0 *
- .NET 8.0 **
The following platform is deprecated but can still be built and tested:
- .NET Framework 4.6.2
To reduce the ci build overhead and the number of tests to be run in Visual Studio, only the tagged versions (* and **) are part of a qualifying ci build to pass a pull request.
All other platforms are only tested in weekly scheduled or manual ci builds.
By default, in Visual Studio only the platforms tagged with (*) are tested. In order to test the other platforms in a command line window or in VS, there is a custom build variable defined to target a specific build. E.g. to target a .NETStandard2.0 build, the test runners are compiled with .NET 6.0 but the class libraries target only netstandard2.0, to force the use of that target.
Another option is to test run such a custom target in a command window with a batch file [CustomTest.bat](../Tests/customtest.bat) which is provided to clean up, restore the project and to run the tests. To run the custom tests in Visual Studio a section in [target.props](../targets.props) needs to be uncommented and the target platform value must be set.
```xml
<!--
Uncomment the following lines to test a custom test target
supported values: net462, netstandard2.0, netstandard2.1, net48, net6.0, net8.0
-->
<PropertyGroup>
<CustomTestTarget>netstandard2.0</CustomTestTarget>
</PropertyGroup>
```
Due to the limitations of the build system it is recommended to run the CustomTest batch file as well to force a clean build of the project for the test target.
## Further information on the supported Nuget packages
The OPCFoundation prefix is reserved and the assemblies and the Nuget packages are signed by the OPC Foundation.
For improved source level debugging in Visual Studio, symbol packages are available on Nuget.org in the 'snupkg' format. A reference to the Nuget symbol server may have to be added in Visual Studio to enable the source level debug support.
In addition packages compiled as Debug are available on Nuget.org with a '.Debug' extension to the package name.
[OPCFoundation.NetStandard.Opc.Ua](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua/)
This is a wrapper package to include all the available packages from this repository, except PubSub. It is recommended to rather include the individual packages as below to reduce the number of dependencies.
[OPCFoundation.NetStandard.Opc.Ua.Core](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Core/)
[OPCFoundation.NetStandard.Opc.Ua.Security.Certificates](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/)
Core and Certificates are required for Client and Server projects.
[OPCFoundation.NetStandard.Opc.Ua.Configuration](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Configuration/)
The configuration contains a helper class to configure a UA application from file or with a fluent API.
[OPCFoundation.NetStandard.Opc.Ua.Server](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Server/)
The server library is used to build a UA server.
[OPCFoundation.NetStandard.Opc.Ua.Client](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client/)
[OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes/)
The client is used to build a client. The complex type library extends the client with support for complex types.
[OPCFoundation.NetStandard.Opc.Ua.Bindings.Https](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Bindings.Https/)
The Https binding is an optional component to support UA over Https for 'opc.https' endpoints.
[OPCFoundation.NetStandard.Opc.Ua.PubSub](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.PubSub/) (Beta)
The PubSub library can be used to implement the publisher subscriber model.
For the licenses please see the information in the packages.
+1
View File
@@ -5,6 +5,7 @@
Here is a list of available documentation for different topics:
UA Core stack related:
* About [.NET platform](PlatformBuild.md) support, Nuget packages and versioning.
* How X.509 [Certificates](Certificates.md) are used in the certificate stores.
* Using the [Reverse Connect](ReverseConnect.md) for the UA-TCP transport.
* Support for the [TransferSubscriptions](TransferSubscription.md) service set.
@@ -15,29 +15,26 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net472'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net48'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net5.0'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<Choose>
<When Condition="'$(TargetFramework)' == 'net462'">
<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
</ItemGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netstandard2.0'">
<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
</ItemGroup>
</When>
<Otherwise>
<PropertyGroup>
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
</ItemGroup>
</Otherwise>
</Choose>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<PackageId>$(PackageId).Debug</PackageId>
@@ -50,9 +47,6 @@
<ItemGroup>
<PackageReference Include="System.Formats.Asn1" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
@@ -61,11 +55,6 @@
<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
</ItemGroup>
<Target Name="GetPackagingOutputs" />
@@ -145,7 +145,7 @@ namespace Opc.Ua.Security.Certificates
string passcode)
{
Org.BouncyCastle.X509.X509Certificate x509 = new X509CertificateParser().ReadCertificate(certificate.RawData);
using (var cfrg = new CertificateFactoryRandomGenerator())
using (var cfrg = new CryptoApiRandomGenerator())
{
return X509Utils.CreatePfxWithPrivateKey(
x509, friendlyName,
@@ -165,7 +165,7 @@ namespace Opc.Ua.Security.Certificates
)
{
if (certificate == null) throw new ArgumentNullException(nameof(certificate));
using (var cfrg = new CertificateFactoryRandomGenerator())
using (var cfrg = new CryptoApiRandomGenerator())
{
SecureRandom random = new SecureRandom(cfrg);
@@ -444,7 +444,7 @@ namespace Opc.Ua.Security.Certificates
throw new NotSupportedException("Need an issuer certificate with a private key or a signature generator.");
}
using (var cfrg = new CertificateFactoryRandomGenerator())
using (var cfrg = new CryptoApiRandomGenerator())
{
// cert generators
SecureRandom random = new SecureRandom(cfrg);
@@ -1,92 +0,0 @@
/* ========================================================================
* Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER
using System;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Prng;
namespace Opc.Ua.Security.Certificates.BouncyCastle
{
/// <summary>
/// Secure .Net Core Random Number generator wrapper for Bounce Castle.
/// Creates an instance of RNGCryptoServiceProvider or an OpenSSL based version on other OS.
/// </summary>
public class CertificateFactoryRandomGenerator : IRandomGenerator, IDisposable
{
RandomNumberGenerator m_prg;
/// <summary>
/// Creates an instance of a crypthographic secure random number generator.
/// </summary>
public CertificateFactoryRandomGenerator()
{
m_prg = RandomNumberGenerator.Create();
}
/// <summary>
/// Dispose the random number generator.
/// </summary>
public void Dispose()
{
m_prg.Dispose();
}
/// <summary>Add more seed material to the generator. Not needed here.</summary>
public void AddSeedMaterial(byte[] seed) { }
/// <summary>Add more seed material to the generator. Not needed here.</summary>
public void AddSeedMaterial(long seed) { }
/// <summary>
/// Fills an array of bytes with a cryptographically strong
/// random sequence of values.
/// </summary>
/// <param name="bytes">Array to be filled.</param>
public void NextBytes(byte[] bytes)
{
m_prg.GetBytes(bytes);
}
/// <summary>
/// Fills an array of bytes with a cryptographically strong
/// random sequence of values.
/// </summary>
/// <param name="bytes">Array to receive bytes.</param>
/// <param name="start">Index to start filling at.</param>
/// <param name="len">Length of segment to fill.</param>
public void NextBytes(byte[] bytes, int start, int len)
{
byte[] temp = new byte[len];
m_prg.GetBytes(temp);
Array.Copy(temp, 0, bytes, start, len);
}
}
}
#endif
+3 -3
View File
@@ -60,7 +60,7 @@ More samples based on the official [Nuget](https://www.nuget.org/packages/OPCFou
[![Github Actions](https://github.com/OPCFoundation/UA-.NETStandard/actions/workflows/buildandtest.yml/badge.svg)](https://github.com/OPCFoundation/UA-.NETStandard/actions/workflows/buildandtest.yml)
### Code Quality
[![Test Status](https://img.shields.io/azure-devops/tests/opcfoundation/opcua-netstandard/14?style=plastic)](https://opcfoundation.visualstudio.com/opcua-netstandard/_test/analytics?definitionId=14&contextType=build)
[![Tests](https://img.shields.io/azure-devops/tests/opcfoundation/opcua-netstandard/14/master?style=plastic&label=Tests)](https://opcfoundation.visualstudio.com/opcua-netstandard/_test/analytics?definitionId=14&contextType=build)
[![CodeQL](https://github.com/OPCFoundation/UA-.NETStandard/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/OPCFoundation/UA-.NETStandard/actions/workflows/codeql-analysis.yml)
[![Coverage Status](https://codecov.io/gh/OPCFoundation/UA-.NETStandard/branch/master/graph/badge.svg?token=vDf5AnilUt)](https://codecov.io/gh/OPCFoundation/UA-.NETStandard)
@@ -71,8 +71,8 @@ All the tools you need for .NET Standard come with the .NET Core tools. See [Get
Note: Since .NET Core 2.1 is end of life,
- VS 2017 has only limited support for .NET 4.8.
- VS 2019 is fully supported with .NET 4.8 and up to .NET Core 3.1 (end of life).
- VS 2022 is the current supported version, including .NET 6.0 (LTS).
- VS 2019 has only limited support for .NET 4.8 because .NET Core 3.1 reached end of life.
- VS 2022 is the current supported version, including .NET 6.0 (LTS) and .NET 8.0 (LTS).
1. Open the UA Reference.sln solution file using Visual Studio.
2. Choose a project in the Solution Explorer and set it with a right click as `Startup Project`.
+9
View File
@@ -2619,9 +2619,14 @@ namespace Opc.Ua
/// </summary>
public static X509Certificate2 ParseCertificateBlob(byte[] certificateData)
{
// macOS X509Certificate2 constructor throws exception if a certchain is encoded
// use AsnParser on macOS to parse for byteblobs,
#if !NETFRAMEWORK
bool useAsnParser = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
#else
bool useAsnParser = false;
#endif
try
{
if (useAsnParser)
@@ -2654,7 +2659,11 @@ namespace Opc.Ua
List<byte> certificatesBytes = new List<byte>(certificateData);
// macOS X509Certificate2 constructor throws exception if a certchain is encoded
// use AsnParser on macOS to parse for byteblobs,
#if !NETFRAMEWORK
bool useAsnParser = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
#else
bool useAsnParser = false;
#endif
while (certificatesBytes.Count > 0)
{
X509Certificate2 certificate;
+17 -9
View File
@@ -276,7 +276,7 @@ namespace Opc.Ua.Client.Tests
OutputSubscriptionInfo(TestContext.Out, subscription);
await subscription.ConditionRefreshAsync().ConfigureAwait(false);
var sre = Assert.Throws<ServiceResultException>(() => subscription.Republish(subscription.SequenceNumber));
var sre = Assert.ThrowsAsync<ServiceResultException>(async () => await subscription.RepublishAsync(subscription.SequenceNumber).ConfigureAwait(false));
Assert.AreEqual(StatusCodes.BadMessageNotAvailable, sre.StatusCode, $"Expected BadMessageNotAvailable, but received {sre.Message}");
// verify that reconnect created subclassed version of subscription and monitored item
@@ -610,7 +610,7 @@ namespace Opc.Ua.Client.Tests
Assert.IsTrue(reactivateResult);
}
await Task.Delay(kDelay).ConfigureAwait(false);
await Task.Delay(2 * kDelay).ConfigureAwait(false);
Assert.AreEqual(session1.SessionId, session2.SessionId);
@@ -638,7 +638,7 @@ namespace Opc.Ua.Client.Tests
}
else if (ii == 0)
{
Assert.AreEqual(10, targetSubscriptionCounters[ii], errorText);
Assert.AreEqual(monitoredItemCount, targetSubscriptionCounters[ii], errorText);
Assert.AreEqual(1, targetSubscriptionFastDataCounters[ii], errorText);
}
else
@@ -673,11 +673,18 @@ namespace Opc.Ua.Client.Tests
}
session1.DeleteSubscriptionsOnClose = true;
session1.Close(1000);
Utils.SilentDispose(session1);
session2.DeleteSubscriptionsOnClose = true;
session2.Close(1000);
if (asyncTest)
{
await session1.CloseAsync(1000).ConfigureAwait(false);
await session2.CloseAsync(1000).ConfigureAwait(false);
}
else
{
session1.Close(1000);
session2.Close(1000);
}
Utils.SilentDispose(session1);
Utils.SilentDispose(session2);
Assert.AreEqual(0, session1ConfigChanged);
@@ -971,7 +978,7 @@ namespace Opc.Ua.Client.Tests
TestContext.Out.WriteLine("TargetSession is now SessionId={0}", targetSession.SessionId);
// wait for some events
await Task.Delay(kDelay).ConfigureAwait(false);
await Task.Delay(2 * kDelay).ConfigureAwait(false);
if (TransferType.KeepOpen == transferType)
{
@@ -981,6 +988,7 @@ namespace Opc.Ua.Client.Tests
Assert.AreEqual(1, originSubscriptionTransferred[(int)subscription.Handle]);
}
}
// stop publishing
foreach (var subscription in transferSubscriptions)
{
@@ -1034,7 +1042,7 @@ namespace Opc.Ua.Client.Tests
}
// wait for some events
await Task.Delay(kDelay).ConfigureAwait(false);
await Task.Delay(2 * kDelay).ConfigureAwait(false);
// validate expected counts
for (int jj = 0; jj < kTestSubscriptions; jj++)
@@ -24,6 +24,18 @@
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
</ItemGroup>
<Choose>
<When Condition="'$(TargetFramework)' == 'net462'">
</When>
<When Condition="'$(TargetFramework)' == 'netstandard2.0'">
</When>
<Otherwise>
<PropertyGroup Condition="'$(DisableECCTests)' != 'true'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup Condition="'$(SignAssembly)' == 'true'">
<DefineConstants>$(DefineConstants);SIGNASSEMBLY</DefineConstants>
</PropertyGroup>
@@ -32,6 +32,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
@@ -40,6 +41,9 @@ using EmbedIO;
using EmbedIO.Actions;
using NUnit.Framework;
using Opc.Ua.Security.Certificates;
#if !ECC_SUPPORT
using X509SignatureGenerator = Opc.Ua.Security.Certificates.X509SignatureGenerator;
#endif
namespace Opc.Ua.Core.Tests.Security.Certificates
{
@@ -86,6 +90,14 @@ namespace Opc.Ua.Core.Tests.Security.Certificates
[OneTimeSetUp]
public async Task OneTimeSetUpAsync()
{
#if NETCOREAPP2_1_OR_GREATER && !ECC_SUPPORT
// this test cannot create the required certs on macOS with legacy bouncy castle support
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Assert.Ignore("Creating the alternate certifcates via Pfx is not supported on mac OS.");
}
#endif
var crlName = "root.crl";
m_webServerUrl = "http://127.0.0.1:9696/";
@@ -39,7 +39,7 @@ using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using Opc.Ua.Security.Certificates;
#if NETCOREAPP2_1
#if NETCOREAPP2_1 || !ECC_SUPPORT
using X509SignatureGenerator = Opc.Ua.Security.Certificates.X509SignatureGenerator;
#endif
@@ -771,13 +771,13 @@ namespace Opc.Ua.Core.Tests.Security.Certificates
var pemDataBlob = PEMWriter.ExportCertificateAsPEM(appCert);
var pemString = Encoding.UTF8.GetString(pemDataBlob);
TestContext.Out.WriteLine(pemString);
#if NETCOREAPP3_1_OR_GREATER
#if NETCOREAPP3_1_OR_GREATER && ECC_SUPPORT
var exception = Assert.Throws<ArgumentException>(() => CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(appCert), pemDataBlob));
#endif
}
}
#if NETCOREAPP3_1_OR_GREATER
#if NETCOREAPP3_1_OR_GREATER && ECC_SUPPORT
/// <summary>
/// Verify the PEM Writer, no password.
/// </summary>
@@ -29,6 +29,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
@@ -358,8 +359,9 @@ namespace Opc.Ua.Security.Certificates.Tests
}
}
#if NETFRAMEWORK || NETCOREAPP3_1
#if NETFRAMEWORK || NETCOREAPP3_1_OR_GREATER
[Test]
[SuppressMessage("Interoperability", "CA1416: Validate platform compatibility", Justification = "Test is ignored.")]
public void CreateIssuerRSACngWithSuppliedKeyPair()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -495,12 +497,12 @@ namespace Opc.Ua.Security.Certificates.Tests
PEMWriter.ExportCertificateAsPEM(certificate);
if (certificate.HasPrivateKey)
{
#if NETFRAMEWORK || NETCOREAPP2_1
#if NETFRAMEWORK || NETCOREAPP2_1 || !ECC_SUPPORT
// The implementation based on bouncy castle has no support to export with password
password = null;
#endif
PEMWriter.ExportPrivateKeyAsPEM(certificate, password);
#if NETCOREAPP3_1_OR_GREATER
#if NETCOREAPP3_1_OR_GREATER && ECC_SUPPORT
PEMWriter.ExportRSAPrivateKeyAsPEM(certificate);
#endif
}
@@ -7,29 +7,20 @@
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net472'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net48'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net5.0'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<Choose>
<When Condition="'$(TargetFramework)' == 'net462'">
</When>
<When Condition="'$(TargetFramework)' == 'netstandard2.0'">
</When>
<Otherwise>
<PropertyGroup Condition="'$(DisableECCTests)' != 'true'">
<DefineConstants>$(DefineConstants);ECC_SUPPORT</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net48'">
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
@@ -50,22 +41,6 @@
<Compile Include="..\Common\Main.cs"/>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
<ProjectReference Include="..\..\Libraries\Opc.Ua.Security.Certificates\Opc.Ua.Security.Certificates.csproj" />
+1 -1
View File
@@ -9,7 +9,7 @@ rem // remove trailing slash
set current-path=%current-path:~0,-1%
set build_root=%current-path%\..
set framework=net48
set runtimes=net48 netcoreapp3.1 net6.0 net8.0
set runtimes=net48 net6.0 net8.0
set filter=*
cd %build_root%
+41
View File
@@ -0,0 +1,41 @@
@echo off
setlocal enabledelayedexpansion
echo This script is used to run custom platform tests for the UA Core Library
echo Supported parameters: net462, netstandard2.0, netstandard2.1, net48, net6.0, net8.0
REM Check if the target framework parameter is provided
if "%1"=="" (
echo Usage: %0 [TargetFramework]
echo Allowed values for TargetFramework: net462, netstandard2.0, netstandard2.1, net48, net6.0, net8.0
goto :eof
)
REM Check if the provided TargetFramework is valid
set "validFrameworks= net462 netstandard2.0 netstandard2.1 net48 net6.0 net8.0"
if "!validFrameworks: %1 =!"=="%validFrameworks%" (
echo Invalid TargetFramework specified. Allowed values are: net462, netstandard2.0, netstandard2.1, net48, net6.0, net8.0
goto :eof
)
REM this is the variable used to switch the build scripts to a dedicated target
set CustomTestTarget=%1
REM clean up all obj and bin folders
REM Set the root directory path as batch file location
set "root=%~dp0"
REM Delete 'obj' and 'bin' folders
for /d /r "%root%" %%d in (*obj *bin) do (
echo Deleting "%%d"
del /S /F /Q "%%d\*.*"
rmdir /s /q "%%d"
)
echo Clean up complete.
echo restore %1
dotnet restore -f "..\UA Core Library.sln"
dotnet build --no-restore "..\UA Core Library.sln"
dotnet test "..\UA Core Library.sln"
+9
View File
@@ -47,6 +47,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azurepipelines", "azurepipelines", "{1C25BE72-C337-42AE-9F7C-D6B45F7B7079}"
ProjectSection(SolutionItems) = preProject
.azurepipelines\ci.yml = .azurepipelines\ci.yml
.azurepipelines\customtest.yml = .azurepipelines\customtest.yml
.azurepipelines\get-matrix.ps1 = .azurepipelines\get-matrix.ps1
.azurepipelines\get-root.ps1 = .azurepipelines\get-root.ps1
.azurepipelines\get-version.ps1 = .azurepipelines\get-version.ps1
@@ -83,6 +84,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stack", "Stack", "{12710D16-90C2-44B1-8B62-8046C1023055}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "actions", "actions", "{82AA8918-FD9F-4477-A131-874673BDC3B9}"
ProjectSection(SolutionItems) = preProject
.github\workflows\buildandtest.yml = .github\workflows\buildandtest.yml
.github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml
.github\workflows\docker-image.yml = .github\workflows\docker-image.yml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -191,6 +199,7 @@ Global
{D9985EA3-0A0F-4552-8BFA-65E282EFC6EA} = {DDDC86D8-79F7-488B-B445-AD176FAE1603}
{FC588507-282A-426E-8BC9-940860C76610} = {DDDC86D8-79F7-488B-B445-AD176FAE1603}
{9FC5C47D-5070-4222-B4F4-94EB495AEE4C} = {EE37EB25-F581-4794-9CAC-F15BF13D520C}
{82AA8918-FD9F-4477-A131-874673BDC3B9} = {0152A569-8287-4E49-9F02-E27FD700B719}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EA3AA3AE-CE8A-4DF1-BED8-CA0BAFC87303}
+53 -15
View File
@@ -25,7 +25,7 @@ pr:
variables:
FullBuild: ${{ or(ne(variables['Build.Reason'], 'PullRequest'), ne(variables['System.PullRequest.IsFork'], 'False')) }}
ScheduledBuild: ${{ eq(variables['Build.Reason'], 'Schedule') }}
ScheduledBuild: ${{ in(variables['Build.Reason'], 'Schedule', 'Manual') }}
stages:
- stage: build
@@ -64,16 +64,6 @@ stages:
framework: net48
agents: '@{ windows = "windows-2019" }'
jobnamesuffix: net48
- template: .azurepipelines/test.yml
parameters:
configuration: Release
framework: netcoreapp3.1
jobnamesuffix: core3
- stage: test6release
dependsOn: [build]
displayName: 'Test .NET 6 Core and SDK Release'
condition: and(succeeded(), ne(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
parameters:
configuration: Release
@@ -82,7 +72,7 @@ stages:
jobnamesuffix: net60
- stage: testreleasepr
dependsOn: []
displayName: 'Fast PR Test Core and SDK Release'
displayName: 'Fast .NET 6.0 PR Test'
condition: and(eq(variables.FullBuild, 'False'), eq(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
@@ -93,13 +83,60 @@ stages:
jobnamesuffix: net60pr
- stage: testdebug
dependsOn: [build]
displayName: 'Test Core and SDK Debug'
displayName: 'Test .NET 6.0 Debug'
condition: and(succeeded(), ne(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
parameters:
framework: netcoreapp3.1
framework: net6.0
configuration: Debug
jobnamesuffix: net60debug
- stage: testnet80
dependsOn: [build]
displayName: 'Test .NET 8.0'
condition: and(succeeded(), ne(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
parameters:
framework: net8.0
configuration: Release
jobnamesuffix: net80
customtestarget: net8.0
- stage: testnet462
dependsOn: [build]
displayName: 'Test .NET 4.6.2'
condition: and(succeeded(), ne(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
parameters:
framework: net462
configuration: Release
jobnamesuffix: net462
agents: '@{ windows = "windows-2022" }'
customtestarget: net462
- stage: testnetstandard20
dependsOn: [build]
displayName: 'Test .NETStandard 2.0'
condition: and(succeeded(), ne(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
parameters:
framework: net6.0
configuration: Release
jobnamesuffix: netstandard20
agents: '@{ windows = "windows-2019"; linux="ubuntu-20.04"}'
customtestarget: netstandard2.0
- stage: testnetstandard21
dependsOn: [build]
displayName: 'Test .NETStandard 2.1'
condition: and(succeeded(), ne(variables.ScheduledBuild, 'False'))
jobs:
- template: .azurepipelines/test.yml
parameters:
framework: net6.0
configuration: Release
jobnamesuffix: netstandard21
customtestarget: netstandard2.1
- stage: coverage
dependsOn: [testdebug,testrelease]
displayName: 'Code Coverage'
@@ -109,5 +146,6 @@ stages:
parameters:
configuration: Release
poolImage: 'ubuntu-22.04'
framework: net6.0
framework: net8.0
jobnamesuffix: net60cc
customtestarget: net8.0
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<Product>OPC UA .NET Standard Library</Product>
<RepositoryUrl>https://github.com/OPCFoundation/UA-.NETStandard</RepositoryUrl>
<VersionPrefix>1.04.368</VersionPrefix>
<VersionPrefix>1.04.372</VersionPrefix>
<VersionSuffix>preview-$([System.DateTime]::Now.ToString("yyyyMMdd"))</VersionSuffix>
<Copyright>Copyright © 2004-2023 OPC Foundation, Inc</Copyright>
<Company>OPC Foundation</Company>
+90 -6
View File
@@ -1,23 +1,107 @@
<Project>
<!-- Uncomment to suppress warning that .NET Core 2.1 is used with .NET 6 library. -->
<!--
<PropertyGroup>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>
-->
<!--
A custom target can be used to test a future or legacy target.
A build with all custom targets which are not part of a regular build
is scheduled once a week in the DevOps build pipeline.
Uncomment the following lines to test a custom test target
supported values: net462, netstandard2.0, netstandard2.1, net48, net6.0, net8.0
-->
<!--
<PropertyGroup>
<CustomTestTarget>netstandard2.0</CustomTestTarget>
</PropertyGroup>
-->
<Choose>
<!-- Note: .NET Core 2.x is end of life, removed netcoreapp2.1 from any target. -->
<!-- Note: to test targets which support deprecated platforms,
set the CustomTestTarget environment variable accordingly -->
<When Condition="'$(CustomTestTarget)' == 'net462'">
<PropertyGroup>
<DisableECCTests>true</DisableECCTests>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net462</AppTargetFrameworks>
<AppTargetFramework>net462</AppTargetFramework>
<TestsTargetFrameworks>net462</TestsTargetFrameworks>
<LibTargetFrameworks>net462</LibTargetFrameworks>
<LibxTargetFrameworks>net462</LibxTargetFrameworks>
<HttpsTargetFrameworks>net462</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<When Condition="'$(CustomTestTarget)' == 'netstandard2.0'">
<PropertyGroup>
<DisableECCTests>true</DisableECCTests>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net6.0</AppTargetFrameworks>
<AppTargetFramework>net6.0</AppTargetFramework>
<TestsTargetFrameworks>net6.0</TestsTargetFrameworks>
<LibTargetFrameworks>netstandard2.0</LibTargetFrameworks>
<LibxTargetFrameworks>netstandard2.1</LibxTargetFrameworks>
<HttpsTargetFrameworks>netstandard2.0</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<When Condition="'$(CustomTestTarget)' == 'netstandard2.1'">
<PropertyGroup>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net6.0</AppTargetFrameworks>
<AppTargetFramework>net6.0</AppTargetFramework>
<TestsTargetFrameworks>net6.0</TestsTargetFrameworks>
<LibTargetFrameworks>netstandard2.1</LibTargetFrameworks>
<LibxTargetFrameworks>netstandard2.1</LibxTargetFrameworks>
<HttpsTargetFrameworks>netstandard2.1</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<When Condition="'$(CustomTestTarget)' == 'net48'">
<PropertyGroup>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net48</AppTargetFrameworks>
<AppTargetFramework>net48</AppTargetFramework>
<TestsTargetFrameworks>net48</TestsTargetFrameworks>
<LibTargetFrameworks>net48</LibTargetFrameworks>
<LibxTargetFrameworks>net48</LibxTargetFrameworks>
<HttpsTargetFrameworks>net48</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<When Condition="'$(CustomTestTarget)' == 'net6.0'">
<PropertyGroup>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net6.0</AppTargetFrameworks>
<AppTargetFramework>net6.0</AppTargetFramework>
<TestsTargetFrameworks>net6.0</TestsTargetFrameworks>
<LibTargetFrameworks>net6.0</LibTargetFrameworks>
<LibxTargetFrameworks>net6.0</LibxTargetFrameworks>
<HttpsTargetFrameworks>net6.0</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<When Condition="'$(CustomTestTarget)' == 'net8.0'">
<PropertyGroup>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net8.0</AppTargetFrameworks>
<AppTargetFramework>net8.0</AppTargetFramework>
<TestsTargetFrameworks>net8.0</TestsTargetFrameworks>
<LibTargetFrameworks>net8.0</LibTargetFrameworks>
<LibxTargetFrameworks>net8.0</LibxTargetFrameworks>
<HttpsTargetFrameworks>net8.0</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<!-- Note: .NET Core 2.x and 3.x is end of life, removed netcoreapp2.1/3.1 from any target. -->
<!-- Note: .NET Framework 4.6.2 deprecated for .372, removed net462 from any target. -->
<!-- Visual Studio 2022, supports .NET Framework 4.8, .NET Core 3.1 and .NET 6 -->
<When Condition="'$(VisualStudioVersion)' == '17.0'">
<PropertyGroup>
<AnalysisLevel>preview-all</AnalysisLevel>
<AppTargetFrameworks>net6.0;netcoreapp3.1;net48</AppTargetFrameworks>
<AppTargetFrameworks>net6.0;net48</AppTargetFrameworks>
<AppTargetFramework>net6.0</AppTargetFramework>
<TestsTargetFrameworks>net48;netcoreapp3.1;net6.0</TestsTargetFrameworks>
<LibTargetFrameworks>net48;netstandard2.0;netstandard2.1;net6.0</LibTargetFrameworks>
<LibxTargetFrameworks>net48;netstandard2.1;net6.0</LibxTargetFrameworks>
<HttpsTargetFrameworks>net48;netstandard2.0;netcoreapp3.1;net6.0</HttpsTargetFrameworks>
<TestsTargetFrameworks>net48;net6.0</TestsTargetFrameworks>
<LibTargetFrameworks>net48;netstandard2.0;netstandard2.1;net6.0;net8.0</LibTargetFrameworks>
<LibxTargetFrameworks>net48;netstandard2.1;net6.0;net8.0</LibxTargetFrameworks>
<HttpsTargetFrameworks>net48;netstandard2.0;netcoreapp3.1;net6.0;net8.0</HttpsTargetFrameworks>
</PropertyGroup>
</When>
<!-- Visual Studio 2019, supports .NET Framework 4.8 and .NET Core 3.1 -->