Skip to content

Contributing

Stable AspireC4 Reviewed 2026-09-17 purview-dev/aspirec4 architecture architecture-as-code architecture-diagrams aspire aspire-dashboard aspire-dotnet aspire-hosting aspnetcore c4 c4-model developer-experience devex diagram diagrams dotnet likec4 roslyn source-generator visualization

Thank you for contributing! This guide covers the tools, conventions, and processes used in the repository.

ToolPurpose
.NET SDK (version from global.json)Build and test
Bun (version from package.json → packageManager)Repository scripts and commit hooks
justTask runner
LefthookGit hooks
DockerIntegration tests, local diagram viewer

After cloning, install all dependencies:

Terminal window
just init # JS dependencies (Bun), NuGet packages, local tools, and Git hooks
Terminal window
just build # Build the solution (Debug by default; pass Release to build Release)
just test # Run all tests (unit + integration)
just lint-check # Check formatting

Two distinct brands exist in this repository. Use them consistently:

BrandWhat it isExamples
AspireC4This library / pluginAspireC4.Hosting NuGet package, AspireC4DiagramOptions, IAspireC4Builder, AddAspireC4()
LikeC4The third-party visualisation tool this library integratesghcr.io/likec4/likec4 container, LikeC4Model, LikeC4DslGenerator, .c4 file format

Rules:

  • Public extension methods and user-facing types use the AspireC4 prefix.
  • Types that directly represent LikeC4 DSL concepts keep the LikeC4 prefix.
  • Never use LikeC4 to refer to this library, and never use AspireC4 to refer to the third-party tool.

just is the single entry point for all development tasks. Run just with no arguments to list all recipes.

RecipeDescription
just restoreRestore NuGet packages and local .NET tools
just build [Debug|Release]Build the solution (default: Debug)
just cleanClean build outputs
just testRun all tests (unit + integration)
just test-unitRun unit tests only
just test-integrationRun integration tests only
just lint-checkCheck formatting with CSharpier
just lint-fixAuto-fix formatting with CSharpier
just packBuild and pack NuGet artifacts into artifacts/nuget/
RecipeDescription
just test-e2e-dockerIntegration tests against the host Docker daemon
just test-e2eDocker + all local CLI runtimes (npm, pnpm, yarn, bun, deno)
just test-e2e-cliAll local CLI runtimes only (npm, pnpm, yarn, bun, deno)
just test-e2e-npmSingle CLI runtime (also -pnpm, -yarn, -bun, -deno)
RecipeDescription
just diagramsOpen the live LikeC4 diagram viewer for this repository
Terminal window
dotnet test src/tests/AspireC4.UnitTests/AspireC4.UnitTests.csproj \
-- --filter "FullyQualifiedName~MyTestMethod"
dotnet test src/tests/AspireC4.IntegrationTests/AspireC4.IntegrationTests.csproj \
-- --filter "FullyQualifiedName~MyTestMethod"

All C# code is formatted with CSharpier, pinned to the version in .config/dotnet-tools.json. It is installed as a local .NET tool via just restore.

Terminal window
just lint-check # Report formatting violations
just lint-fix # Auto-fix formatting violations

CSharpier runs automatically on every git commit via Lefthook. Do not pin a specific CSharpier version in .csproj files — the version lives exclusively in .config/dotnet-tools.json.

Lefthook manages two hooks, configured in .config/lefthook.yml:

HookWhat it does
pre-commitRuns just lint-check (CSharpier over the repo root). Rejects the commit if any file is mis-formatted.
commit-msgRuns commitlint to enforce conventional commit format.

Lefthook installs when you run just init. To verify it is active:

Terminal window
bunx lefthook install

To bypass a hook temporarily (e.g. a work-in-progress commit you will amend):

Terminal window
git commit --no-verify -m "wip: ..."

Do not bypass hooks on commits intended for main.

Commit messages must follow Conventional Commits and are enforced by commitlint (via Lefthook).

Format:

<type>(<optional scope>): <subject>
<optional body>
<optional footer>

Allowed types: feat, fix, refactor, perf, test, docs, ci, build, chore, style, revert.

Rules:

  • Subject must be lower-case, no trailing period, max 100 characters.
  • Body lines max 100 characters.
  • Breaking changes: append ! after the type/scope, or add BREAKING CHANGE: in the footer.
Terminal window
# Good
feat(core): add image alias resolution for azure resources
fix: correct hmr port fallback on windows
chore(deps): bump aspire.hosting to 9.2.0
# Bad — upper-case subject, trailing period
Fix: Correct HMR port fallback on Windows.

All tests in this repository must use TUnit. Do not use xUnit, NUnit, or MSTest. Test projects declare just <Project Sdk="Microsoft.NET.Sdk" />; the SDK (Purview.BuildSdk) wires TUnit, TUnit.Mocks, and Bogus into them automatically.

[Test]
public async Task Something_Should_DoX()
{
// Arrange
// Act
// Assert
await Assert.That(result).IsEqualTo(expected);
}

Mocking uses TUnit.Mocks (.Returns(...) API); NSubstitute is not referenced.

ProjectWhat to test here
AspireC4.UnitTestsLikeC4ModelBuilder, LikeC4DslGenerator, annotations, options — no Docker required
AspireC4.IntegrationTestsFull Aspire lifecycle: container startup, file generation, endpoint availability

Integration tests require Docker to be running. They pull ghcr.io/likec4/likec4 on first run.