diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index ce63fad2..f61f6468 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -228,6 +228,18 @@ Available VS Code tasks (use via `run_task` tool):
```
+5. **Directory.Build.props**: Common MSBuild properties shared across all projects
+ (`TargetFramework`, `Nullable`, `ImplicitUsings`, `AnalysisLevel`, `AnalysisMode`,
+ `EnableNETAnalyzers`, `ArtifactsPath`, `IsPackable`, `ManagePackageVersionsCentrally`)
+ live here at the solution root. Only add a property to a `.csproj` when it is
+ specific to that project or requires an explicit override of the shared default.
+
+6. **Directory.Packages.props**: All NuGet package versions are centralised here via
+ `PackageVersion` items. Individual `.csproj` files use `PackageReference Include="..."`
+ with no `Version` attribute. Asset metadata (`PrivateAssets`, `IncludeAssets`) stays
+ in the `.csproj` `PackageReference` element. Use `VersionOverride` only when a project
+ genuinely requires a different version from the central default.
+
### Code Formatting Tools
1. **CSharpier**: Primary code formatter
diff --git a/.github/workflows/build-executable-task.yml b/.github/workflows/build-executable-task.yml
index 4b7a900b..9ea6dfd3 100644
--- a/.github/workflows/build-executable-task.yml
+++ b/.github/workflows/build-executable-task.yml
@@ -36,7 +36,7 @@ jobs:
run: |
dotnet publish ./Console/Console.csproj \
--runtime ${{ matrix.runtime }} \
- --output ${{ runner.temp }}/publish/${{ matrix.runtime }} \
+ -property:PublishDir=${{ runner.temp }}/publish/${{ matrix.runtime }}/ \
--configuration ${{ github.ref_name == 'main' && 'Release' || 'Debug' }} \
-property:PublishAot=false \
-property:Version=${{ needs.get-version.outputs.AssemblyVersion }} \
diff --git a/.github/workflows/build-library-task.yml b/.github/workflows/build-library-task.yml
index 53d4c28a..6bd1279b 100644
--- a/.github/workflows/build-library-task.yml
+++ b/.github/workflows/build-library-task.yml
@@ -40,7 +40,8 @@ jobs:
- name: Build library project step
run: |
dotnet build ./Library/Library.csproj \
- --output ${{ runner.temp }}/publish \
+ -property:OutputPath=${{ runner.temp }}/publish/ \
+ -property:PackageOutputPath=${{ runner.temp }}/publish/ \
--configuration ${{ github.ref_name == 'main' && 'Release' || 'Debug' }} \
-property:Version=${{ needs.get-version.outputs.AssemblyVersion }} \
-property:FileVersion=${{ needs.get-version.outputs.AssemblyFileVersion }} \
diff --git a/.github/workflows/run-periodic-codegen-app-pull-request.yml b/.github/workflows/run-periodic-codegen-app-pull-request.yml
index fcd687f1..a08284f6 100644
--- a/.github/workflows/run-periodic-codegen-app-pull-request.yml
+++ b/.github/workflows/run-periodic-codegen-app-pull-request.yml
@@ -1,23 +1,24 @@
-name: Run weekly CodeGen App and Pull Request action
-
-on:
- workflow_dispatch:
- schedule:
- # Run weekly on Thursdays at 02:00 UTC (PAT workflow runs on Mondays)
- - cron: '0 2 * * THU'
-
-concurrency:
- group: codegen-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
-
- run-codegen-app:
- name: Run codegen app and pull request job
- uses: ./.github/workflows/run-codegen-app-pull-request-task.yml
- secrets:
- CODEGEN_APP_ID: ${{ secrets.CODEGEN_APP_ID }}
- CODEGEN_APP_PRIVATE_KEY: ${{ secrets.CODEGEN_APP_PRIVATE_KEY }}
- permissions:
- contents: write
- pull-requests: write
+name: Run weekly CodeGen App and Pull Request action
+
+on:
+ workflow_dispatch:
+ schedule:
+ # Run weekly on Thursdays at 02:00 UTC (PAT workflow runs on Mondays)
+ - cron: '0 2 * * THU'
+
+concurrency:
+ # Workflow always checks out and targets main/codegen
+ group: codegen-main
+ cancel-in-progress: true
+
+jobs:
+
+ run-codegen-app:
+ name: Run codegen app and pull request job
+ uses: ./.github/workflows/run-codegen-app-pull-request-task.yml
+ secrets:
+ CODEGEN_APP_ID: ${{ secrets.CODEGEN_APP_ID }}
+ CODEGEN_APP_PRIVATE_KEY: ${{ secrets.CODEGEN_APP_PRIVATE_KEY }}
+ permissions:
+ contents: write
+ pull-requests: write
diff --git a/.github/workflows/run-periodic-codegen-pull-request.yml b/.github/workflows/run-periodic-codegen-pull-request.yml
index 701a7294..2c01b9c3 100644
--- a/.github/workflows/run-periodic-codegen-pull-request.yml
+++ b/.github/workflows/run-periodic-codegen-pull-request.yml
@@ -7,7 +7,8 @@ on:
- cron: '0 2 * * MON'
concurrency:
- group: codegen-${{ github.ref }}
+ # Workflow always checks out and targets main/codegen
+ group: codegen-main
cancel-in-progress: true
jobs:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index b4087235..1aab653f 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,51 +1,51 @@
-{
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Console Root",
- "type": "coreclr",
- "request": "launch",
- "preLaunchTask": ".Net Build",
- "program": "${workspaceFolder}/Console/bin/Debug/net10.0/Console.dll",
- "args": [
- "--loglevel=Debug",
- "--logfile=console.log",
- "--logfile-clear=true"
- ],
- "cwd": "${workspaceFolder}/Console/bin/Debug/net10.0",
- "console": "internalConsole",
- "stopAtEntry": false
- },
- {
- "name": "Console Test",
- "type": "coreclr",
- "request": "launch",
- "preLaunchTask": ".Net Build",
- "program": "${workspaceFolder}/Console/bin/Debug/net10.0/Console.dll",
- "args": [
- "--loglevel=Debug",
- "--logfile=console.log",
- "--logfile-clear=true",
- "test",
- "--test=test"
- ],
- "cwd": "${workspaceFolder}/Console/bin/Debug/net10.0",
- "console": "internalConsole",
- "stopAtEntry": false
- },
- {
- "name": "CodeGen",
- "type": "coreclr",
- "request": "launch",
- "preLaunchTask": ".Net Build",
- "program": "${workspaceFolder}/CodeGen/bin/Debug/net10.0/CodeGen.dll",
- "args": [
- "--codepath",
- "${workspaceFolder}/CodeGen"
- ],
- "cwd": "${workspaceFolder}/CodeGen/bin/Debug/net10.0",
- "console": "internalConsole",
- "stopAtEntry": false
- }
- ]
-}
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Console Root",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": ".Net Build",
+ "program": "${workspaceFolder}/.artifacts/bin/Console/Debug/Console.dll",
+ "args": [
+ "--loglevel=Debug",
+ "--logfile=console.log",
+ "--logfile-clear=true"
+ ],
+ "cwd": "${workspaceFolder}/.artifacts/bin/Console/Debug",
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": "Console Test",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": ".Net Build",
+ "program": "${workspaceFolder}/.artifacts/bin/Console/Debug/Console.dll",
+ "args": [
+ "--loglevel=Debug",
+ "--logfile=console.log",
+ "--logfile-clear=true",
+ "test",
+ "--test=test"
+ ],
+ "cwd": "${workspaceFolder}/.artifacts/bin/Console/Debug",
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": "CodeGen",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": ".Net Build",
+ "program": "${workspaceFolder}/.artifacts/bin/CodeGen/Debug/CodeGen.dll",
+ "args": [
+ "--codepath",
+ "${workspaceFolder}/CodeGen"
+ ],
+ "cwd": "${workspaceFolder}/.artifacts/bin/CodeGen/Debug",
+ "console": "internalConsole",
+ "stopAtEntry": false
+ }
+ ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index f8ae84ae..15724458 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -93,6 +93,28 @@
"clear": false
}
},
+ {
+ "label": ".Net Benchmark",
+ "type": "process",
+ "command": "dotnet",
+ "args": [
+ "run",
+ "--project",
+ "${workspaceFolder}/Benchmarks/Benchmarks.csproj",
+ "-c",
+ "Release",
+ "--",
+ "--artifacts",
+ "${workspaceFolder}/.artifacts/benchmarks"
+ ],
+ "problemMatcher": [
+ "$msCompile"
+ ],
+ "presentation": {
+ "showReuseMessage": false,
+ "clear": false
+ }
+ },
{
"label": ".Net Outdated Upgrade",
"type": "process",
diff --git a/AGENTS.md b/AGENTS.md
index e5283834..ac3a0281 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -24,6 +24,15 @@ For comprehensive coding standards and detailed conventions, refer to [`.github/
- `true`
- `latest-all`
+### Project Configuration
+
+- Common MSBuild properties (`TargetFramework`, `Nullable`, `ImplicitUsings`, `AnalysisLevel`, etc.)
+ live in `Directory.Build.props` at the solution root. Do not duplicate these in individual `.csproj`
+ files — only add a property to a `.csproj` when it is project-specific or overrides the shared default.
+- All NuGet package versions are centralised in `Directory.Packages.props`. `PackageReference` elements
+ in `.csproj` files must not include a `Version` attribute. Asset metadata (`PrivateAssets`,
+ `IncludeAssets`) stays in the `.csproj` `PackageReference` element.
+
### Development Environment
- Target latest .NET SDK (currently .NET 10 with C# 14)
diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj
index 84b9a369..ab6aa801 100644
--- a/Benchmarks/Benchmarks.csproj
+++ b/Benchmarks/Benchmarks.csproj
@@ -1,15 +1,10 @@
- latest-all
- true
- false
- enable
Exe
ptr727.ProjectTemplate.Benchmarks
- net10.0
-
+
diff --git a/Benchmarks/GlobalUsings.cs b/Benchmarks/GlobalUsings.cs
index 4603ccb2..15ff6fb5 100644
--- a/Benchmarks/GlobalUsings.cs
+++ b/Benchmarks/GlobalUsings.cs
@@ -1,3 +1,2 @@
-global using System;
global using BenchmarkDotNet.Attributes;
global using BenchmarkDotNet.Running;
diff --git a/CodeGen/CodeGen.cs b/CodeGen/CodeGen.cs
index a283a0e3..f1f6f050 100644
--- a/CodeGen/CodeGen.cs
+++ b/CodeGen/CodeGen.cs
@@ -7,7 +7,7 @@ internal static class CodeGen
internal static void Quote()
{
- const string dateTime = "2026-01-30T22:28:14.6290903Z";
+ const string dateTime = "2026-04-13T22:37:43.5686751Z";
Console.WriteLine($"{dateTime} : {QuoteOfTheDay}");
Log.Logger.Information("Quote of the Day: {DateTime} : {Quote}", dateTime, QuoteOfTheDay);
}
diff --git a/CodeGen/CodeGen.csproj b/CodeGen/CodeGen.csproj
index 8ff838f4..dc3bf7db 100644
--- a/CodeGen/CodeGen.csproj
+++ b/CodeGen/CodeGen.csproj
@@ -1,14 +1,9 @@
-
+
- latest-all
- true
1.0.0-pre
- false
- enable
Exe
false
ptr727.ProjectTemplate.CodeGen
- net10.0
1.0.0
@@ -17,10 +12,10 @@
true
-
-
-
-
-
+
+
+
+
+
diff --git a/CodeGen/GlobalUsings.cs b/CodeGen/GlobalUsings.cs
index 88aa9dac..85c42612 100644
--- a/CodeGen/GlobalUsings.cs
+++ b/CodeGen/GlobalUsings.cs
@@ -1,9 +1,3 @@
-global using System;
global using System.Collections.Frozen;
global using System.Globalization;
-global using System.IO;
-global using System.Linq;
-global using System.Net.Http;
-global using System.Threading;
-global using System.Threading.Tasks;
global using Serilog;
diff --git a/Console/Console.csproj b/Console/Console.csproj
index 1e00bf4e..bc4ea6ae 100644
--- a/Console/Console.csproj
+++ b/Console/Console.csproj
@@ -1,14 +1,9 @@
- latest-all
- true
1.0.0-pre
- false
- enable
Exe
false
ptr727.ProjectTemplate.Console
- net10.0
1.0.0
@@ -17,13 +12,13 @@
true
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/Console/GlobalUsings.cs b/Console/GlobalUsings.cs
index 89b47da4..17a0a025 100644
--- a/Console/GlobalUsings.cs
+++ b/Console/GlobalUsings.cs
@@ -1,10 +1,5 @@
-global using System;
global using System.Collections.Frozen;
global using System.Globalization;
-global using System.IO;
-global using System.Linq;
-global using System.Threading;
-global using System.Threading.Tasks;
global using Microsoft.Extensions.Logging;
global using Serilog;
global using Serilog.Events;
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 00000000..da26fe38
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,14 @@
+
+
+ net10.0
+ enable
+ enable
+ latest-all
+ All
+ true
+ true
+ $(MSBuildThisFileDirectory).artifacts
+ false
+ true
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 00000000..2f77ae1b
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Library/GlobalUsings.cs b/Library/GlobalUsings.cs
index 8aba491d..f52bcbcf 100644
--- a/Library/GlobalUsings.cs
+++ b/Library/GlobalUsings.cs
@@ -1,3 +1,2 @@
-global using System;
global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Logging.Abstractions;
diff --git a/Library/Library.csproj b/Library/Library.csproj
index 5623d4bf..6736346e 100644
--- a/Library/Library.csproj
+++ b/Library/Library.csproj
@@ -1,13 +1,11 @@
- latest-all
1.0.0.0
Pieter Viljoen
Pieter Viljoen
Pieter Viljoen
C# .NET template project
true
- true
1.0.0.0
true
true
@@ -15,7 +13,6 @@
1.0.0-pre
true
true
- enable
ptr727.ProjectTemplate.Library
MIT
https://github.com/ptr727/ProjectTemplate
@@ -26,19 +23,14 @@
https://github.com/ptr727/ProjectTemplate
ptr727.ProjectTemplate.Library
snupkg
- net10.0
1.0.0.0
true
-
-
+
+
diff --git a/Library/LogOptions.cs b/Library/LogOptions.cs
index 1de42803..9c63601c 100644
--- a/Library/LogOptions.cs
+++ b/Library/LogOptions.cs
@@ -1,5 +1,3 @@
-using System.Threading;
-
namespace ptr727.ProjectTemplate.Library;
///
diff --git a/Tests/GlobalUsings.cs b/Tests/GlobalUsings.cs
index 43d718ba..d85913ed 100644
--- a/Tests/GlobalUsings.cs
+++ b/Tests/GlobalUsings.cs
@@ -1,4 +1,2 @@
-global using System;
-global using System.Collections.Generic;
global using AwesomeAssertions;
global using Xunit;
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 36ada6b2..8c53010d 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -1,22 +1,17 @@
- latest-all
- true
- false
true
- enable
ptr727.ProjectTemplate.Tests
- net10.0
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+