Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d443c3a
fix: disable AoT, refactor Directory.Build.props
vmelamed May 25, 2026
cee30b2
chore: update vm2.TestUtilities package version to 1.5.2 and clarify …
vmelamed May 25, 2026
4397e92
refactor!: put the Newtonsoft.Json Ulid converter in a separate proje…
vmelamed May 26, 2026
8f82dfb
refactor: use per test JsonSerializerSettings
vmelamed May 26, 2026
422da4e
fix: correct variable name for JsonSerializerSettings in UlidNsConver…
vmelamed May 26, 2026
e0623ca
refactor: renamed folders and projects from UlidType to Ulid
vmelamed May 26, 2026
b0eed52
refactor!: established and followed the names of namespace, projects,…
vmelamed May 26, 2026
3416cd7
refactor!: follow the new conventions
vmelamed May 27, 2026
cf1ad98
fix: update project paths in CI configuration and Directory.Build.pro…
vmelamed May 27, 2026
e79f131
fix: add OutputType property to project files for consistency
vmelamed May 27, 2026
1cc702e
fix: remove AssemblyName property for consistency in project file
vmelamed May 28, 2026
b535d3f
fix: remove AssemblyName property for consistency in benchmark and te…
vmelamed May 28, 2026
9dd40a4
fix: rename benchmark project file and update references for consistency
vmelamed May 28, 2026
09abca0
fix: update PackageProjectUrl for accuracy in project file
vmelamed May 28, 2026
ca4f82c
fix: update UlidConverter comments for consistency in type references
vmelamed May 28, 2026
a12e543
chore: diff-shared.sh
vmelamed May 28, 2026
86f1fce
chore: cosmetic change for consistency
vmelamed May 28, 2026
62db3f9
fix: update .gitattributes for consistent line endings and add AOT gu…
vmelamed May 28, 2026
fd743fc
refactor: change "test/" to "tests/"
vmelamed May 29, 2026
9792a5d
fix: update test utilities package version to 2.0.2 and improve regex…
vmelamed May 29, 2026
21d9909
fix: update vm2.TestUtilities package version to 2.0.2
vmelamed May 29, 2026
9d8258d
fix: update benchmark tests instructions for clarity and add missing …
vmelamed May 29, 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
18 changes: 9 additions & 9 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
*.ps1 text eol=crlf

# Explicitly declare text files you want to always be normalized and converted to native line endings on checkout
*.cs text diff=csharp
*.csproj text
*.sln text
*.slnx text
*.md text
*.json text
*.yaml text
*.yml text
*.xml text
*.cs text eol=lf diff=csharp
*.csproj text eol=lf
*.sln text eol=lf
*.slnx text eol=lf
*.md text eol=lf
*.json text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.xml text eol=lf

