ptr727.ProjectTemplate.Library
1.0.52
See the version list below for details.
dotnet add package ptr727.ProjectTemplate.Library --version 1.0.52
NuGet\Install-Package ptr727.ProjectTemplate.Library -Version 1.0.52
<PackageReference Include="ptr727.ProjectTemplate.Library" Version="1.0.52" />
<PackageVersion Include="ptr727.ProjectTemplate.Library" Version="1.0.52" />
<PackageReference Include="ptr727.ProjectTemplate.Library" />
paket add ptr727.ProjectTemplate.Library --version 1.0.52
#r "nuget: ptr727.ProjectTemplate.Library, 1.0.52"
#:package ptr727.ProjectTemplate.Library@1.0.52
#addin nuget:?package=ptr727.ProjectTemplate.Library&version=1.0.52
#tool nuget:?package=ptr727.ProjectTemplate.Library&version=1.0.52
ProjectTemplate
C# .NET project template.
Build and Distribution
- Source Code: GitHub - Source code, issues, discussions, and CI/CD pipelines.
- Versioned Releases: GitHub Releases - Version tagged source code and build artifacts.
- Docker Images: Docker Hub - Container images with all tools pre-installed.
- NuGet Packages: NuGet Packages - .NET libraries published to NuGet.org.
- PyPI Packages: PyPI Packages - Python library published to PyPI.org.
Build Status
Releases
Release Notes
Version: 1.0:
Summary:
- Something.
- And something else.
⚠️ Breaking Changes:
- Something.
- And something else.
See Release History for complete release notes and older versions.
Getting Started
Get started with ProjectTemplate in three easy steps:
⚠️ Important: Some important warning.
ℹ️ Note: Some interesting note.
Install ProjectTemplate:
- Do something.
Configure ProjectTemplate:
- Then something else.
Run ProjectTemplate:
Console --loglevel=Debug
See Installation for detailed setup instructions.
Table of Contents
- Build and Distribution
- Getting Started
- Table of Contents
- Use Cases
- Installation
- Configuration
- Usage
- Questions or Issues
- Development Environment Setup
- 3rd Party Tools
- License
- Template Project Setup
Use Cases
ℹ️ TL;DR: This widget is special because it does something special.
- It does something special.
- And it does something else special.
Installation
Choose an installation method based on your platform and requirements:
- Method 1 (Recommended): Easiest and most up-to-date option.
- ✅ Some good reason.
- ⚠️ Some not so good reason.
- ❌ Strong reason to avoid.
- Best for: Linux, NAS devices, servers, cross-platform deployments.
- Method 2: Custom configuration options.
- ✅ Some good reason.
- ⚠️ Some not so good reason.
- ❌ Strong reason to avoid.
- Best for: Specialized devices.
Configuration
⚠️ Important: The spinner setting must be configured before first use.
Required configuration:
- Set
footo something. - Set
barto something else.
Optional configuration:
- Set
advancedtospecial. - Some other custom option.
Usage
Console [global options] <command> [command options]
Command Quick Reference
| Command | Description | Notes |
|---|---|---|
| default | Default action when no command is specified | First time setup |
test |
Do something else useful | Some note |
--help |
Show help output | Use <command> --help for command specific help |
--version |
Show version output |
Use the --help option to get a list of all commands and global options.
To get help for a specific command run Console <command> --help.
Global Options
Global options apply to all commands:
| Option | Description | Default |
|---|---|---|
--logfile |
Debug log file | Optional |
--loglevel |
Debug log level | Default is Information |
--logfile-clear |
Clear log file at startup | Default is false |
General help:
>.\Console\bin\Debug\net10.0\Console --help
Description:
C# .NET console project
Usage:
Console [command] [options]
Options:
-l, --loglevel <Debug|Error|Fatal|Information|Verbose|Warning> Set the log level (default: Information). [default: Information]
-f, --logfile <logfile> Write logs to the specified file (optional).
-c, --logfile-clear Clear the log file before writing (default: false).
-?, -h, --help Show help and usage information
--version Show version information
Commands:
test Test command
Test Command
Test command options:
| Option | Description | Default |
|---|---|---|
--test |
Test options | Optional |
Test command help:
>.\Console\bin\Debug\net10.0\Console test --help
Description:
Test command
Usage:
Console test [options]
Options:
-t, --test <test> Test command option (optional).
-?, -h, --help Show help and usage information
-l, --loglevel <Debug|Error|Fatal|Information|Verbose|Warning> Set the log level (default: Information). [default: Information]
-f, --logfile <logfile> Write logs to the specified file (optional).
-c, --logfile-clear Clear the log file before writing (default: false).
Questions or Issues
For General Questions:
- Use the Discussions forum for general questions.
For Bug Reports:
- Ask in the Discussions forum if you are not sure if it is a bug.
- Check the existing Issues tracker for known problems.
- If the issue is unique and a bug, file it in Issues, and include all pertinent steps to reproduce the issue.
Development Environment Setup
The recommended setup is one of the per-language Dev Containers under .devcontainer/:
.devcontainer/dotnet/— .NET 10 SDK + GitHub CLI. Pair withDotNet.code-workspace..devcontainer/python/— Python 3.14 +uv+ GitHub CLI. Pair withPython.code-workspace.
Each container bind-mounts your SSH public key, allowed-signers file, and gh config from the host so commits sign correctly. gh is pre-authenticated when the host token is file-backed; macOS Keychain and Linux libsecret-backed tokens require an in-container gh auth login — see the credential-store nuance section.
Windows note: Python work is intentionally not supported on the Windows host. The Python extension caches the Linux-layout
PyPiLibrary/.venv/bin/pythonagainst a venv whose actual Windows path isPyPiLibrary\.venv\Scripts\python.exe, breaking Ruff. Use the python devcontainer.
Recommended (devcontainer):
- Complete host setup once per machine (git identity, SSH key, allowed_signers,
gh auth login, SSH commit signing). - Clone the repo, open the matching workspace (
DotNet.code-workspaceorPython.code-workspace) in VS Code with the Dev Containers extension, and run Reopen in Container — pick the language flavor. - The
postCreateCommandrunsdotnet tool restore(.NET container) or installsuvand runsuv sync(Python container). No git hooks are installed by default — see "Optional: enable git hooks locally" below.
Alternative (host install):
Install Developer Tools:
Install .NET SDK:
# Windows winget install Microsoft.DotNet.SDK.10 # Linux apt install dotnet-sdk-10.0Install Visual Studio Code:
# Windows winget install Microsoft.VisualStudioCodeInstall Visual Studio:
# Windows winget install Microsoft.VisualStudio.Community
Clone and Configure Project:
Clone the repository and initialize tools:
# Clone from CLI (or clone from VSCode) git clone -b main https://github.com/ptr727/[Project].git ./[Project] # Initialize dotnet tools cd ./[Project] dotnet tool restoreOpen
DotNet.code-workspace(orPython.code-workspace) in Visual Studio Code.Open
[Project].slnxin Visual Studio.
Optional: enable git hooks locally:
Hooks are not shipped with the template — CI is the lint backstop. Opt in per language if you want pre-commit checks locally.
For .NET work — install Husky.Net:
dotnet new tool-manifest # if no tool manifest exists yet dotnet tool install Husky dotnet husky install dotnet husky add pre-commit -c "dotnet csharpier check . && dotnet format style --verify-no-changes --severity=info"For Python work — install pre-commit:
uv tool install pre-commit pre-commit installSample
.pre-commit-config.yaml(the hooks shell intoPyPiLibrary/because the uv project — and therefore ruff/pyright and their configs — lives there, not at the repo root):repos: - repo: local hooks: - id: ruff-check name: ruff check entry: uv run --directory PyPiLibrary ruff check language: system files: ^PyPiLibrary/.*\.py$ pass_filenames: false - id: ruff-format name: ruff format entry: uv run --directory PyPiLibrary ruff format --check language: system files: ^PyPiLibrary/.*\.py$ pass_filenames: false - id: pyright name: pyright entry: uv run --directory PyPiLibrary pyright language: system files: ^PyPiLibrary/.*\.py$ pass_filenames: false
CI runs these same checks on every PR, so hooks are purely a local convenience.
3rd Party Tools
3rd Party tools used in this project:
- API Ninjas
- AwesomeAssertions
- Bring Your Own Badge
- Create Pull Request
- CSharpier
- GH Release
- Git Auto Commit
- GitHub Actions
- GitHub Dependabot
- Nerdbank.GitVersioning
- Serilog
- xUnit.Net
License
Licensed under the MIT License
Template Project Setup
Template - TODO List
- Configure git for SSH signing and SSH forwarding in dev containers — see docs/host-setup.md, docs/ssh-signing.md, and docs/devcontainer.md.
- Decide whether your project needs the .NET (
NuGetLibrary/) side, the Python (PyPiLibrary/) side, or both. Delete the unused folder and remove its references fromProjectTemplate.slnx,.github/dependabot.yml, and the corresponding.github/workflows/build-*-task.yml. - Start on Linux to avoid file permission issues when moving from Windows.
- Configure the Developer Environment.
- Open the project directory (not the workspace) in Visual Studio Code, and rename (Ctrl-Shift-H) all instances of
ProjectTemplateto[NewProject]in code. - Rename
DotNet.code-workspaceto[NewProject].code-workspaceandPython.code-workspaceto[NewProject]-Python.code-workspace, or delete the workspace for the language you don't need. RenameProjectTemplate.slnxto[NewProject].slnx. - Open the workspace file for the language you kept (
[NewProject].code-workspaceand/or[NewProject]-Python.code-workspace) in Visual Studio Code. - Delete any projects and associated actions that will not be used, update dependencies in actions to remove deleted actions.
- Rename projects to match the naming, update
.slnxand.csprojfiles, and update actions to match the naming. - Update the
namespacein.csand.csprojfiles to match the naming. - Update all ref-links in
README.mdto point to the naming. - Publish to GitHub from VSCode to create a new empty GitHub repository.
- Commit and push the
first-branch. - Edit and iterate only in
first-branchuntil ready to start with git history. - Setup
mainas the first permanent branch when ready. - Configure GitHub for the new repository.
- Follow the Branching Workflow.
- Delete the
Project Template Setupsection fromREADME.md.
Template - Developer Environment Setup
Template - Git Setup
⚠️ Prerequisites:
- Configure git for SSH signing — see SSH commit signing.
- Configure host prerequisites (SSH key,
allowed_signers,ghauth) — see host setup. - Configure SSH forwarding for dev containers — see devcontainer setup.
Setup new project from template:
# Clone the template project git clone -b main https://github.com/ptr727/ProjectTemplate.git ./[NewProject] # Reset git to start a new repo rm -r ./[NewProject]/.git cd ./[NewProject] git init -b first-branch # Init dotnet tools dotnet tool restore # Update dotnet tools dotnet tool update --all dotnet outdated --upgrade:promptSetup new project from scratch:
⚠️ Linux: Start configuration on Linux to avoid file permission issues.
# Init git mkdir ./[NewProject] cd ./[NewProject] git init -b first-branch # Init dotnet tools dotnet new tool-manifest dotnet tool install csharpier dotnet tool install dotnet-outdated-toolUse
first-branchfor all the initial project setup and testing.When ready, only when ready, create
mainbranch fromfirst-branchwith no history:# Create main branch with no history git checkout --orphan main git commit --allow-empty -m "temp" # Squash merge changes git merge --squash first-branch git commit -m "Initial import (squashed)" # Drop the temporary commit git reset --hard HEAD~1 # Delete first-branch git branch -D first-branch
Template - GitHub Setup
GitHub secrets setup:
Create a NuGet API Key.
- Save the Key as
NUGET_API_KEYin:- GitHub project security Settings / Secrets / Actions.
- GitHub project security Settings / Secrets / Dependabot.
- GitHub Local Actions Settings / Secrets.
- Save the Key as
Create a Docker Hub Personal Access Token.
- Save the PAT as
DOCKER_HUB_ACCESS_TOKENandDOCKER_HUB_USERNAMEin:- GitHub project security Settings / Secrets / Actions.
- GitHub project security Settings / Secrets / Dependabot.
- Save the PAT as
Create a GitHub App for the codegen and merge-bot workflows.
- App name:
ptr727-codegen. Bot user:ptr727-codegen[bot]. - Permissions required (repository scope):
- Contents: Read & write — push commits to the
codegenbranch and merge bot PRs. - Pull requests: Read & write — open, update, and merge pull requests.
- Metadata: Read-only (auto-required).
- Contents: Read & write — push commits to the
- Note the App ID from the app's settings page; generate a private key (downloads a
.pemfile). - Install the app on your account and grant it access to the repository. The app must be both created and installed — creating it alone is not sufficient (
actions/create-github-app-tokenfails withNot Foundif the app isn't installed on the repository). - Save the App ID as
CODEGEN_APP_IDand the private key contents asCODEGEN_APP_PRIVATE_KEYin both of:- GitHub project security Settings / Secrets / Actions — for the codegen workflow and the codegen merge job.
- GitHub project security Settings / Secrets / Dependabot — required because Dependabot-triggered
pull_requestworkflow runs use a separate, restricted secret context that doesn't see Actions secrets. Without the App secrets in the Dependabot store, themerge-dependabotjob inmerge-bot-pull-request.ymlcan't mint an App token and the PR will never auto-merge.
- If the codegen workflows require additional secrets (e.g. third-party API keys), register them in the Actions store; if a Dependabot-triggered workflow ever needs them, register them in the Dependabot store too.
- The App token is used by both the codegen workflow (
run-codegen-pull-request-task.yml) and every job inmerge-bot-pull-request.yml. App-authored pushes/PRs trigger downstreampull_requestandpushworkflow events directly — unlikeGITHUB_TOKEN-authored events, which are blocked by GitHub's recursion guard. This is whypublish-release.ymlfires on the merge commit after Dependabot or codegen auto-merge, and why the codegen workflow no longer needs the legacy close/reopen dance to trigger auto-merge. - The codegen auto-merge condition in
merge-bot-pull-request.yml(merge-codegenjob) requires:github.event.pull_request.user.login == 'ptr727-codegen[bot]'— PR was opened by the App.github.actor == 'ptr727-codegen[bot]'— the event was triggered by the App. This stops the job from re-invokinggh pr merge --autoon a maintainer-triggeredsynchronize, but does not disable auto-merge once it was already enabled by the initial bot-drivenopenedevent. If a maintainer pushes commits to a codegen PR with auto-merge already on, the next CI pass will merge them. To edit a codegen PR safely, disable auto-merge first viagh pr merge --disable-auto <PR>(or the GitHub UI button) before pushing.github.event.pull_request.head.repo.full_name == github.repository— PR is from this repo (not a fork).- Strict head/base pairing —
(head.ref == 'codegen-main' && base.ref == 'main') || (head.ref == 'codegen-develop' && base.ref == 'develop'). Codegen runs as a matrix opening one PR per branch; this pairing prevents a misconfigured workflow from sneaking acodegen-developbranch intomainor vice versa.
Codegen targets
mainANDdevelopin parallel (matrix inrun-codegen-pull-request-task.yml), so generated content lands on both branches independently without any back-merging. See AGENTS.md "Branching Model" for why this dual-target pattern beats develop-only-with-flow-through.- App name:
Codegen workflow schedule:
run-periodic-codegen-pull-request.ymlruns every Monday at 02:00 UTC, plus on-demand viaworkflow_dispatch. It uses the App token (CODEGEN_APP_ID+CODEGEN_APP_PRIVATE_KEY) to commit, open the PR asptr727-codegen[bot], and let the merge-bot auto-merge once CI passes. No PAT, no close/reopen dance.
GitHub project settings:
- General:
- Default branch:
main - Pull requests — both merge methods enabled at the repo level so each branch ruleset can pick the right one (develop =
Squash, main =Merge):Allow merge commits✓ (required for develop → main releases)Allow squash merging✓ (required for feature → develop merges)Allow rebase merging— disabled (no flow uses it; the develop ruleset forbids it anyway)Always suggest updating pull request branchesAllow auto-merge
- Default branch:
- Rules / Rulesets — separate rulesets per branch so allowed merge methods differ (develop = squash-only; main = merge-commit-only, per AGENTS.md). Everything else is shared.
- "Develop":
- Target branches:
develop. - Allowed merge methods:
Squash Require linear history(develop is kept linear; main carries merge commits by design, so this setting belongs to develop only)- Plus shared settings (below).
- Target branches:
- "Main":
- Target branches:
main. - Allowed merge methods:
Merge - Plus shared settings (below).
- Target branches:
- Shared settings (apply to both rulesets):
Restrict deletionsRequire signed commitsRequire a pull request before mergingDismiss stale pull request approvals when new commits are pushedRequire conversation resolution before merging
Require status checks to passRequire branches to be up to date before merging- Status checks that are required:
Check pull request workflow status
Block force pushesAutomatically request Copilot code reviewReview new pushesReview draft pull requests
- "Develop":
- Actions / General:
Allow GitHub Actions to create and approve pull requests
Template - Branching Workflow
See AGENTS.md "Branching Model" for the authoritative definition. Summary:
- Persistent
mainanddevelopbranches, each with its own ruleset (above). Both must always be building error free. - Feature branches off
develop. Only commit on feature branches, never directly todevelopormain. - Feature →
develop: squash-merge (develop ruleset enforces this; develop is kept linear). develop→main: merge-commit (preserves develop's commit list as a real second-parent reference on main; main ruleset enforces this).developis forward-only. Nomain → developback-merges. The develop squash-only ruleset physically blocks merge commits.- Bots open parallel PRs against both branches.
.github/dependabot.ymlduplicates each ecosystem entry per branch, and.github/workflows/run-codegen-pull-request-task.ymlruns as a matrix (branch namescodegen-mainandcodegen-develop). Each branch absorbs its own bot PRs independently — neither falls behind, no back-merges needed.
Template - Release Distribution Model: Push vs. Pull
This template ships with a push-on-merge release model — every commit on main triggers .github/workflows/publish-release.yml which publishes a GitHub release, NuGet/PyPI uploads, Docker tags, and platform executables. With the dual-target bot model (Dependabot/codegen targeting both branches), this means every Dependabot bump that lands on main produces a new release. That's the right default for projects whose consumers pull at their own cadence (Docker pulls, NuGet/PyPI installs, manual binary downloads) — releases are cheap and frequent, consumers update on their own schedule.
For projects whose consumers are pushed updates (HACS for Home Assistant, package managers that auto-update integrations, Linux distros that vendor from main), every release is a forced update to all users. Frequent bot-driven releases become noise. To switch to a manual main-release model while keeping the rest of the dual-target dual-channel flow:
Edit
.github/workflows/publish-release.ymland change the trigger:on: - push: - branches: [ main, develop ] - workflow_dispatch: + push: + branches: [ develop ] + workflow_dispatch:Result:
developpushes still publish dev releases automatically (PEP 440.dev0to PyPI, NBGV-prerelease tags on NuGet, prerelease GitHub releases).mainpushes no longer auto-publish; you trigger the release manually via the GitHub Actions UI (workflow_dispatch) when a real release is wanted.(Optional) narrow what flows into
mainautomatically. If a sea of Dependabot PRs onmainis noisy without auto-release, either:- Drop the
main-target Dependabot entries from.github/dependabot.yml(so deps update ondeveloponly, and reachmainthrough the next develop → main release the maintainer triggers — closer to a pure develop-only flow with manual cadence), or - Keep dual-target Dependabot and let the merge-bot auto-merge them silently into
main; main always has fresh code, but ships only when the maintainer dispatches a release.
- Drop the
For an example of the manual-release model in production, see homeassistant-purpleair — that integration ships through HACS (push distribution) and uses workflow_dispatch for actual releases.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.57 | 89 | 5/18/2026 |
| 1.0.55 | 84 | 5/13/2026 |
| 1.0.55-gbd3876e3dc | 85 | 5/18/2026 |
| 1.0.54 | 94 | 5/12/2026 |
| 1.0.54-ga03ad12524 | 86 | 5/13/2026 |
| 1.0.53-gd450626890 | 84 | 5/12/2026 |
| 1.0.52 | 88 | 5/12/2026 |
| 1.0.52-gbb66475387 | 86 | 5/12/2026 |
| 1.0.51-g1b1df869b1 | 94 | 5/11/2026 |
| 1.0.50-g5ce95cf23d | 94 | 5/11/2026 |
| 1.0.49 | 86 | 5/11/2026 |
| 1.0.49-ge72324d780 | 88 | 5/11/2026 |
| 1.0.48-gffb9e64d9e | 85 | 5/11/2026 |
| 1.0.47 | 85 | 5/11/2026 |
| 1.0.47-g2a27067c66 | 89 | 5/11/2026 |
| 1.0.46-gb67737eab3 | 91 | 5/11/2026 |
| 1.0.45-g4ddc6b9a5e | 86 | 5/11/2026 |
| 1.0.44 | 82 | 5/11/2026 |
| 1.0.44-gf154b783a4 | 92 | 5/11/2026 |
| 1.0.43-g79b34e0148 | 87 | 5/11/2026 |