diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 0eae325..6979242 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,32 +3,39 @@
"isRoot": true,
"tools": {
"powershell": {
- "version": "7.5.1",
+ "version": "7.5.4",
"commands": [
"pwsh"
],
"rollForward": false
},
"dotnet-coverage": {
- "version": "17.14.2",
+ "version": "18.3.1",
"commands": [
"dotnet-coverage"
],
"rollForward": false
},
"nbgv": {
- "version": "3.7.115",
+ "version": "3.9.50",
"commands": [
"nbgv"
],
"rollForward": false
},
"docfx": {
- "version": "2.78.3",
+ "version": "2.78.4",
"commands": [
"docfx"
],
"rollForward": false
+ },
+ "nerdbank.dotnetrepotools": {
+ "version": "1.0.92",
+ "commands": [
+ "repo"
+ ],
+ "rollForward": false
}
}
}
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index cd1285d..64f23a9 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,5 +1,5 @@
# Refer to https://hub.docker.com/_/microsoft-dotnet-sdk for available versions
-FROM mcr.microsoft.com/dotnet/sdk:9.0.301-noble@sha256:4f50505b5344e9d8a76805d71bb4ba76da6b01656e17a66a8ce1e4c4dfaaec12
+FROM mcr.microsoft.com/dotnet/sdk:10.0.101@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190
# Installing mono makes `dotnet test` work without errors even for net472.
# But installing it takes a long time, so it's excluded by default.
diff --git a/.github/actions/publish-artifacts/action.yaml b/.github/actions/publish-artifacts/action.yaml
index 1f345fe..e024682 100644
--- a/.github/actions/publish-artifacts/action.yaml
+++ b/.github/actions/publish-artifacts/action.yaml
@@ -14,46 +14,46 @@ runs:
- name: 📢 Upload project.assets.json files
if: always()
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: projectAssetsJson-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/projectAssetsJson
continue-on-error: true
- name: 📢 Upload variables
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: variables-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/Variables
continue-on-error: true
- name: 📢 Upload build_logs
if: always()
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: build_logs-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/build_logs
continue-on-error: true
- name: 📢 Upload testResults
if: always()
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: testResults-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/testResults
continue-on-error: true
- name: 📢 Upload coverageResults
if: always()
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: coverageResults-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/coverageResults
continue-on-error: true
- name: 📢 Upload symbols
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: symbols-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/symbols
continue-on-error: true
- name: 📢 Upload deployables
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: deployables-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/deployables
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..0859350
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,23 @@
+# Copilot instructions for this repository
+
+## High level guidance
+
+* Review the `CONTRIBUTING.md` file for instructions to build and test the software.
+* Set the `NBGV_GitEngine` environment variable to `Disabled` before running any `dotnet` or `msbuild` commands.
+
+## Software Design
+
+* Design APIs to be highly testable, and all functionality should be tested.
+* Avoid introducing binary breaking changes in public APIs of projects under `src` unless their project files have `IsPackable` set to `false`.
+
+## Testing
+
+* There should generally be one test project (under the `test` directory) per shipping project (under the `src` directory). Test projects are named after the project being tested with a `.Test` suffix.
+* Tests should use the Xunit testing framework.
+* Some tests are known to be unstable. When running tests, you should skip the unstable ones by running `dotnet test --filter "TestCategory!=FailsInCloudTest"`.
+
+## Coding style
+
+* Honor StyleCop rules and fix any reported build warnings *after* getting tests to pass.
+* In C# files, use namespace *statements* instead of namespace *blocks* for all new files.
+* Add API doc comments to all new public and internal members.
diff --git a/.github/renovate.json b/.github/renovate.json
index c8b723c..79dba1e 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -1,6 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": ["config:best-practices"],
+ "extends": ["config:best-practices","helpers:pinGitHubActionDigestsToSemver"],
"labels": ["dependencies"],
"packageRules": [
{
@@ -11,6 +11,10 @@
"matchPackageNames": ["xunit*"],
"groupName": "xunit"
},
+ {
+ "matchPackageNames": ["Microsoft.Testing.Extensions.*"],
+ "groupName": "Microsoft Testing Platform"
+ },
{
"matchDatasources": ["dotnet-version", "docker"],
"matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"],
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 71a2714..bb1063b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -12,7 +12,6 @@ on:
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
BUILDCONFIGURATION: Release
- # codecov_token: 4dc9e7e2-6b01-4932-a180-847b52b43d35 # Get a new one from https://codecov.io/
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages/
jobs:
@@ -24,12 +23,12 @@ jobs:
fail-fast: false
matrix:
os:
- - ubuntu-22.04
- # - macos-14
- # - windows-2022
+ - ubuntu-24.04
+ # - macOS-15
+ # - windows-2025
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
- name: ⚙ Install prerequisites
@@ -64,18 +63,20 @@ jobs:
uses: ./.github/actions/publish-artifacts
if: cancelled() == false
- name: 📢 Publish code coverage results to codecov.io
- run: ./tools/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}"
+ run: |
+ if ('${{ secrets.CODECOV_TOKEN }}') {
+ ./tools/publish-CodeCov.ps1 -CodeCovToken '${{ secrets.CODECOV_TOKEN }}' -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}"
+ }
shell: pwsh
timeout-minutes: 3
continue-on-error: true
- if: env.codecov_token != ''
docs:
name: 📃 Docs
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: 🔗 Markup Link Checker (mlc)
- uses: becheran/mlc@88c9db09b8dabab813a2edd13f955b36aa73657a # v0.22.0
+ uses: becheran/mlc@7ec24825cefe0c9c8c6bac48430e1f69e3ec356e # v1.2.0
with:
- args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx
+ args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx -i https://www.npmjs.com/package/*,https://get.dot.net/
diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml
index 053f56e..ebd5388 100644
--- a/.github/workflows/copilot-setup-steps.yml
+++ b/.github/workflows/copilot-setup-steps.yml
@@ -26,7 +26,7 @@ jobs:
# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
- name: ⚙ Install prerequisites
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 0a8f821..b1ba568 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -5,13 +5,6 @@ on:
branches:
- main
-# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
-permissions:
- actions: read
- pages: write
- id-token: write
- contents: read
-
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
@@ -20,12 +13,18 @@ concurrency:
jobs:
publish-docs:
+ # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+ permissions:
+ actions: read
+ pages: write
+ id-token: write
+ contents: read
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
- name: ⚙ Install prerequisites
@@ -35,10 +34,10 @@ jobs:
name: 📚 Generate documentation
- name: Upload artifact
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
+ uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4
with:
path: docfx/_site
- name: Deploy to GitHub Pages
id: deployment
- uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
+ uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml
index 7d0a67a..0b111a6 100644
--- a/.github/workflows/libtemplate-update.yml
+++ b/.github/workflows/libtemplate-update.yml
@@ -17,7 +17,7 @@ jobs:
contents: write
pull-requests: write
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e37811d..51b1138 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -11,22 +11,14 @@ on:
run-name: ${{ github.ref_name }}
-permissions:
- actions: read
- contents: write
-
jobs:
release:
runs-on: ubuntu-24.04
+ permissions:
+ actions: read # Required to download artifacts
+ contents: write # Upload artifacts to Release
+ id-token: write # Required for NuGet CLI Login
steps:
- - name: ⚙️ Initialization
- shell: pwsh
- run: |
- if ('${{ secrets.NUGET_API_KEY }}') {
- Write-Host "NUGET_API_KEY secret detected. NuGet packages will be pushed."
- echo "NUGET_API_KEY_DEFINED=true" >> $env:GITHUB_ENV
- }
-
- name: 🔎 Search for build of ${{ github.ref }}
shell: pwsh
id: findrunid
@@ -65,13 +57,22 @@ jobs:
Echo "runid=$runid" >> $env:GITHUB_OUTPUT
- name: 🔻 Download deployables artifacts
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
+ uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: deployables-Linux
path: ${{ runner.temp }}/deployables
run-id: ${{ steps.findrunid.outputs.runid }}
github-token: ${{ github.token }}
+ - name: 🪪 Authorize NuGet package push
+ uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544 # v1.1.0
+ id: nuget-login
+ with:
+ user: ${{ secrets.NUGET_USER }}
+
+ - name: 🚀 Push NuGet packages
+ run: dotnet nuget push ${{ runner.temp }}/deployables/*.nupkg --source https://api.nuget.org/v3/index.json -k '${{ steps.nuget-login.outputs.NUGET_API_KEY }}'
+
- name: 💽 Upload artifacts to release
shell: pwsh
if: ${{ github.event_name == 'release' && github.event.release.assets_url != '' }}
@@ -82,7 +83,3 @@ jobs:
Write-Host "Uploading $($_.Name) to release..."
gh release -R ${{ github.repository }} upload "${{ github.ref_name }}" $_.FullName
}
-
- - name: 🚀 Push NuGet packages
- run: dotnet nuget push ${{ runner.temp }}/deployables/*.nupkg --source https://api.nuget.org/v3/index.json -k '${{ secrets.NUGET_API_KEY }}'
- if: ${{ env.NUGET_API_KEY_DEFINED == 'true' }}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4281f29..d4322a7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,7 +39,7 @@ This repository can be built on Windows, Linux, and OSX.
Building, testing, and packing this repository can be done by using the standard dotnet CLI commands (e.g. `dotnet build`, `dotnet test`, `dotnet pack`, etc.).
-[pwsh]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell?view=powershell-6
+[pwsh]: https://learn.microsoft.com/powershell/scripting/install/installing-powershell
## Releases
@@ -53,9 +53,9 @@ Push the tag.
When your repo is hosted by GitHub and you are using GitHub Actions, you should create a GitHub Release using the standard GitHub UI.
Having previously used `nbgv tag` and pushing the tag will help you identify the precise commit and name to use for this release.
-After publishing the release, the `.github\workflows\release.yml` workflow will be automatically triggered, which will:
+After publishing the release, the `.github/workflows/release.yml` workflow will be automatically triggered, which will:
-1. Find the most recent `.github\workflows\build.yml` GitHub workflow run of the tagged release.
+1. Find the most recent `.github/workflows/build.yml` GitHub workflow run of the tagged release.
1. Upload the `deployables` artifact from that workflow run to your GitHub Release.
1. If you have `NUGET_API_KEY` defined as a secret variable for your repo or org, any nuget packages in the `deployables` artifact will be pushed to nuget.org.
@@ -66,7 +66,7 @@ Trigger the pipeline by adding the `auto-release` tag on a run of your main `azu
## Tutorial and API documentation
-API and hand-written docs are found under the `docfx/` directory. and are built by [docfx](https://dotnet.github.io/docfx/).
+API and hand-written docs are found under the `docfx/` directory and are built by [docfx](https://dotnet.github.io/docfx/).
You can make changes and host the site locally to preview them by switching to that directory and running the `dotnet docfx --serve` command.
After making a change, you can rebuild the docs site while the localhost server is running by running `dotnet docfx` again from a separate terminal.
@@ -88,11 +88,11 @@ If Renovate is not creating pull requests when you expect it to, check that the
### Maintaining your repo based on this template
The best way to keep your repo in sync with Library.Template's evolving features and best practices is to periodically merge the template into your repo:
-`
+
```ps1
git fetch
git checkout origin/main
-.\tools\MergeFrom-Template.ps1
+./tools/MergeFrom-Template.ps1
# resolve any conflicts, then commit the merge commit.
git push origin -u HEAD
```
diff --git a/Directory.Build.props b/Directory.Build.props
index e7fe524..df42d74 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -14,14 +14,17 @@
preview
true
true
+ true
true
+
+ true
+
true
-
- false
+ true
$(MSBuildThisFileDirectory)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ca34c1b..bd3dba5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,18 +4,21 @@
true
true
+ 2.0.2
-
-
+
+
-
-
-
+
+
+
+
+
@@ -24,7 +27,7 @@
-
+
diff --git a/README.md b/README.md
index 8a0a0eb..6dc0a1f 100644
--- a/README.md
+++ b/README.md
@@ -51,9 +51,9 @@ The raw data for the boundaries comes from the [Timezone Boundary Builder](https
#### Included data files
|`TimeZoneData`|`maxLevel`|`minRingDistance`|Size [KB]|GeoHash length|Error [km]|
|---|---|---|---|---|---|
-|Small|20|5.000|63|4|20|
-|Medium|25|600|310|5|2.4|
-|Large|30|152|1.579|6|0.61|
+|Small|20|5,000|64|4|20|
+|Medium|25|600|313|5|2.4|
+|Large|30|152|1,592|6|0.61|
#### Creating your own data file
Install the tool in your project or as global tool and run it with `dotnet tz-build`.
```batch
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 2dfbef7..9ba2847 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -26,7 +26,6 @@ parameters:
variables:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
BuildConfiguration: Release
- #codecov_token: # Get a new one from https://codecov.io/
#ci_feed: # Azure Artifacts feed URL
NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages/
diff --git a/azure-pipelines/Merge-CodeCoverage.ps1 b/azure-pipelines/Merge-CodeCoverage.ps1
index 308f575..169bb17 100644
--- a/azure-pipelines/Merge-CodeCoverage.ps1
+++ b/azure-pipelines/Merge-CodeCoverage.ps1
@@ -28,6 +28,7 @@ try {
if ($reports) {
$reports |% { $_.FullName } |% {
# In addition to replacing {reporoot}, we also normalize on one kind of slash so that the report aggregates data for a file whether data was collected on Windows or not.
+ Write-Verbose "Processing $_"
$xml = [xml](Get-Content -LiteralPath $_)
$xml.coverage.packages.package.classes.class |? { $_.filename} |% {
$_.filename = $_.filename.Replace('{reporoot}', $RepoRoot).Replace([IO.Path]::AltDirectorySeparatorChar, [IO.Path]::DirectorySeparatorChar)
diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml
index 5c106ad..7d808ed 100644
--- a/azure-pipelines/build.yml
+++ b/azure-pipelines/build.yml
@@ -2,7 +2,7 @@ parameters:
- name: windowsPool
type: object
default:
- vmImage: windows-2022
+ vmImage: windows-2025
- name: includeMacOS
type: boolean
- name: RunTests
@@ -28,7 +28,7 @@ jobs:
- job: Linux
pool:
- vmImage: Ubuntu-22.04
+ vmImage: ubuntu-24.04
steps:
- checkout: self
fetchDepth: 0 # avoid shallow clone so nbgv can do its work.
@@ -46,7 +46,7 @@ jobs:
- job: macOS
condition: ${{ parameters.includeMacOS }}
pool:
- vmImage: macOS-14
+ vmImage: macOS-15
steps:
- checkout: self
fetchDepth: 0 # avoid shallow clone so nbgv can do its work.
diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml
index 30bb410..9a572af 100644
--- a/azure-pipelines/dotnet.yml
+++ b/azure-pipelines/dotnet.yml
@@ -20,11 +20,14 @@ steps:
displayName: 📢 Publish artifacts
condition: succeededOrFailed()
-- ${{ if and(ne(variables['codecov_token'], ''), parameters.RunTests) }}:
+- ${{ if parameters.RunTests }}:
- powershell: |
$ArtifactStagingFolder = & "tools/Get-ArtifactsStagingDirectory.ps1"
$CoverageResultsFolder = Join-Path $ArtifactStagingFolder "coverageResults-$(Agent.JobName)"
- tools/publish-CodeCov.ps1 -CodeCovToken "$(codecov_token)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)"
+ tools/publish-CodeCov.ps1 -CodeCovToken "$(CODECOV_TOKEN)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)"
displayName: 📢 Publish code coverage results to codecov.io
timeoutInMinutes: 3
continueOnError: true
+ # Set the CODECOV_TOKEN variable in your Azure Pipeline to enable code coverage reporting
+ # Get a token from https://codecov.io/
+ condition: and(succeeded(), ne(variables['CODECOV_TOKEN'], ''))
diff --git a/azurepipelines-coverage.yml b/azurepipelines-coverage.yml
index 0cd5dad..e2dd1f5 100644
--- a/azurepipelines-coverage.yml
+++ b/azurepipelines-coverage.yml
@@ -1,4 +1,4 @@
-# https://learn.microsoft.com/azure/devops/pipelines/test/codecoverage-for-pullrequests?view=azure-devops
+# https://learn.microsoft.com/azure/devops/pipelines/test/codecoverage-for-pullrequests
coverage:
status:
comments: on # add comment to PRs reporting diff in coverage of modified files
diff --git a/global.json b/global.json
index 5f0c3cc..a0ec2d8 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,10 @@
{
"sdk": {
- "version": "10.0.100-preview.5.25277.114",
+ "version": "10.0.101",
"rollForward": "patch",
"allowPrerelease": false
+ },
+ "test": {
+ "runner": "Microsoft.Testing.Platform"
}
}
diff --git a/src/TZFinder.Builder/Context.cs b/src/TZFinder.Builder/Context.cs
index 682c506..ebde46b 100644
--- a/src/TZFinder.Builder/Context.cs
+++ b/src/TZFinder.Builder/Context.cs
@@ -58,9 +58,6 @@ public class Context : BuilderContext
///
public TimeZoneBuilderTree? TimeZoneTree { get; set; }
- private Context(CancellationToken cancellationToken) : base(cancellationToken)
- { }
-
///
/// Runs the builder.
///
@@ -108,7 +105,7 @@ public static async Task CreateAndRunAsync(
string sourceFileName = includeEtc ? "timezones-with-oceans.geojson" : "timezones.geojson";
FileResource timeZoneDataFile = new(Path.Combine(releasePath, $"{maxLevel}_{minRingDistance}_{(includeEtc ? "Etc" : "NoEtc")}_{TZLookup.DataFileName}"));
- Context context = new(cancellationToken)
+ Context context = new()
{
DownloadSource = new DownloadableResource(new Uri($"https://github.com/{SourceRepository}/releases/download/{release}/{sourceFileName}.zip")),
SourceFile = new FileResource(Path.Combine(releasePath, sourceFileName)),
@@ -130,7 +127,8 @@ await context.RunAsync(
[
new MemoryInfo(),
new GCTimeInfo(),
- ]);
+ ],
+ cancellationToken);
Console.WriteLine();
if (!force && File.Exists(outputPath))
diff --git a/src/TZFinder.Builder/TimeZoneIndex8.cs b/src/TZFinder.Builder/TimeZoneIndex8.cs
index a793fe4..6fe263f 100644
--- a/src/TZFinder.Builder/TimeZoneIndex8.cs
+++ b/src/TZFinder.Builder/TimeZoneIndex8.cs
@@ -36,16 +36,17 @@ public struct TimeZoneIndex8
///
/// Adds a time zone index to the structure.
///
- /// The time zone index to add.
+ /// The time zone index to add.
/// Thrown when the structure is full.
- public void Add(short index)
+ public void Add(short value)
{
for (int i = 0; i < Length; i++)
{
- if (this[i] == index) return;
- if (this[i] == 0)
+ ref short index = ref this[i];
+ if (index == value) return;
+ if (index == 0)
{
- this[i] = index;
+ index = value;
return;
}
}
diff --git a/src/TZFinder/data/20_5000_NoEtc_TimeZoneData.bin b/src/TZFinder/data/20_5000_NoEtc_TimeZoneData.bin
index 642479b..ab44455 100644
Binary files a/src/TZFinder/data/20_5000_NoEtc_TimeZoneData.bin and b/src/TZFinder/data/20_5000_NoEtc_TimeZoneData.bin differ
diff --git a/src/TZFinder/data/25_600_NoEtc_TimeZoneData.bin b/src/TZFinder/data/25_600_NoEtc_TimeZoneData.bin
index 6e5e945..bc45212 100644
Binary files a/src/TZFinder/data/25_600_NoEtc_TimeZoneData.bin and b/src/TZFinder/data/25_600_NoEtc_TimeZoneData.bin differ
diff --git a/src/TZFinder/data/30_152_NoEtc_TimeZoneData.bin b/src/TZFinder/data/30_152_NoEtc_TimeZoneData.bin
index df2c28a..cb84033 100644
Binary files a/src/TZFinder/data/30_152_NoEtc_TimeZoneData.bin and b/src/TZFinder/data/30_152_NoEtc_TimeZoneData.bin differ
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index 6c7aa71..2b5b542 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -5,6 +5,7 @@
false
true
+ true
diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets
index 9f32cd0..3758bb8 100644
--- a/test/Directory.Build.targets
+++ b/test/Directory.Build.targets
@@ -1,5 +1,11 @@
+
+
+
+
+
+
diff --git a/test/TZFinder.Tests/TZFinder.Tests.csproj b/test/TZFinder.Tests/TZFinder.Tests.csproj
index 7db8b39..44e9307 100644
--- a/test/TZFinder.Tests/TZFinder.Tests.csproj
+++ b/test/TZFinder.Tests/TZFinder.Tests.csproj
@@ -20,9 +20,7 @@
-
-
-
+
diff --git a/tools/Get-NuGetTool.ps1 b/tools/Get-NuGetTool.ps1
index 8a3b9ee..bed0cba 100644
--- a/tools/Get-NuGetTool.ps1
+++ b/tools/Get-NuGetTool.ps1
@@ -6,7 +6,7 @@
#>
Param(
[Parameter()]
- [string]$NuGetVersion='6.12.2'
+ [string]$NuGetVersion='6.14.0'
)
$toolsPath = & "$PSScriptRoot\Get-TempToolsPath.ps1"
diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1
index 402b430..590581e 100644
--- a/tools/Install-DotNetSdk.ps1
+++ b/tools/Install-DotNetSdk.ps1
@@ -125,14 +125,14 @@ Function Get-InstallerExe(
}
if ($TypedVersion.Build -eq -1) {
- $versionInfo = -Split (Invoke-WebRequest -Uri "https://dotnetcli.blob.core.windows.net/dotnet/$sku/$Version/latest.version" -UseBasicParsing)
+ $versionInfo = -Split (Invoke-WebRequest -Uri "https://builds.dotnet.microsoft.com/dotnet/$sku/$Version/latest.version" -UseBasicParsing)
$Version = $versionInfo[-1]
}
$majorMinor = "$($TypedVersion.Major).$($TypedVersion.Minor)"
$ReleasesFile = Join-Path $DotNetInstallScriptRoot "$majorMinor\releases.json"
if (!(Test-Path $ReleasesFile)) {
- Get-FileFromWeb -Uri "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/$majorMinor/releases.json" -OutDir (Split-Path $ReleasesFile) | Out-Null
+ Get-FileFromWeb -Uri "https://builds.dotnet.microsoft.com/dotnet/release-metadata/$majorMinor/releases.json" -OutDir (Split-Path $ReleasesFile) | Out-Null
}
$releases = Get-Content $ReleasesFile | ConvertFrom-Json
@@ -197,7 +197,7 @@ if ($InstallLocality -eq 'machine') {
$restartRequired = $false
$sdks |% {
if ($_.Version) { $version = $_.Version } else { $version = $_.Channel }
- if ($PSCmdlet.ShouldProcess(".NET SDK $_", "Install")) {
+ if ($PSCmdlet.ShouldProcess(".NET SDK $version ($arch)", "Install")) {
Install-DotNet -Version $version -Architecture $arch
$restartRequired = $restartRequired -or ($LASTEXITCODE -eq 3010)
@@ -281,10 +281,10 @@ if ($IncludeX86) {
}
if ($IsMacOS -or $IsLinux) {
- $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/0b09de9bc136cacb5f849a6957ebd4062173c148/src/dotnet-install.sh"
+ $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/a3fbd0fd625032bac207f1f590e5353fe26faa59/src/dotnet-install.sh"
$DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.sh"
} else {
- $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/0b09de9bc136cacb5f849a6957ebd4062173c148/src/dotnet-install.ps1"
+ $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/a3fbd0fd625032bac207f1f590e5353fe26faa59/src/dotnet-install.ps1"
$DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.ps1"
}
@@ -306,7 +306,7 @@ $global:LASTEXITCODE = 0
$sdks |% {
if ($_.Version) { $parameters = '-Version', $_.Version } else { $parameters = '-Channel', $_.Channel }
- if ($PSCmdlet.ShouldProcess(".NET SDK $_", "Install")) {
+ if ($PSCmdlet.ShouldProcess(".NET SDK $_ ($arch)", "Install")) {
$anythingInstalled = $true
Invoke-Expression -Command "$DotNetInstallScriptPathExpression $parameters -Architecture $arch -InstallDir $DotNetInstallDir $switches"
diff --git a/tools/Install-NuGetPackage.ps1 b/tools/Install-NuGetPackage.ps1
new file mode 100644
index 0000000..3c11b0f
--- /dev/null
+++ b/tools/Install-NuGetPackage.ps1
@@ -0,0 +1,63 @@
+<#
+.SYNOPSIS
+ Installs a NuGet package.
+.PARAMETER PackageID
+ The Package ID to install.
+.PARAMETER Version
+ The version of the package to install. If unspecified, the latest stable release is installed.
+.PARAMETER Source
+ The package source feed to find the package to install from.
+.PARAMETER Prerelease
+ Include prerelease packages when searching for the latest version.
+.PARAMETER ExcludeVersion
+ Installs the package without adding the version to the folder name.
+.PARAMETER DirectDownload
+ Bypass the local cache when downloading packages.
+.PARAMETER PackagesDir
+ The directory to install the package to. By default, it uses the Packages folder at the root of the repo.
+.PARAMETER ConfigFile
+ The nuget.config file to use. By default, it uses :/nuget.config.
+.OUTPUTS
+ System.String. The path to the installed package.
+#>
+[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Low')]
+Param(
+ [Parameter(Position=1,Mandatory=$true)]
+ [string]$PackageId,
+ [Parameter()]
+ [string]$Version,
+ [Parameter()]
+ [string]$Source,
+ [Parameter()]
+ [switch]$Prerelease,
+ [Parameter()]
+ [switch]$ExcludeVersion,
+ [Parameter()]
+ [switch]$DirectDownload,
+ [Parameter()]
+ [string]$PackagesDir="$PSScriptRoot\..\packages",
+ [Parameter()]
+ [string]$ConfigFile="$PSScriptRoot\..\nuget.config",
+ [Parameter()]
+ [ValidateSet('Quiet','Normal','Detailed')]
+ [string]$Verbosity='normal'
+)
+
+$nugetPath = & "$PSScriptRoot\Get-NuGetTool.ps1"
+
+Write-Verbose "Installing $PackageId..."
+$nugetArgs = "Install",$PackageId,"-OutputDirectory",$PackagesDir,'-ConfigFile',$ConfigFile
+if ($Version) { $nugetArgs += "-Version",$Version }
+if ($Source) { $nugetArgs += "-FallbackSource",$Source }
+if ($Prerelease) { $nugetArgs += "-Prerelease" }
+if ($ExcludeVersion) { $nugetArgs += '-ExcludeVersion' }
+if ($DirectDownload) { $nugetArgs += '-DirectDownload' }
+$nugetArgs += '-Verbosity',$Verbosity
+
+if ($PSCmdlet.ShouldProcess($PackageId, 'nuget install')) {
+ $p = Start-Process $nugetPath $nugetArgs -NoNewWindow -Wait -PassThru
+ if ($null -ne $p.ExitCode -and $p.ExitCode -ne 0) { throw }
+}
+
+# Provide the path to the installed package directory to our caller.
+Write-Output (Get-ChildItem "$PackagesDir\$PackageId.*")[0].FullName
diff --git a/tools/artifacts/Variables.ps1 b/tools/artifacts/Variables.ps1
index 7a320c7..c4d9766 100644
--- a/tools/artifacts/Variables.ps1
+++ b/tools/artifacts/Variables.ps1
@@ -26,7 +26,7 @@ Get-ChildItem "$PSScriptRoot/../variables" |% {
if ($value) {
# We got something, so wrap it with quotes so it's treated like a literal value.
- $value = "'$value'"
+ $value = "'" + $value.Replace("'", "''") + "'"
}
}
diff --git a/tools/artifacts/coverageResults.ps1 b/tools/artifacts/coverageResults.ps1
index 8c68216..1aadbb7 100644
--- a/tools/artifacts/coverageResults.ps1
+++ b/tools/artifacts/coverageResults.ps1
@@ -1,25 +1,26 @@
-$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
+$RepoRoot = Resolve-Path "$PSScriptRoot\..\.."
-$coverageFiles = @(Get-ChildItem "$RepoRoot/test/*.cobertura.xml" -Recurse | Where {$_.FullName -notlike "*/In/*" -and $_.FullName -notlike "*\In\*" })
+$coverageFilesUnderRoot = @(Get-ChildItem "$RepoRoot/*.cobertura.xml" -Recurse | Where-Object {$_.FullName -notlike "*/In/*" -and $_.FullName -notlike "*\In\*" })
+
+# Under MTP, coverage files are written directly to the artifacts output directory,
+# so we need to look there too.
+$ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1"
+$directTestLogs = Join-Path $ArtifactStagingFolder test_logs
+$coverageFilesUnderArtifacts = if (Test-Path $directTestLogs) { @(Get-ChildItem "$directTestLogs/*.cobertura.xml" -Recurse) } else { @() }
# Prepare code coverage reports for merging on another machine
-$repoRoot = $env:SYSTEM_DEFAULTWORKINGDIRECTORY
-if (!$repoRoot) { $repoRoot = $env:GITHUB_WORKSPACE }
-if ($repoRoot) {
- Write-Host "Substituting $repoRoot with `"{reporoot}`""
- $coverageFiles |% {
- $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($repoRoot), "{reporoot}" }
- Set-Content -LiteralPath $_ -Value $content -Encoding UTF8
- }
-} else {
- Write-Warning "coverageResults: Cloud build not detected. Machine-neutral token replacement skipped."
+Write-Host "Substituting $repoRoot with `"{reporoot}`""
+@($coverageFilesUnderRoot + $coverageFilesUnderArtifacts) |? { $_ }|% {
+ $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($repoRoot), "{reporoot}" }
+ Set-Content -LiteralPath $_ -Value $content -Encoding UTF8
}
if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return }
@{
+ $directTestLogs = $coverageFilesUnderArtifacts;
$RepoRoot = (
- $coverageFiles +
+ $coverageFilesUnderRoot +
(Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse)
);
}
diff --git a/tools/artifacts/testResults.ps1 b/tools/artifacts/testResults.ps1
index 5310fb5..a841967 100644
--- a/tools/artifacts/testResults.ps1
+++ b/tools/artifacts/testResults.ps1
@@ -4,7 +4,8 @@ Param(
$result = @{}
-$testRoot = Resolve-Path "$PSScriptRoot\..\..\test"
+$RepoRoot = Resolve-Path "$PSScriptRoot\..\.."
+$testRoot = Join-Path $RepoRoot test
$result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File)
$artifactStaging = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1"
diff --git a/tools/dotnet-test-cloud.ps1 b/tools/dotnet-test-cloud.ps1
index 02891d9..5d20481 100644
--- a/tools/dotnet-test-cloud.ps1
+++ b/tools/dotnet-test-cloud.ps1
@@ -25,6 +25,7 @@ Param(
$RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path
$ArtifactStagingFolder = & "$PSScriptRoot/Get-ArtifactsStagingDirectory.ps1"
+$OnCI = ($env:CI -or $env:TF_BUILD)
$dotnet = 'dotnet'
if ($x86) {
@@ -45,23 +46,68 @@ if ($x86) {
}
$testBinLog = Join-Path $ArtifactStagingFolder (Join-Path build_logs test.binlog)
-$testDiagLog = Join-Path $ArtifactStagingFolder (Join-Path test_logs diag.log)
+$testLogs = Join-Path $ArtifactStagingFolder test_logs
-& $dotnet test $RepoRoot `
- --no-build `
- -c $Configuration `
- --filter "TestCategory!=FailsInCloudTest" `
- --collect "Code Coverage;Format=cobertura" `
- --settings "$PSScriptRoot/test.runsettings" `
- --blame-hang-timeout 60s `
- --blame-crash `
- -bl:"$testBinLog" `
- --diag "$testDiagLog;TraceLevel=info" `
- --logger trx `
+$globalJson = Get-Content $PSScriptRoot/../global.json | ConvertFrom-Json
+$isMTP = $globalJson.test.runner -eq 'Microsoft.Testing.Platform'
+$extraArgs = @()
+$failedTests = 0
+
+if ($isMTP) {
+ if ($OnCI) { $extraArgs += '--no-progress' }
+
+ $dumpSwitches = @(
+ ,'--hangdump'
+ ,'--hangdump-timeout','120s'
+ ,'--crashdump'
+ )
+ $mtpArgs = @(
+ ,'--coverage'
+ ,'--coverage-output-format','cobertura'
+ ,'--diagnostic'
+ ,'--diagnostic-output-directory',$testLogs
+ ,'--diagnostic-verbosity','Information'
+ ,'--results-directory',$testLogs
+ ,'--report-trx'
+ )
+
+ & $dotnet test --solution $RepoRoot `
+ --no-build `
+ -c $Configuration `
+ -bl:"$testBinLog" `
+ --filter-not-trait 'TestCategory=FailsInCloudTest' `
+ --coverage-settings "$PSScriptRoot/test.runsettings" `
+ @mtpArgs `
+ @dumpSwitches `
+ @extraArgs
+ if ($LASTEXITCODE -ne 0) { $failedTests += 1 }
+
+ $trxFiles = Get-ChildItem -Recurse -Path $testLogs\*.trx
+} else {
+ $testDiagLog = Join-Path $ArtifactStagingFolder (Join-Path test_logs diag.log)
+ & $dotnet test $RepoRoot `
+ --no-build `
+ -c $Configuration `
+ --filter "TestCategory!=FailsInCloudTest" `
+ --collect "Code Coverage;Format=cobertura" `
+ --settings "$PSScriptRoot/test.runsettings" `
+ --blame-hang-timeout 60s `
+ --blame-crash `
+ -bl:"$testBinLog" `
+ --diag "$testDiagLog;TraceLevel=info" `
+ --logger trx `
+ @extraArgs
+ if ($LASTEXITCODE -ne 0) { $failedTests += 1 }
+
+ $trxFiles = Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx
+}
$unknownCounter = 0
-Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% {
- Copy-Item $_ -Destination $ArtifactStagingFolder/test_logs/
+$trxFiles |% {
+ New-Item $testLogs -ItemType Directory -Force | Out-Null
+ if (!($_.FullName.StartsWith($testLogs, [StringComparison]::OrdinalIgnoreCase))) {
+ Copy-Item $_ -Destination $testLogs
+ }
if ($PublishResults) {
$x = [xml](Get-Content -LiteralPath $_)
@@ -84,3 +130,7 @@ Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% {
Write-Host "##vso[results.publish type=VSTest;runTitle=$runTitle;publishRunAttachments=true;resultFiles=$_;failTaskOnFailedTests=true;testRunSystem=VSTS - PTR;]"
}
}
+
+if ($failedTests -ne 0) {
+ exit $failedTests
+}
diff --git a/version.json b/version.json
index 0085c75..2562eb6 100644
--- a/version.json
+++ b/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "1.0",
+ "version": "1.1",
"publicReleaseRefSpec": [
"^refs/heads/main$",
"^refs/heads/v\\d+(?:\\.\\d+)?$"