Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d338b93
Re-sync unprotected template-tracked files to canonical (C1 drift)
Chris-Wolfgang May 22, 2026
d0c9303
Fill {{PROJECT_NAME}} placeholder in CONTRIBUTING.md (Wolfgang.TryPat…
Chris-Wolfgang May 22, 2026
f8ebf2f
Propagate setup.ps1 UTF-8/newline fix from canonical
Chris-Wolfgang May 22, 2026
4de6fbb
Add canonical test/benchmark project config (Phase-0 files)
Chris-Wolfgang May 22, 2026
1b64176
Drop tests/Directory.Build.props — hold test projects to the warning bar
Chris-Wolfgang May 22, 2026
a19533b
Add github-actions ecosystem to Dependabot (CI2)
Chris-Wolfgang May 23, 2026
e6ee5cb
Move stray docs files under docfx_project/docs/ (D7)
Chris-Wolfgang May 23, 2026
bd89ef8
Add CHANGELOG.md (D3)
Chris-Wolfgang May 23, 2026
00ad787
Switch benchmarks entry point to BenchmarkSwitcher (P2)
Chris-Wolfgang May 23, 2026
26555bf
Address PR review round 2 (canonical-unprotected)
Chris-Wolfgang May 23, 2026
943b1ca
Drop vestigial one-time setup scripts (post-bootstrap cleanup)
Chris-Wolfgang May 24, 2026
ca4c2a0
CONTRIBUTING.md: correct format.ps1 and README-FORMATTING.md paths
Chris-Wolfgang May 25, 2026
1c143d8
scripts/format.ps1: work from repo root + correct usage examples
Chris-Wolfgang May 25, 2026
c37ec19
CONTRIBUTING.md: correct AsyncFixer description (ConfigureAwait is MA…
Chris-Wolfgang May 25, 2026
1cdcb11
Fix-BranchRuleset.ps1: normalize Repository before gh api calls
Chris-Wolfgang May 25, 2026
37a8885
CONTRIBUTING.md: bump prerequisite SDK to 10.0 to match repo TFMs
Chris-Wolfgang May 25, 2026
3f7927f
scripts/Validate-DocsDeploy.sh: rmdir mktemp path before worktree add
Chris-Wolfgang May 25, 2026
3bf791f
Setup-Labels.ps1: restore early -Repository format validation
Chris-Wolfgang May 25, 2026
9563591
scripts/build-pr.ps1: drop -UseBasicParsing from Invoke-WebRequest
Chris-Wolfgang May 25, 2026
4fb38d1
Remove subtree TreatWarningsAsErrors=false overrides
Chris-Wolfgang May 25, 2026
bce9b4e
Validate-DocsDeploy.sh: handle SSH remote URLs in REPO_NAME parsing
Chris-Wolfgang May 25, 2026
c14db4d
build-pr.ps1: ensure .NET global-tools dir is on PATH after install
Chris-Wolfgang May 25, 2026
037ded8
scripts: repair Setup-Labels.ps1 param block + drop --paginate on rul…
Chris-Wolfgang May 26, 2026
0b0fd33
C4: drop stale <AssemblyVersion> from src csproj(s)
Chris-Wolfgang May 26, 2026
3548b62
CI1: add <RepositoryUrl> to src csproj(s)
Chris-Wolfgang May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/ISSUE_TEMPLATE/maintenance-task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: "✨ Maintenance task"
description: "Track an actionable improvement under the Maintenance framework (security, performance, testing, cleanup, docs, API, or CI/CD)."
title: "[Maintenance] <category>: <short description>"
labels: [maintenance-task]
assignees: []
body:
- type: markdown
attributes:
value: |
## Maintenance framework sub-issue

This template creates a **`maintenance-task`** sub-issue under this repo's parent `Maintenance: <repo>` issue. The new issue will auto-appear in the cross-repo Maintenance project board (URL listed in the parent `Maintenance: <repo>` issue body).

- Pick exactly **one** category in the dropdown below. The corresponding `maintenance - <category>` label will need to be added manually after creation (issue forms don't yet support dynamic label addition).
- Fill in **Scope** (what's done & why), **Acceptance** (when do we close this?), and **Links** (PRs, scan output, related issues).
- If you're closing this issue via a PR, include `Fixes #<this-issue-number>` in the PR body so the auto-add workflow marks the project item as Done.

- type: dropdown
id: category
attributes:
label: Category
description: "Pick exactly one. After creation, also add the corresponding `maintenance - <category>` label."
options:
- "security — scans, finding fixes, dependency vulnerability audit"
- "performance — profile, benchmark, optimize, validate gains"
- "testing — coverage, integration/smoke/mutation tests, fixtures"
- "cleanup — refactor for reuse / quality / efficiency"
- "docs — XML doc coverage, README, CHANGELOG, samples"
- "API — public/internal surface audit, breaking-change vigilance"
- "CI/CD — Docker, CI workflow, build/publish pipeline"
validations:
required: true

- type: textarea
id: scope
attributes:
label: Scope
description: "What needs to be done? What's the motivation?"
placeholder: |
e.g.
- Profile the hot path in `Extractor.ExtractAsync` and identify the dominant allocations.
- Goal: reduce per-record allocations to enable streaming larger inputs.
validations:
required: true

- type: textarea
id: acceptance
attributes:
label: Acceptance criteria
description: "When do we close this issue? Concrete observable outcomes."
placeholder: |
e.g.
- Benchmark X shows <50% of current allocations.
- No regression in existing benchmark suite (>5%).
- Updated benchmark numbers committed.
validations:
required: true

- type: textarea
id: links
attributes:
label: Links
description: "Related PRs, scan output, prior issues, external references."
placeholder: |
- Related PR: #...
- Scan output: ...
- Related issue: #...
validations:
required: false

- type: markdown
attributes:
value: |
---

💡 **Tip for agents (Copilot etc.):** When opening a maintenance-task sub-issue, use this template and pick the matching category. After creation, add the `maintenance - <category>` label manually. See `.github/copilot-instructions.md` for the full Maintenance framework convention.
12 changes: 12 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

Fixes/Complete # (issue)

<!--
If this PR addresses a Maintenance framework sub-issue, link it explicitly so the
project board auto-marks the item as Done on merge:
Fixes #<maintenance-task-issue-number>
The Maintenance framework tracks ongoing improvement work (security, performance,
testing, cleanup, docs, API, CI/CD) — see the parent `Maintenance: <repo>` issue
for details.
-->


## Type of change

Please delete options that are not relevant.
Expand Down
188 changes: 182 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing to <Application Name>
# Contributing to Wolfgang.TryPattern

Thank you for your interest in contributing to **<Application Name>**! We welcome contributions to help improve this project.
Thank you for your interest in contributing to **Wolfgang.TryPattern**! We welcome contributions to help improve this project.

## How Can You Contribute?

Expand All @@ -11,8 +11,9 @@ You can contribute in several ways:
- Improving documentation
- Writing or improving tests

Please note: Before coding anything please check with me first by entering an issue and getting approval for it. PRs are more likely to get merged if I have agreed to the changes.
**Please note:** Before coding anything please check with me first by entering an issue and getting approval for it. PRs are more likely to get merged if I have agreed to the changes.

---

## Getting Started

Expand All @@ -36,27 +37,202 @@ Please note: Before coding anything please check with me first by entering an is
- Building the project
- Running automated tests
- Checking code style and linting
- Running static analysis with multiple static analyzers (see list below)

**It is important to make sure that all CI steps pass before your PR can be merged.**
- If any CI step fails, please review the error messages and update your PR as needed.
- Maintainers will review your PR once all checks have passed.

---

## Code Quality Standards

This project maintains **extremely high code quality standards** through multiple layers of static analysis and automated enforcement.

### The 7 Analyzers

All code is analyzed by these tools during build:

1. **Microsoft.CodeAnalysis.NetAnalyzers** (Built-in .NET SDK)
- Correctness, performance, and security rules
- Latest analysis level enabled

2. **Roslynator.Analyzers**
- 500+ refactoring and code quality rules
- Advanced C# pattern detection

3. **AsyncFixer**
- Detects async/await anti-patterns
- Ensures proper `ConfigureAwait()` usage
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
- Prevents fire-and-forget async calls

4. **Microsoft.VisualStudio.Threading.Analyzers**
- Thread safety enforcement
- Async method naming conventions
- Deadlock prevention

5. **Microsoft.CodeAnalysis.BannedApiAnalyzers**
- Blocks usage of APIs listed in `BannedSymbols.txt`
- Enforces async-first patterns (see below)

6. **Meziantou.Analyzer**
- Comprehensive code quality checks
- Performance optimizations
- Best practice enforcement

7. **SonarAnalyzer.CSharp**
- Industry-standard code analysis
- Security vulnerability detection
- Code smell identification

### Async-First Enforcement

This library **prohibits synchronous blocking calls** via `BannedSymbols.txt`. The following APIs are **banned**:

#### ❌ Blocking Async Operations
```csharp
// Banned - blocks threads
task.Wait();
task.Result;
Task.WaitAll(tasks);

// Required - truly async
await task;
await Task.WhenAll(tasks);
```

#### ❌ Synchronous I/O
```csharp
// Banned
File.ReadAllText(path);
stream.Read(buffer, 0, count);
streamReader.ReadLine();

// Required
await File.ReadAllTextAsync(path);
await stream.ReadAsync(buffer, 0, count);
await streamReader.ReadLineAsync();
```

#### ❌ Thread Blocking
```csharp
// Banned
Thread.Sleep(1000);
Console.ReadLine();

// Required
await Task.Delay(1000);
// Avoid blocking console reads in async code
```

#### ❌ Obsolete/Insecure APIs
```csharp
// Banned
var client = new WebClient();
var formatter = new BinaryFormatter();
var now = DateTime.Now; // Use DateTimeOffset

// Required
var client = new HttpClient();
// Use System.Text.Json.JsonSerializer
var now = DateTimeOffset.UtcNow;
```

**Why?** This ensures all code is **truly asynchronous** and **non-blocking**, providing optimal performance in async contexts.

---

## Build and Test Instructions

### Prerequisites
- .NET 8.0 SDK or later
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
- PowerShell Core (optional, for formatting scripts)

### Build the Project

```bash
# Restore NuGet packages
dotnet restore

# Build in Release configuration (enforces all analyzers)
dotnet build --configuration Release
```

**Note:** Release builds treat all analyzer warnings as errors (`<TreatWarningsAsErrors>true</TreatWarningsAsErrors>`). Debug builds allow warnings to facilitate development.

### Run Tests

```bash
# Run all unit tests
dotnet test --configuration Release

# Run with coverage (if configured)
dotnet test --collect:"XPlat Code Coverage"
```

### Code Formatting

This project uses `.editorconfig` for consistent code style:

```bash
# Format all code
dotnet format

# Check formatting without changes (CI mode)
dotnet format --verify-no-changes

# PowerShell formatting script
pwsh ./format.ps1
```

See [README-FORMATTING.md](README-FORMATTING.md) for detailed formatting rules.
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated
Comment thread
Chris-Wolfgang marked this conversation as resolved.
Outdated

---

## .editorconfig Rules

Key style rules enforced:

- **Indentation:** 4 spaces (C#), 2 spaces (XML/JSON)
- **Line endings:** LF (Unix-style)
- **Charset:** UTF-8
- **Trim trailing whitespace:** Yes
- **Final newline:** Yes
- **Braces:** New line style (Allman)
- **Naming:** PascalCase for public members, camelCase for parameters/locals
- **File-scoped namespaces:** Required in C# 10+
- **`var` preferences:** Use for built-in types and when type is obvious
- **Null checks:** Prefer pattern matching (`is null`, `is not null`)
Comment thread
Chris-Wolfgang marked this conversation as resolved.

View the complete configuration in [.editorconfig](.editorconfig).

---

## Guidelines

- Follow the coding style used in the project.
- Write clear, concise commit messages.
- Add relevant tests for new features or bug fixes.
- Document any public APIs or significant changes.
- Document any public APIs with XML documentation comments.
- Ensure all analyzer warnings are addressed (they're treated as errors in Release builds).
- Use async/await patterns - no blocking calls allowed.
- Include `CancellationToken` parameters in async methods where appropriate.

---

## Pull Requests

- Ensure your pull request passes all tests.
- Ensure your pull request passes all tests and analyzer checks.
- Respond to review feedback in a timely manner.
- Reference related issues in your pull request description.
- Keep changes focused and atomic - one feature/fix per PR.
- Update documentation if you change public APIs.

---

## Code of Conduct

Please be respectful and considerate in all interactions. See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) if available.
Please be respectful and considerate in all interactions. See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for our community guidelines.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/README-FORMATTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This repository uses `dotnet format` to enforce consistent C# code style.

## Prerequisites

The `dotnet format` command is **built into the .NET SDK** starting with .NET 6 and later. Since this project requires .NET 8.0 SDK or later, you already have `dotnet format` available — no separate tool installation is needed.
The `dotnet format` command is **built into the .NET SDK** starting with .NET 6 — no separate tool installation is needed. In practice `dotnet format` still has to load and evaluate the project, so you need an SDK new enough to handle this repo's target frameworks: use the SDK version(s) installed by `.github/workflows/pr.yaml` (and `global.json` if present). The latest stable .NET SDK is generally a safe choice.

> **Note:** The standalone `dotnet-format` global tool was deprecated when `dotnet format` was integrated into the .NET 6 SDK in August 2021.

Expand Down
2 changes: 1 addition & 1 deletion docs/RELEASE-WORKFLOW-SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ Before creating a production GitHub Release (e.g., `v1.0.0`):

If you encounter issues not covered in this guide:

1. Check the [Actions tab](../../actions) for detailed logs
1. Check the Actions tab of this repository on GitHub for detailed logs
2. Review artifacts uploaded by failed jobs
3. Consult the [GitHub Actions documentation](https://docs.github.com/en/actions)
4. Open an issue in this repository with:
Expand Down
2 changes: 2 additions & 0 deletions docs/WORKFLOW_SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ In addition to the overwrite step, a separate "Detect protected configuration fi
"BannedSymbols.txt"
"*.globalconfig"
"*.ruleset"
".github/workflows/*.yml"
".github/workflows/*.yaml"
)

# Copy each configuration file from main branch if it exists
Expand Down
Loading
Loading