Thank you for your interest in contributing to MyBlog! This document is the canonical contributor guide for project setup, workflow, and pull request expectations.
git clone https://github.com/mpaulosky/MyBlog.git
cd MyBlogHooks are installed automatically on clone. If needed, reinstall manually:
./scripts/install-hooks.shThis installs a pre-push gate that validates your code before it reaches GitHub. The hook also installs a post-checkout hook that ensures the pre-push gate stays current as the repo evolves.
The pre-push hook automatically runs before every git push and enforces
7 sequential gates:
| Gate | Rule | Enforced Behavior |
|---|---|---|
| 0 | Squad branch naming | Rejects pushes on non-squad/{issue}-{slug} branches; blocks main and dev |
| 1 | Untracked source files | Warns if .razor or .cs files exist but are not staged; prompts to confirm before proceeding |
| 2 | Markdown lint | Runs markdownlint-cli2; blocks push on Markdown lint violations |
| 3 | dotnet format | Runs dotnet format --verify-no-changes; prompts to auto-fix if formatting issues found |
| 4 | Release build | Runs dotnet build MyBlog.slnx --configuration Release; zero warnings or errors required |
| 5 | Unit & architecture tests | Runs Architecture.Tests, Domain.Tests, Web.Tests, Web.Tests.Bunit (Release configuration) |
| 6 | Integration tests | Runs Web.Tests.Integration, AppHost.Tests (Release configuration; Docker daemon required) |
Retry logic: Gates 4–6 allow up to 3 attempts. Between failures, the hook pauses and prompts you to fix errors, then retries automatically.
All work must be on a squad/{issue}-{slug} branch. Examples:
git checkout -b squad/42-fix-login-validation
git checkout -b squad/103-add-blog-search-featureThe pre-push hook rejects any push from a branch that does not match this
pattern, or from main/dev.
git push --no-verify- .NET 10 SDK — Download
- Docker daemon — Required for integration tests (Gate 6:
tests/Web.Tests.Integration,tests/AppHost.Tests) - Auth0 account — See AUTH0_SETUP.md for Auth0 configuration
# Restore dependencies
dotnet restore MyBlog.slnx
# Build the solution (Release config, as Gate 4 does)
dotnet build MyBlog.slnx --configuration Release
# Run all tests (as Gates 5 and 6 do)
dotnet test MyBlog.slnx --configuration Release
# Run the application (via Aspire AppHost)
cd src/AppHost
dotnet run- Start from
dev:
git checkout dev
git pull origin dev- Create a
squad/*branch with the issue number and a kebab-case slug:
git checkout -b squad/42-fix-login-validationThe pre-push gate will reject any other branch name.
Before git push:
- Verify you are on a
squad/*branch:
git symbolic-ref --short HEAD-
Ensure all untracked
.razorand.csfiles are staged or intentionally excluded from git. -
Run the pre-push gates locally to catch errors early:
# Run unit/architecture tests (Gate 4)
dotnet test tests/Architecture.Tests --configuration Release --no-build
dotnet test tests/Domain.Tests --configuration Release --no-build
dotnet test tests/Web.Tests --configuration Release --no-build
dotnet test tests/Web.Tests.Bunit --configuration Release --no-build
# Run integration tests (Gate 6 — requires Docker)
dotnet test tests/Web.Tests.Integration --configuration Release --no-build
dotnet test tests/AppHost.Tests --configuration Release --no-build- Push:
git pushIf the pre-push gate fails, fix the errors and retry git push. The hook will
re-run all gates again.
- Create a PR from your
squad/*branch todev:
gh pr create \
--base dev \
--title "feat(scope): description" \
--body "Closes #<issue-number>
## Changes
- Your changes here
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing done"-
Wait for CI to pass — all checks must be green before requesting review.
-
Address code review feedback. If changes are needed, push corrections to the same branch.
-
Once all reviewers approve and CI is green, squash-merge to
dev:
gh pr merge <PR-number> --squash --delete-branch- After merge, local branch cleanup is automatic via the post-checkout hook, but you can also manually clean up orphaned branches:
git checkout dev
git pull origin dev
git fetch --prune
git branch -vv | grep gone | awk '{print $1}' | xargs -r git branch -Dsquad/* branch after your PR
has been merged. If you need to continue work on related issues:
- Switch to
devand pull the latest:
git checkout dev
git pull origin dev- Create a fresh
squad/{issue}-{slug}branch for your next task:
git checkout -b squad/45-next-issue- Push to the new branch — the pre-push gate will guide you.
If you accidentally commit on a merged branch, you can recover by following these same steps. New commits on a merged branch create orphaned history; starting fresh on a new issue branch keeps the repository clean and your work tracking obvious.
- Follow .NET naming conventions (PascalCase for types, camelCase for locals)
- Use C# 14 features where appropriate
- Keep methods focused and testable
- Write unit tests for new domain logic
- Maintain or improve code coverage
- Use xUnit, FluentAssertions, and NSubstitute
- Domain layer must not depend on Web layer
- Use repository and feature-slice patterns already present in the solution
- Keep Blazor components focused on presentation concerns
- ARCHITECTURE.md — Solution structure and design decisions
- AUTH0_SETUP.md — Auth0 configuration guide
- APPHOST-LOCAL-DEVELOPMENT.md — AppHost orchestration, seeding, and clear-and-reseed workflow
- README.md — Project overview and getting started
- Pre-Push Process Playbook — Detailed pre-push troubleshooting and gate descriptions
- PR Review & Merge Process — End-to-end PR lifecycle and reviewer protocol
- Warnings treated as errors: The Release config enforces
TreatWarningsAsErrors=true. Fix warnings first. - Missing file references: Stage any new
.razoror.csfiles withgit add, then retry. - NuGet restore failure: Run
dotnet restoremanually and retry.
- Architecture test failure: Check naming conventions (commands →
Command, queries →Query, handlers →Handler, validators →Validator). - DateTime equality failures: Assert individual fields instead of
whole-record equality;
UtcNowchanges between calls. - Docker not running (Gate 6): Start Docker Desktop and retry.
- Container startup timeout: Increase Docker resources and verify images are pulled.
If the pre-push hook is missing:
./scripts/install-hooks.shOpen an issue or reach out to @mpaulosky.