# Denote all files that are truly binary and should not be modified
*.png binary
Expand Down
62 changes: 61 additions & 1 deletion .github/CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [Performance](#performance)
- [Security](#security)
- [Naming](#naming)
- [AOT and Trimming](#aot-and-trimming)
- [Git and PR Hygiene](#git-and-pr-hygiene)
- [Files with shared content](#files-with-shared-content-5)
- [Documentation](#documentation)
Expand Down Expand Up @@ -132,7 +133,7 @@ The project owner is a non-native English speaker.
- Global usings: defined in **`usings.cs` per project**
- Standard folder layout:
- `src/` — source code
- `test/` — test projects. The stack is: **xUnit, FluentAssertions, NSubstitute, MTP v2, coverage**
- `tests/` — test projects. The stack is: **xUnit, FluentAssertions, NSubstitute, MTP v2, coverage**
- `benchmarks/` — **BenchmarkDotNet** projects (desirable)
- `examples/` — usage examples (desirable). Prefer single-file programs for simplicity, but multi-file projects are acceptable if the example is complex enough to warrant it.
- `docs/` — documentation (optional, in addition to README.md, e.g. blogs, design docs, etc.)
Expand Down Expand Up @@ -257,6 +258,65 @@ The project owner is a non-native English speaker.
- Events: past tense — `OrderPlacedEvent`.
- Commands: imperative — `PlaceOrderCommand`.
- Handlers: `...Handler` suffix.
- **Always set `<OutputType>` explicitly** in every `*.csproj` to make it clear to the CI scripts what type of file to run for tests and benchmarks, and to avoid drift when project file names change.
- Prefer **domain-first public API type names** without suffixes unless required to avoid language-level symbol conflicts.
- Prefer **package-first artifact identity** for NuGet packages and assemblies:
- Package ID: `vm2.<Package>` or `vm2.<Package>.<Feature>`
- Assembly name: `vm2.<Package>` or `vm2.<Package>.<Feature>`
- Always set `<RootNamespace>` explicitly in every `*.csproj`.
- Root namespace policy:
- For core libraries, prioritize API clarity and discoverability.
- For feature libraries, use a stable hierarchy that mirrors the feature domain.
- Test naming policy (tests-first):
- Project and assembly: `<Package>.Tests` or `<Package>.<Feature>.Tests` to group tests by package and feature, e.g. `Ulid.Tests` for `vm2.Ulid` package, `UlidTool.Tests` for `vm2.UlidTool` package, etc. This also makes it clear that the assembly contains tests for the specific package or feature. **Prefer the default name for the assembly** - the name of the project file without the extension, e.g. `Ulid.Tests` for `Ulid.Tests.csproj`.
- Namespace: `vm2.Tests.<Package>[.<Feature>]` to avoid conflicts where `<Package>` is also a name of a type, e.g. `Ulid`. It also makes it clear that the namespace contains tests for the specific package, class, or feature, e.g. `vm2.Tests.Ulid` for `vm2.Ulid` package/type, `vm2.Tests.UlidTool` for `vm2.UlidTool` package/feature (tool), etc.
- **Always specify `<OutputType>Exe</OutputType>` explicitly** in test project files to make it clear to the CI scripts what type of file to run.
- Benchmark naming policy (benchmarks-first):
- Project and assembly: `<Package>.Benchmarks` or `<Package>.<Feature>.Benchmarks` to group benchmarks by package and feature, e.g. `Ulid.Benchmarks` for `vm2.Ulid` package. This also makes it clear that the assembly contains benchmarks for the specific package or feature. **The assembly name MUST be the default** - the name of the project file without the extension, e.g. `Ulid.Benchmarks` for `Ulid.Benchmarks.csproj`. This is BenchmarkDotNet's required convention.
- Namespace: `vm2.Benchmarks.<Package>[.Feature]` to avoid conflicts where `<Package>` is also a name of a type, e.g. `Ulid`. It also makes it clear that the namespace contains tests for the specific package, class, or feature, e.g. `vm2.Tests.Ulid` for `vm2.Ulid` package/type.
- **Always specify `<OutputType>Exe</OutputType>`** in benchmark project files to make it clear to the CI scripts what type of file to run for benchmarks.
- Inside a single repository, do not mix naming strategies. Choose one namespace strategy and apply it consistently to `src/`, `tests/`, and `benchmarks/`.

## AOT and Trimming

- Scope by project type (usually set in **`Directory.Build.props`** with folder-based conditions):
- **test** and **benchmark** projects: no trimming and no AOT checks by default; optimize for correctness/perf feedback, not deployment-shape validation:
- `IsAotCompatible=false`
- `VerifyReferenceAotCompatibility=false`
- `EnableTrimAnalyzer=false`
- `IsTrimmable=false`
- **product** projects: trimming and AOT checks enabled by default (usually set in **`Directory.Build.props`**):
- `IsAotCompatible=true`
- `VerifyReferenceAotCompatibility=true` when strict dependency metadata validation is desired.
- `EnableTrimAnalyzer=true`
- `IsTrimmable=true`
- Build and classify diagnostics (handled in CI and local `dotnet build`/`dotnet publish`):
- IL2026-family: trimming compatibility issue.
- IL3050-family: AOT dynamic-code issue.
- IL3058: referenced assembly is not marked AOT-compatible.
- If IL2026 appears (code-level fix):
- first try `DynamicallyAccessedMembersAttribute` to make reflection requirements explicit.
- if an API is fundamentally trim-unsafe, annotate the API boundary with `RequiresUnreferencedCodeAttribute`.
- avoid suppression-first fixes.
- If IL3050 appears (code-level fix):
- first try removing/replacing dynamic code patterns.
- if an API is fundamentally AOT-unsafe, annotate the API boundary with `RequiresDynamicCodeAttribute`.
- if unsupported surface is substantial, split into AOT-safe core and non-AOT companion code/package.
- If strict AOT/trimming is not worth it for a specific product project (project-level opt-out in **`*.csproj`**):
- `IsAotCompatible=false`
- `VerifyReferenceAotCompatibility=false`
If needed, also set:
- `EnableTrimAnalyzer=false`
- `IsTrimmable=false`
- use this only as an explicit, documented design decision with rationale in README/changelog/PR.
- Re-run checks and verify warning flow (CI and local build/publish):
- warnings should be either fixed or intentionally bubbled at public API boundaries.
- unsupported features must be documented clearly for consumers.
- IL warning suppression policy (code-level and project-level):
- **do not suppress IL warnings** (`IL2xxx`, `IL3xxx`) by default.
- only suppress when the safety argument is explicit, tested, and documented.
- if you think suppression is the easiest fix, stop and re-evaluate API design first.
- unless you really, really know what you are doing, Val.

## Git and PR Hygiene

Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,21 @@ concurrency:
env:
BUILD_PROJECTS: >-
[
"./vm2.Ulid.slnx"
"vm2.Ulid.slnx"
]
TEST_PROJECTS: >-
[
"test/UlidType.Tests/UlidType.Tests.csproj",
"test/UlidTool.Tests/UlidTool.Tests.csproj"
"tests/Ulid/Ulid.Tests.csproj",
"tests/UlidTool/UlidTool.Tests.csproj"
]
BENCHMARK_PROJECTS: >-
[
"benchmarks/UlidType.Benchmarks/UlidType.Benchmarks.csproj"
"benchmarks/Ulid/Ulid.Benchmarks.csproj"
]
PACKAGE_PROJECTS: >-
[
"src/UlidType/UlidType.csproj",
"src/Ulid/Ulid.csproj",
"src/Serialization.NsJson.Ulid/Serialization.NsJson.Ulid.csproj",
"src/UlidTool/UlidTool.csproj"
]
RUNNERS_OS: >-
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/Prerelease.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ on:
env:
PACKAGE_PROJECTS: >-
[
"src/UlidType/UlidType.csproj",
"src/Ulid/Ulid.csproj",
"src/Serialization.NsJson.Ulid/Serialization.NsJson.Ulid.csproj",
"src/UlidTool/UlidTool.csproj"
]
# Ensure the NUGET_API_KEY secret is issued by the server selected here.
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/Release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ on:
env:
PACKAGE_PROJECTS: >-
[
"src/UlidType/UlidType.csproj",
"src/Ulid/Ulid.csproj",
"src/Serialization.NsJson.Ulid/Serialization.NsJson.Ulid.csproj",
"src/UlidTool/UlidTool.csproj"
]
# Ensure the NUGET_API_KEY secret is issued by the server selected here.
Expand Down
6 changes: 0 additions & 6 deletions .vscode/settings.json

This file was deleted.

8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ Key design decisions:
```text
vm2.Ulid/
├── src/
│ ├── UlidType/ # Core library: Ulid struct, UlidFactory, providers
│ ├── Ulid/ # Core library: Ulid struct, UlidFactory, providers
│ └── UlidTool/ # CLI tool: generate ULIDs from command line
├── test/
│ └── UlidType.Tests/ # xUnit v3 tests
├── tests/
│ └── Ulid.Tests/ # xUnit v3 tests
├── benchmarks/
│ └── UlidType.Benchmarks/
│ └── Ulid.Benchmarks/
├── examples/
│ └── GenerateUlids.cs # Runnable script example
└── vm2.Ulid.slnx
Expand Down
Loading
Loading