diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cdf176af3a..37d6898b3f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,10 +7,18 @@ on:
- 'release/**'
- 'maintenance/**'
paths-ignore:
- - '**/*.png'
- '**/*.md'
+ - '**/*.png'
workflow_dispatch:
+permissions:
+ contents: read
+
+concurrency:
+ group: ci-${{ github.workflow }}-${{ github.ref }}
+ # Never interrupt a master run while it may be publishing an immutable package set.
+ cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
@@ -18,87 +26,78 @@ env:
jobs:
build-and-test:
name: Build & Test
- runs-on: windows-latest
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ permissions:
+ contents: read
+ id-token: write
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v7
with:
fetch-depth: 1
lfs: true
- - name: Setup .NET SDK
- uses: actions/setup-dotnet@v4
+ - name: Setup .NET SDKs
+ uses: actions/setup-dotnet@v6
with:
dotnet-version: |
- 6.0.x
8.0.x
+ 9.0.x
+ 10.0.x
- - name: Build, Test and Pack
- shell: pwsh
- run: |
- ./Build/build.ps1
- working-directory: ${{ github.workspace }}
-
- - name: Upload to codecov.io
+ - name: Build, test and pack
shell: pwsh
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- run: |
- Write-Host -Foreground Green "Downloading codecov binaries..."
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/verification.gpg -OutFile codecov.asc
- gpg.exe --import codecov.asc
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM -Outfile codecov.exe.SHA256SUM
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM.sig -Outfile codecov.exe.SHA256SUM.sig
-
- gpg.exe --verify codecov.exe.SHA256SUM.sig codecov.exe.SHA256SUM
- If ($(Compare-Object -ReferenceObject $(($(certUtil -hashfile codecov.exe SHA256)[1], "codecov.exe") -join " ") -DifferenceObject $(Get-Content codecov.exe.SHA256SUM)).length -eq 0) { echo "SHASUM verified" } Else {exit 1}
+ run: ./Build/build.ps1
- Write-Host -Foreground Green "Uploading to codecov..."
-
- .\codecov.exe --dir "Artifacts/Coverage" -t "$env:CODECOV_TOKEN" --build "${{ github.run_number }}"
-
- Write-Host -Foreground Green "✅ Uploaded to codecov."
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v6
+ with:
+ directory: Artifacts/Coverage
+ fail_ci_if_error: true
+ plugins: noop
+ use_oidc: true
- - name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v7
with:
name: artifacts
path: Artifacts/
retention-days: 30
- name: Upload NuGet packages
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: nuget-packages
path: |
Artifacts/**/*.nupkg
Artifacts/**/*.snupkg
+ if-no-files-found: error
retention-days: 30
publish-nuget:
- name: Publish to NuGet
+ name: Publish NuGet packages
needs: build-and-test
runs-on: ubuntu-latest
+ timeout-minutes: 10
if: github.ref == 'refs/heads/master' && github.repository_owner == 'angularsen'
environment: Publish
steps:
- name: Download NuGet packages
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: nuget-packages
path: nugets
- name: Setup .NET SDK
- uses: actions/setup-dotnet@v4
+ uses: actions/setup-dotnet@v6
with:
- dotnet-version: 8.0.x
+ dotnet-version: 10.0.x
- name: Push to nuget.org
- run: |
- dotnet nuget push "**/*.nupkg" --skip-duplicate --api-key ${{ secrets.NUGET_ORG_APIKEY }} --source https://api.nuget.org/v3/index.json
- working-directory: nugets
\ No newline at end of file
+ env:
+ NUGET_ORG_APIKEY: ${{ secrets.NUGET_ORG_APIKEY }}
+ run: dotnet nuget push "**/*.nupkg" --skip-duplicate --api-key "$NUGET_ORG_APIKEY" --source https://api.nuget.org/v3/index.json
+ working-directory: nugets
diff --git a/.github/workflows/net48-compatibility.yml b/.github/workflows/net48-compatibility.yml
new file mode 100644
index 0000000000..d5e435929c
--- /dev/null
+++ b/.github/workflows/net48-compatibility.yml
@@ -0,0 +1,118 @@
+name: .NET Framework 4.8 Compatibility
+
+on:
+ # Remove `pull_request` for post-merge validation only, or remove `push` for PR validation only.
+ # Test and coverage behavior is identical for every enabled trigger.
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ id-token: write
+
+concurrency:
+ group: net48-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+env:
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+
+jobs:
+ test:
+ name: Test and coverage on CLR 4
+ runs-on: windows-latest
+ timeout-minutes: 45
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v7
+ with:
+ fetch-depth: 1
+ lfs: true
+
+ - name: Setup .NET SDK
+ uses: actions/setup-dotnet@v6
+ with:
+ dotnet-version: 10.0.x
+
+ - name: Restore .NET tools
+ run: dotnet tool restore
+
+ - name: Generate code
+ run: dotnet run --project CodeGen
+
+ - name: Run the complete test suite with coverage on .NET Framework 4.8
+ shell: pwsh
+ run: |
+ $testProjects = @(
+ 'UnitsNet.Tests/UnitsNet.Tests.csproj',
+ 'UnitsNet.NumberExtensions.Tests/UnitsNet.NumberExtensions.Tests.csproj',
+ 'UnitsNet.NumberExtensions.CS14.Tests/UnitsNet.NumberExtensions.CS14.Tests.csproj',
+ 'UnitsNet.Serialization.JsonNet.Tests/UnitsNet.Serialization.JsonNet.Tests.csproj'
+ )
+
+ New-Item -ItemType Directory -Force -Path Artifacts/Coverage | Out-Null
+
+ foreach ($testProject in $testProjects) {
+ $projectName = [IO.Path]::GetFileNameWithoutExtension($testProject)
+
+ dotnet dotcover test $testProject `
+ --configuration Release `
+ --framework net48 `
+ --logger trx `
+ --results-directory Artifacts/TestResults `
+ -p:ContinuousIntegrationBuild=true `
+ --dotCoverFilters="+:module=UnitsNet*;-:module=*Tests" `
+ --dotCoverOutput="Artifacts/Coverage/$projectName.coverage.xml" `
+ --dcReportType=DetailedXML
+
+ if ($LASTEXITCODE -ne 0) {
+ exit $LASTEXITCODE
+ }
+ }
+
+ - name: Upload test results
+ if: always()
+ uses: actions/upload-artifact@v7
+ with:
+ name: net48-test-results
+ path: Artifacts/TestResults/*.trx
+ if-no-files-found: ignore
+ retention-days: 30
+
+ # publish-net48-test-results.yml defines the "Publish .NET Framework 4.8 Test Results"
+ # workflow_run workflow that publishes these results with checks: write. Keeping that permission
+ # out of this workflow lets fork PRs execute contributor code with a read-only token.
+ - name: Upload workflow event
+ if: always()
+ uses: actions/upload-artifact@v7
+ with:
+ name: net48-event
+ path: ${{ github.event_path }}
+ retention-days: 30
+
+ - name: Upload coverage to Codecov
+ if: ${{ success() && hashFiles('Artifacts/Coverage/*.coverage.xml') != '' }}
+ uses: codecov/codecov-action@v6
+ with:
+ directory: Artifacts/Coverage
+ fail_ci_if_error: ${{ github.event_name != 'pull_request' }}
+ flags: net48
+ name: net48-clr4
+ plugins: noop
+ use_oidc: true
+
+ - name: Upload coverage reports
+ if: always()
+ uses: actions/upload-artifact@v7
+ with:
+ name: net48-coverage
+ path: Artifacts/Coverage/*.coverage.xml
+ if-no-files-found: ignore
+ retention-days: 30
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index fc2347bd29..5c25d91f4a 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -7,9 +7,13 @@ on:
- 'release/**'
- 'maintenance/**'
paths-ignore:
- - '*.md'
- - '*.png'
- - '*.gitignore'
+ - '**/*.gitignore'
+ - '**/*.md'
+ - '**/*.png'
+
+concurrency:
+ group: pr-${{ github.workflow }}-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
@@ -18,71 +22,60 @@ env:
jobs:
build-and-test:
name: Build & Test
- runs-on: windows-latest
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ permissions:
+ contents: read
+ checks: write
+ id-token: write
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v7
with:
fetch-depth: 1
lfs: true
- - name: Setup .NET SDK
- uses: actions/setup-dotnet@v4
+ - name: Setup .NET SDKs
+ uses: actions/setup-dotnet@v6
with:
dotnet-version: |
- 6.0.x
8.0.x
+ 9.0.x
+ 10.0.x
- - name: Build, Test and Pack
+ - name: Build, test and pack
shell: pwsh
- run: |
- ./Build/build.ps1
- working-directory: ${{ github.workspace }}
+ run: ./Build/build.ps1
- - name: Upload Test Results
- uses: actions/upload-artifact@v4
+ - name: Upload test results
if: always()
+ uses: actions/upload-artifact@v7
with:
name: test-results
path: Artifacts/TestResults/*.trx
+ if-no-files-found: ignore
retention-days: 7
- - name: Publish Test Results
- uses: EnricoMi/publish-unit-test-result-action/windows@v2
- if: always()
+ - name: Publish test results
+ if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository && hashFiles('Artifacts/TestResults/*.trx') != '' }}
+ uses: EnricoMi/publish-unit-test-result-action@v2
with:
- files: |
- Artifacts/TestResults/*.trx
+ files: Artifacts/TestResults/*.trx
check_name: Test Results
comment_mode: off
- - name: Upload to codecov.io
- shell: pwsh
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- run: |
- Write-Host -Foreground Green "Downloading codecov binaries..."
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/verification.gpg -OutFile codecov.asc
- gpg.exe --import codecov.asc
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM -Outfile codecov.exe.SHA256SUM
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM.sig -Outfile codecov.exe.SHA256SUM.sig
-
- gpg.exe --verify codecov.exe.SHA256SUM.sig codecov.exe.SHA256SUM
- If ($(Compare-Object -ReferenceObject $(($(certUtil -hashfile codecov.exe SHA256)[1], "codecov.exe") -join " ") -DifferenceObject $(Get-Content codecov.exe.SHA256SUM)).length -eq 0) { echo "SHASUM verified" } Else {exit 1}
-
- Write-Host -Foreground Green "Uploading to codecov..."
-
- .\codecov.exe --dir "Artifacts/Coverage" -t "$env:CODECOV_TOKEN" --build "${{ github.run_number }}"
-
- Write-Host -Foreground Green "✅ Uploaded to codecov."
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v6
+ with:
+ directory: Artifacts/Coverage
+ fail_ci_if_error: false
+ plugins: noop
+ use_oidc: true
- - name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v7
with:
name: artifacts
path: Artifacts/
- retention-days: 7
\ No newline at end of file
+ retention-days: 7
diff --git a/.github/workflows/publish-net48-test-results.yml b/.github/workflows/publish-net48-test-results.yml
new file mode 100644
index 0000000000..b399c60d3b
--- /dev/null
+++ b/.github/workflows/publish-net48-test-results.yml
@@ -0,0 +1,50 @@
+name: Publish .NET Framework 4.8 Test Results
+
+on:
+ workflow_run:
+ workflows:
+ - .NET Framework 4.8 Compatibility
+ types:
+ - completed
+
+# This workflow receives write permission because it never checks out or executes contributor
+# code. It only downloads immutable artifacts from the exact workflow run that triggered it.
+permissions: {}
+
+jobs:
+ publish:
+ name: Publish test results
+ if: ${{ github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure' }}
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ permissions:
+ actions: read
+ checks: write
+
+ steps:
+ - name: Download test results
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: net48-test-results
+ path: artifacts/net48-test-results
+ github-token: ${{ github.token }}
+ run-id: ${{ github.event.workflow_run.id }}
+
+ - name: Download workflow event
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: net48-event
+ path: artifacts/net48-event
+ github-token: ${{ github.token }}
+ run-id: ${{ github.event.workflow_run.id }}
+
+ - name: Publish test results
+ if: ${{ hashFiles('artifacts/net48-test-results/*.trx') != '' }}
+ uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
+ with:
+ check_name: .NET Framework 4.8 Test Results
+ comment_mode: off
+ commit: ${{ github.event.workflow_run.head_sha }}
+ event_file: artifacts/net48-event/event.json
+ event_name: ${{ github.event.workflow_run.event }}
+ files: artifacts/net48-test-results/*.trx
diff --git a/Build/build-functions.psm1 b/Build/build-functions.psm1
index 96a801fbbe..5aa22cb354 100644
--- a/Build/build-functions.psm1
+++ b/Build/build-functions.psm1
@@ -54,9 +54,12 @@ function Start-Tests {
# dotnet commands (xunit, dotcover) must run in same dir as project
push-location $projectDir
- # Create coverage report for this test project
+ # Build validates every target framework. Run tests and collect coverage only on the latest
+ # .NET runtime because net8.0, net9.0, and net10.0 compile the same code paths. The separate
+ # CLR4 workflow tests the meaningfully different netstandard2.0 assets on .NET Framework.
& dotnet dotcover test `
--no-build `
+ --framework net10.0 `
--logger trx `
--results-directory "$testReportDir" `
--dotCoverFilters="+:module=UnitsNet*;-:module=*Tests" `
diff --git a/GITHUB_ACTIONS_MIGRATION_README.md b/GITHUB_ACTIONS_MIGRATION_README.md
deleted file mode 100644
index 8bc08b6f9f..0000000000
--- a/GITHUB_ACTIONS_MIGRATION_README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# GitHub Actions Migration
-
-This PR adds GitHub Actions workflows to run alongside the existing Azure Pipelines configuration.
-
-## Files to Move
-
-Due to GitHub App permission restrictions, the workflow files are created in the root directory. Please move these files to `.github/workflows/` after merging:
-
-1. `github-actions-ci.yml` → `.github/workflows/ci.yml`
-2. `github-actions-pr.yml` → `.github/workflows/pr.yml`
-
-## Key Features
-
-### CI Workflow (ci.yml)
-- Triggers on pushes to master, release/*, and maintenance/* branches
-- Runs tests and uploads coverage to codecov.io
-- Publishes NuGet packages to nuget.org (only on master branch)
-- Uses Windows runner to match Azure Pipelines configuration
-
-### PR Workflow (pr.yml)
-- Triggers on pull requests to master, release/*, and maintenance/* branches
-- Same build and test process as CI workflow
-- Publishes test results as PR checks
-- Uploads test coverage to codecov.io
-- No NuGet publishing for PRs
-
-## Migration Notes
-
-- Both workflows use the existing PowerShell build script (`Build/build.ps1`)
-- Secrets needed: `CODECOV_TOKEN` and `NUGET_ORG_APIKEY` (should already be configured)
-- The workflows are designed to run alongside Azure Pipelines for comparison
-- Azure Pipelines configuration files remain unchanged as requested
-
-## Next Steps
-
-1. Move the workflow files to `.github/workflows/`
-2. Test both workflows to ensure they work correctly
-3. Compare results with Azure Pipelines
-4. Make any necessary adjustments based on testing
\ No newline at end of file
diff --git a/README.md b/README.md
index 848da04e66..169cd060f7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-[](https://dev.azure.com/unitsnet/Units.NET/_build/latest?definitionId=1&branchName=master)
+[](https://github.com/angularsen/UnitsNet/actions/workflows/ci.yml)
+[](https://github.com/angularsen/UnitsNet/actions/workflows/pr.yml)
+[](https://github.com/angularsen/UnitsNet/actions/workflows/net48-compatibility.yml)
[](https://codecov.io/gh/angularsen/UnitsNet)
[](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
@@ -476,11 +478,14 @@ Get the same strongly typed units on other platforms, based on the same [unit de
### Continuous Integration
-[Azure DevOps](https://dev.azure.com/unitsnet/Units.NET/) performs the following:
+[GitHub Actions](https://github.com/angularsen/UnitsNet/actions) performs the following for v6 on `master`:
-* Build and test all branches
-* Build and test pull requests, notifies on success or error
-* Deploy NuGets on master branch, if nuspec versions changed
+* The [CI workflow](https://github.com/angularsen/UnitsNet/actions/workflows/ci.yml) builds and tests pushes to `master` and publishes packages to [NuGet.org](https://www.nuget.org/packages/UnitsNet)
+* The [pull-request workflow](https://github.com/angularsen/UnitsNet/actions/workflows/pr.yml) builds and tests pull requests, with test results and code coverage
+* Linux CI builds every shipped target and runs the full test suite with coverage on .NET 10
+* The [.NET Framework 4.8 compatibility workflow](https://github.com/angularsen/UnitsNet/actions/workflows/net48-compatibility.yml) runs the complete test suite against the `netstandard2.0` assemblies on CLR4 for pull requests and pushes to `master`
+
+The [`maintenance/v5`](https://github.com/angularsen/UnitsNet/tree/maintenance/v5) branch remains on Azure DevOps because its nanoFramework build requires Visual Studio MSBuild and the nanoFramework MSBuild components.
### Who are Using UnitsNet?
diff --git a/UnitsNet.NumberExtensions.CS14.Tests/UnitsNet.NumberExtensions.CS14.Tests.csproj b/UnitsNet.NumberExtensions.CS14.Tests/UnitsNet.NumberExtensions.CS14.Tests.csproj
index 3983936e1d..af9a2e50a9 100644
--- a/UnitsNet.NumberExtensions.CS14.Tests/UnitsNet.NumberExtensions.CS14.Tests.csproj
+++ b/UnitsNet.NumberExtensions.CS14.Tests/UnitsNet.NumberExtensions.CS14.Tests.csproj
@@ -1,7 +1,8 @@
- net48;net8.0;net9.0;net10.0
+ net10.0
+ $(TargetFrameworks);net48
UnitsNet.NumberExtensions.Tests
preview
enable
diff --git a/UnitsNet.NumberExtensions.CS14/UnitsNet.NumberExtensions.CS14.csproj b/UnitsNet.NumberExtensions.CS14/UnitsNet.NumberExtensions.CS14.csproj
index 9ff4fcacde..e6302ea00f 100644
--- a/UnitsNet.NumberExtensions.CS14/UnitsNet.NumberExtensions.CS14.csproj
+++ b/UnitsNet.NumberExtensions.CS14/UnitsNet.NumberExtensions.CS14.csproj
@@ -15,6 +15,7 @@
MIT-0
false
UnitsNet Extensions NumberToExtensions NumberToUnitsExtensions NumberExtensions NumberToUnits convert conversion parse
+ README.md
@@ -52,6 +53,7 @@
+
diff --git a/UnitsNet.NumberExtensions.Tests/UnitsNet.NumberExtensions.Tests.csproj b/UnitsNet.NumberExtensions.Tests/UnitsNet.NumberExtensions.Tests.csproj
index be1d2ddbb8..4344a9b89b 100644
--- a/UnitsNet.NumberExtensions.Tests/UnitsNet.NumberExtensions.Tests.csproj
+++ b/UnitsNet.NumberExtensions.Tests/UnitsNet.NumberExtensions.Tests.csproj
@@ -1,7 +1,8 @@
- net48;net8.0;net9.0;net10.0
+ net10.0
+ $(TargetFrameworks);net48
UnitsNet.NumberExtensions.Tests
latest
enable
diff --git a/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj b/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj
index 90747668bd..77e1339e3c 100644
--- a/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj
+++ b/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj
@@ -15,6 +15,7 @@
MIT-0
false
UnitsNet Extensions NumberToExtensions NumberToUnitsExtensions NumberExtensions NumberToUnits convert conversion parse
+ README.md
@@ -49,6 +50,7 @@
+
diff --git a/UnitsNet.Serialization.JsonNet.Tests/UnitsNet.Serialization.JsonNet.Tests.csproj b/UnitsNet.Serialization.JsonNet.Tests/UnitsNet.Serialization.JsonNet.Tests.csproj
index dddf08cd08..f3b029259d 100644
--- a/UnitsNet.Serialization.JsonNet.Tests/UnitsNet.Serialization.JsonNet.Tests.csproj
+++ b/UnitsNet.Serialization.JsonNet.Tests/UnitsNet.Serialization.JsonNet.Tests.csproj
@@ -1,8 +1,10 @@
- net8.0;net9.0;net10.0
+ net10.0
+ $(TargetFrameworks);net48
UnitsNet.Serialization.JsonNet.Tests
+ latest
true
CS0618
diff --git a/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj b/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj
index 725a174924..4b5b327ceb 100644
--- a/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj
+++ b/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj
@@ -15,6 +15,7 @@
MIT-0
false
unit units measurement json Json.NET Newtonsoft serialize deserialize serialization deserialization
+ README.md
Upgrade JSON.NET to 12.0.3. Support arrays.
@@ -51,6 +52,7 @@
+
diff --git a/UnitsNet.Tests/UnitsNet.Tests.csproj b/UnitsNet.Tests/UnitsNet.Tests.csproj
index 0ab93c024c..e97fc71757 100644
--- a/UnitsNet.Tests/UnitsNet.Tests.csproj
+++ b/UnitsNet.Tests/UnitsNet.Tests.csproj
@@ -1,7 +1,8 @@
- net8.0;net9.0;net10.0
+ net10.0
+ $(TargetFrameworks);net48
latest
enable
true
diff --git a/UnitsNet.slnx b/UnitsNet.slnx
index 19f5d456fa..7c14e04985 100644
--- a/UnitsNet.slnx
+++ b/UnitsNet.slnx
@@ -9,7 +9,6 @@
-
@@ -52,4 +51,4 @@
-
\ No newline at end of file
+
diff --git a/azure-pipelines-pr.yml b/azure-pipelines-pr.yml
index 8a6ab51fa8..4f3f2c0aa9 100644
--- a/azure-pipelines-pr.yml
+++ b/azure-pipelines-pr.yml
@@ -1,104 +1,12 @@
-name: PR_$(Date:yyyy.MM.dd)$(Rev:.rrr)
-
-# PR pipeline
-# - Build all targets
-# - Run tests and upload test coverage to codecov.io
-
+# PR validation for v6/master has moved to GitHub Actions.
+# maintenance/v5 retains its branch-specific Azure Pipeline definition for nanoFramework.
trigger: none
-pr:
- branches:
- include:
- - master
- - release/*
- - maintenance/*
- paths:
- exclude:
- - '*.md'
- - '*.png'
- - '*.gitignore'
+pr: none
pool:
- vmImage: windows-latest
-
-variables:
-- group: common
-
-stages:
-- stage: Build
- displayName: Build & test
- jobs:
- - job: Build
- displayName: Build & test
- steps:
- - checkout: self
- fetchDepth: 1
- clean: false
- lfs: true
- submodules: false
- fetchTags: false
-
- - task: UseDotNet@2
- displayName: 'Install .NET 8 SDK'
- inputs:
- packageType: 'sdk'
- version: '8.x'
-
- - task: UseDotNet@2
- displayName: 'Install .NET 9 SDK'
- inputs:
- packageType: 'sdk'
- version: '9.x'
-
- - task: UseDotNet@2
- displayName: 'Install .NET 10 SDK Preview (for C# 14)'
- inputs:
- packageType: 'sdk'
- version: '10.x'
- includePreviewVersions: true
-
- - task: PowerShell@2
- displayName: 'Build, test, pack'
- inputs:
- filePath: 'Build/build.ps1'
- failOnStderr: true
- showWarnings: true
- pwsh: true
- workingDirectory: '$(Build.SourcesDirectory)'
-
- - task: PublishTestResults@2
- condition: always()
- inputs:
- testResultsFormat: "VSTest"
- testResultsFiles: "*.trx"
- searchFolder: $(Build.SourcesDirectory)\Artifacts\TestResults
- mergeTestResults: true
-
- - task: PowerShell@2
- displayName: Upload to codecov.io
- env:
- CODECOV_TOKEN: $(CODECOV_TOKEN)
- inputs:
- targetType: 'inline'
- script: |
- Write-Host -Foreground Green "Downloading codecov binaries..."
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/verification.gpg -OutFile codecov.asc
- gpg.exe --import codecov.asc
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM -Outfile codecov.exe.SHA256SUM
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM.sig -Outfile codecov.exe.SHA256SUM.sig
-
- gpg.exe --verify codecov.exe.SHA256SUM.sig codecov.exe.SHA256SUM
- If ($(Compare-Object -ReferenceObject $(($(certUtil -hashfile codecov.exe SHA256)[1], "codecov.exe") -join " ") -DifferenceObject $(Get-Content codecov.exe.SHA256SUM)).length -eq 0) { echo "SHASUM verified" } Else {exit 1}
-
- Write-Host -Foreground Green "Uploading to codecov..."
-
- .\codecov.exe --dir "Artifacts/Coverage" -t "$env:CODECOV_TOKEN" --build "$(Build.BuildNumber)"
-
- Write-Host -Foreground Green "✅ Uploaded to codecov."
- pwsh: true
+ vmImage: ubuntu-latest
- - publish: $(Build.SourcesDirectory)/Artifacts
- displayName: 'Publish Artifacts'
- artifact: 'Artifacts'
\ No newline at end of file
+steps:
+- checkout: none
+- script: echo "Azure Pipelines is disabled for v6. Use the GitHub Actions PR workflow."
+ displayName: GitHub Actions migration notice
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index e0f7a05ff8..65d2aecebb 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,144 +1,12 @@
+# CI for v6/master has moved to GitHub Actions.
+# maintenance/v5 retains its branch-specific Azure Pipeline definition for nanoFramework.
+trigger: none
pr: none
-trigger:
- branches:
- include:
- - master
- - release/*
- - maintenance/*
- paths:
- exclude:
- - '**/*.png'
- - '**/*.md'
pool:
- vmImage: windows-latest
+ vmImage: ubuntu-latest
-variables:
-- group: common
-
-stages:
-- stage: Build
- displayName: Build & test
- jobs:
- - job: Build
- displayName: Build & test
- steps:
- - checkout: self
- fetchDepth: 1
- clean: false
- lfs: true
- submodules: false
- fetchTags: false
-
- - task: UseDotNet@2
- displayName: 'Install .NET 8 SDK'
- inputs:
- packageType: 'sdk'
- version: '8.x'
-
- - task: UseDotNet@2
- displayName: 'Install .NET 9 SDK'
- inputs:
- packageType: 'sdk'
- version: '9.x'
-
- - task: UseDotNet@2
- displayName: 'Install .NET 10 SDK Preview (for C# 14)'
- inputs:
- packageType: 'sdk'
- version: '10.x'
- includePreviewVersions: true
-
- - task: PowerShell@2
- displayName: 'Build, test, pack'
- inputs:
- filePath: 'Build/build.ps1'
- failOnStderr: true
- showWarnings: true
- pwsh: true
- workingDirectory: '$(Build.SourcesDirectory)'
-
- - task: PowerShell@2
- displayName: Upload to codecov.io
- env:
- CODECOV_TOKEN: $(CODECOV_TOKEN)
- inputs:
- targetType: 'inline'
- script: |
- Write-Host -Foreground Green "Downloading codecov binaries..."
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/verification.gpg -OutFile codecov.asc
- gpg.exe --import codecov.asc
-
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM -Outfile codecov.exe.SHA256SUM
- Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe.SHA256SUM.sig -Outfile codecov.exe.SHA256SUM.sig
-
- gpg.exe --verify codecov.exe.SHA256SUM.sig codecov.exe.SHA256SUM
- If ($(Compare-Object -ReferenceObject $(($(certUtil -hashfile codecov.exe SHA256)[1], "codecov.exe") -join " ") -DifferenceObject $(Get-Content codecov.exe.SHA256SUM)).length -eq 0) { echo "SHASUM verified" } Else {exit 1}
-
- Write-Host -Foreground Green "Uploading to codecov..."
-
- .\codecov.exe --dir "Artifacts/Coverage" -t "$env:CODECOV_TOKEN" --build "$(Build.BuildNumber)"
-
- Write-Host -Foreground Green "✅ Uploaded to codecov."
- pwsh: true
-
- - publish: $(Build.SourcesDirectory)/Artifacts
- displayName: 'Publish Artifacts'
- artifact: 'Artifacts'
-
- - task: CopyFiles@2
- displayName: Copy nugets to staging
- inputs:
- SourceFolder: '$(Build.SourcesDirectory)/Artifacts'
- Contents: |
- **/*.nupkg
- **/*.snupkg
- TargetFolder: '$(Build.ArtifactStagingDirectory)'
- flattenFolders: true
- preserveTimestamp: true
- retryCount: '3'
- ignoreMakeDirErrors: true
-
- - task: PublishPipelineArtifact@1
- displayName: Upload nugets to pipeline
- inputs:
- targetPath: '$(Build.ArtifactStagingDirectory)'
- artifact: 'nugets'
- publishLocation: 'pipeline'
-
-- stage: Publish
- dependsOn: Build
- jobs:
- - deployment: Publish
- displayName: Publish nugets
- environment: 'Publish'
- strategy:
- runOnce:
- deploy:
- steps:
- - task: DownloadPipelineArtifact@2
- displayName: Download nugets from pipeline
- inputs:
- buildType: 'current'
- artifactName: 'nugets'
- targetPath: '$(Build.ArtifactStagingDirectory)'
-
- - task: Bash@3
- displayName: 'Push to nuget.org'
- env:
- NUGET_ORG_APIKEY: '$(NUGET_ORG_APIKEY)'
- inputs:
- targetType: 'inline'
- script: 'dotnet nuget push "*.nupkg" --skip-duplicate --api-key $NUGET_ORG_APIKEY --source https://api.nuget.org/v3/index.json'
- workingDirectory: '$(Build.ArtifactStagingDirectory)'
-
- - task: NuGetCommand@2
- displayName: Push to internal NuGet feed
- inputs:
- command: 'push'
- packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg'
- nuGetFeedType: 'internal'
- publishVstsFeed: 'fee4c64f-3e49-4618-9ea4-5a3167257c37/989275f4-a952-4abd-ae82-2e7a0cb97b9b'
- allowPackageConflicts: true
+steps:
+- checkout: none
+- script: echo "Azure Pipelines is disabled for v6. Use the GitHub Actions CI workflow."
+ displayName: GitHub Actions migration notice