Conversation
Blog posts, README, and docs/index.html updated for v1.2.0. Reviewed and approved by Aragorn.
Fixes 3 review blockers identified in PR #126 review: - docs/index.html: npm run css:watch → npm run tw:watch (matches root package.json) - README.md + kickoff blog post: Aspire 13.2.2 → 13.2.3 (matches Directory.Packages.props) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary
Adds `workflow_dispatch` trigger to `squad-mark-released.yml` so the
Done → Released project board migration can be run manually.
## Problem
When v1.2.0 was published, `squad-mark-released.yml` did not fire —
likely because the release event and workflow landing on `main` had a
timing race. With no manual trigger, the only recovery path was direct
GraphQL mutations.
## Changes
- Add `workflow_dispatch: {}` trigger
- Update job `if` condition to always run on manual dispatch (skip the
pre-release/draft guard for `workflow_dispatch` events)
- Use `context.payload.release?.tag_name ?? 'manual dispatch'` to
prevent null-ref in the summary notice
## Testing
After merge to `dev` → `main`, the workflow will appear under **Actions
→ Squad Mark Released → Run workflow** for manual recovery use.
---
> ⚠️ This PR should be fast-tracked to `main` so `dev` and `main` stay
in sync.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Boromir <boromir@squad.dev>
Closes #130 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #133 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Sprint 6: Code Quality **Goal:** Eliminate analyzer warnings, enforce internal visibility on Web feature types, expand test coverage, and migrate Unit.Tests into Web.Tests. --- ## Merged Feature PRs - Closes #137 — PR #144 — fix(quality): rename `ct` → `cancellationToken` in all MediatR handlers - Closes #138 — PR #145 — test: add unit tests for BlogPost, Result, and ValidationBehavior (42 tests) - Closes #139 — PR #146 — test: add unit tests for UserManagementHandler (16 tests) - Closes #140 — PR #147 — fix(quality): make Web feature types `internal` (CA1515, ~28 types) - Closes #141 — PR #148 — test: add unit tests for BlogPostMappings (22 tests) - Closes #142 — PR #149 — fix(quality): add ConfigureAwait(false) and specific exception catches - Closes #143 — PR #150 — fix(quality): address Domain and ServiceDefaults analyzer warnings - Closes #151 — PR #152 — feat(tests): migrate Unit.Tests → Web.Tests and remove Unit.Tests project --- ## Test Summary - **80+ new tests** added across all PRs - **105 Web.Tests passing** (0 failures) - `DynamicProxyGenAssembly2` added to `InternalsVisibleTo` in Web.csproj for NSubstitute support ## Notable Changes - `Unit.Tests` project removed; all tests now live in `Web.Tests` - ~28 Web feature types changed from `public` to `internal` (CA1515 compliance) - All MediatR handler parameters renamed from `ct` to `cancellationToken` for clarity - `ConfigureAwait(false)` applied to all async calls in service layer - Domain and ServiceDefaults analyzer warnings resolved --- ## Checklist - [x] All sprint issues closed (#137–#143, #151) - [x] CI green (0 build errors) - [x] 105 Web.Tests passing - [x] Milestone at 100% --------- Co-authored-by: Boromir <boromir@squad.dev> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🏗️ PR Added to Squad Triage QueueThis PR has been labeled with Next steps:
|
There was a problem hiding this comment.
Pull request overview
Release PR that consolidates Sprint 6 “code quality” work: tightening Web-layer visibility, improving handler error/cancellation behavior, reorganizing/adding tests, and expanding release/docs automation + GitHub Pages content.
Changes:
- Refined Web CQRS handlers (cancellation + exception handling,
ConfigureAwait(false)), and reduced surface area by making many Web typesinternalwith updatedInternalsVisibleTo. - Added/adjusted test coverage across Web/Domain test projects and updated release workflows to run the new test projects.
- Added/updated documentation (README + GitHub Pages index + dev blog posts) and improved release/project automation workflows.
Reviewed changes
Copilot reviewed 64 out of 67 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Web.Tests/Handlers/GetBlogPostsHandlerTests.cs | Adds cache-exception test for GetBlogPosts handler. |
| tests/Web.Tests/Handlers/EditBlogPostHandlerTests.cs | Adds cache-exception test for GetBlogPostById path. |
| tests/Web.Tests/Handlers/CreateBlogPostHandlerTests.cs | Adds test asserting Create invalidates “all” but not “by id”. |
| tests/Web.Tests.Integration/Infrastructure/RedisFixture.cs | Narrows helper visibility (CreateCacheService → internal). |
| tests/Unit.Tests/Unit.Tests.csproj | Removes the Unit.Tests project file. |
| tests/Unit.Tests/Handlers/UserManagementHandlerTests.cs | Adds unit tests for UserManagement handler (currently under removed project). |
| tests/Unit.Tests/Handlers/GetBlogPostsHandlerTests.cs | Deletes prior Unit.Tests handler tests. |
| tests/Unit.Tests/Handlers/GetBlogPostByIdHandlerTests.cs | Deletes prior Unit.Tests handler tests. |
| tests/Unit.Tests/Handlers/EditBlogPostHandlerTests.cs | Deletes prior Unit.Tests handler tests. |
| tests/Unit.Tests/Handlers/DeleteBlogPostHandlerTests.cs | Deletes prior Unit.Tests handler tests. |
| tests/Unit.Tests/Handlers/CreateBlogPostHandlerTests.cs | Deletes prior Unit.Tests handler tests. |
| tests/Unit.Tests/GlobalUsings.cs | Deletes Unit.Tests global usings. |
| tests/Unit.Tests/Data/BlogPostMappingsTests.cs | Adds mapping tests (currently under removed project). |
| tests/Domain.Tests/Properties/AssemblyInfo.cs | Adds CLS compliance attribute for Domain.Tests. |
| tests/Domain.Tests/GlobalUsings.cs | Expands global usings (FluentValidation, MediatR, NSubstitute, etc.). |
| tests/Domain.Tests/Entities/BlogPostTests.cs | Adds BlogPost entity tests to Domain.Tests. |
| tests/Domain.Tests/Domain.Tests.csproj | Adds packages needed for new Domain.Tests coverage. |
| tests/Domain.Tests/Behaviors/ValidationBehaviorTests.cs | Adds ValidationBehavior pipeline behavior tests. |
| tests/Domain.Tests/Abstractions/ResultTests.cs | Adds Result/Result behavior tests. |
| src/Web/Security/RoleClaimsHelper.cs | Reduces visibility to internal. |
| src/Web/Properties/AssemblyInfo.cs | Adds CLS + expands InternalsVisibleTo list (incl. proxy gen). |
| src/Web/Infrastructure/Caching/IBlogPostCacheService.cs | Reduces interface visibility to internal. |
| src/Web/Infrastructure/Caching/CachingServiceExtensions.cs | Reduces extensions visibility to internal. |
| src/Web/Infrastructure/Caching/BlogPostCacheKeys.cs | Reduces cache keys visibility to internal. |
| src/Web/Features/UserManagement/UserManagementHandler.cs | Makes handler internal; improves cancellation/exception handling + ConfigureAwait(false). |
| src/Web/Features/UserManagement/RemoveRoleCommand.cs | Reduces visibility to internal. |
| src/Web/Features/UserManagement/GetUsersWithRolesQuery.cs | Reduces visibility to internal (query + DTO). |
| src/Web/Features/UserManagement/GetAvailableRolesQuery.cs | Reduces visibility to internal (query + DTO). |
| src/Web/Features/UserManagement/AssignRoleCommand.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/List/GetBlogPostsQuery.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/List/GetBlogPostsHandler.cs | Makes handler internal; improves cancellation/exception handling + ConfigureAwait(false). |
| src/Web/Features/BlogPosts/Edit/GetBlogPostByIdQuery.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/Edit/EditBlogPostHandler.cs | Makes handler internal; improves cancellation/exception handling + ConfigureAwait(false). |
| src/Web/Features/BlogPosts/Edit/EditBlogPostCommandValidator.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/Edit/EditBlogPostCommand.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/Delete/DeleteBlogPostHandler.cs | Makes handler internal; improves cancellation/exception handling + ConfigureAwait(false). |
| src/Web/Features/BlogPosts/Delete/DeleteBlogPostCommandValidator.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/Delete/DeleteBlogPostCommand.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/Create/CreateBlogPostHandler.cs | Makes handler internal; improves cancellation/exception handling + ConfigureAwait(false). |
| src/Web/Features/BlogPosts/Create/CreateBlogPostCommandValidator.cs | Reduces visibility to internal. |
| src/Web/Features/BlogPosts/Create/CreateBlogPostCommand.cs | Reduces visibility to internal. |
| src/Web/Data/MongoDbBlogPostRepository.cs | Reduces repository visibility to internal. |
| src/Web/Data/BlogPostDto.cs | Reduces DTO visibility to internal. |
| src/ServiceDefaults/Properties/AssemblyInfo.cs | Adds CLS compliance attribute for ServiceDefaults. |
| src/ServiceDefaults/Extensions.cs | Makes Path filtering case-insensitive in OpenTelemetry instrumentation. |
| src/Domain/Properties/AssemblyInfo.cs | Adds CLS compliance + InternalsVisibleTo for Domain.Tests. |
| src/Domain/Behaviors/ValidationBehavior.cs | Adds null-check for next delegate. |
| src/Domain/Abstractions/Result.cs | Adds ToValue() and Result<T>.FromValue() helper. |
| docs/index.html | Updates GitHub Pages landing page content to reflect current stack and releases. |
| docs/blog/index.md | Adds dev blog index (table-driven). |
| docs/blog/2026-04-24-release-v1-2-0.md | Adds release blog post for v1.2.0. |
| docs/blog/2026-04-24-release-v1-1-0.md | Adds release blog post for v1.1.0. |
| docs/blog/2026-04-20-sprint-3-e2e-tests-ci-hardening.md | Adds Sprint 3 blog post. |
| docs/blog/2026-04-20-sprint-2-cqrs-mediatr.md | Adds Sprint 2 blog post. |
| docs/blog/2026-04-20-release-v1-0-0.md | Adds v1.0.0 release blog post. |
| docs/blog/2026-04-18-myblog-project-kickoff.md | Adds Sprint 1 kickoff post. |
| docs/SQUAD-COMMANDS.md | Adds Squad commands documentation. |
| README.md | Updates README with badges, stack, structure, blog + release history sections. |
| MyBlog.slnx | Removes Unit.Tests project from the solution. |
| .squad/agents/gimli/history.md | Adds a review note about ConfigureAwait(false) behavior. |
| .squad/agents/aragorn/charter.md | Updates PR merge sequence to include Codecov check. |
| .github/workflows/squad-release.yml | Updates release workflow test execution to new project layout. |
| .github/workflows/squad-mark-released.yml | Adds manual dispatch + improves conditions/message. |
| .github/workflows/squad-insider-release.yml | Updates insider release workflow test execution to new project layout. |
| .github/workflows/release-blog.yml | Adjusts generated blog brief body formatting. |
| .github/workflows/milestone-release-decision.yml | Fixes indentation/formatting for posted issue comments/bodies. |
| .github/workflows/milestone-blog.yml | Fixes indentation/formatting for posted issue bodies. |
| | Date | Title | Tags | | ||
| |------|-------|------| | ||
| | 2026-04-24 | [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](./2026-04-24-release-v1-2-0.md) | release, v1.2.0, redis, caching, aspire, sprint-5 | | ||
| | 2026-04-24 | [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](./2026-04-24-release-v1-1-0.md) | release, v1.1.0, blazor, tailwind, theme, testing, sprint-4 | | ||
| | 2026-04-20 | [Release: v1.0.0 — Semantic Versioning and Production Readiness](./2026-04-20-release-v1-0-0.md) | release, semver, ci, devops | | ||
| | 2026-04-20 | [Sprint 3: E2E Testing and CI Hardening](./2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | e2e, aspire, ci, testing, sprint-3 | | ||
| | 2026-04-20 | [Sprint 2: CQRS and MediatR Deep Dive](./2026-04-20-sprint-2-cqrs-mediatr.md) | cqrs, mediatr, testing, domain, sprint-2 | | ||
| | 2026-04-18 | [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](./2026-04-18-myblog-project-kickoff.md) | aspire, blazor, clean-architecture, sprint-1 | |
There was a problem hiding this comment.
The blog index table won’t be picked up by blog-readme-sync.yml because the header/separator/rows use || ... (double leading pipes). The sync workflow regex matches the exact header | Date | Title | Tags | followed by the separator line and rows starting/ending with a single |. Update the table to use single-pipe markdown rows so README sync works.
| | 2026-04-24 | [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](./2026-04-24-release-v1-2-0.md) | release, v1.2.0, redis, caching, aspire, sprint-5 | | ||
| | 2026-04-24 | [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](./2026-04-24-release-v1-1-0.md) | release, v1.1.0, blazor, tailwind, theme, testing, sprint-4 | | ||
| | 2026-04-20 | [Release: v1.0.0 — Semantic Versioning and Production Readiness](./2026-04-20-release-v1-0-0.md) | release, semver, ci, devops | | ||
| | 2026-04-20 | [Sprint 3: E2E Testing and CI Hardening](./2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | e2e, aspire, ci, testing, sprint-3 | | ||
| | 2026-04-20 | [Sprint 2: CQRS and MediatR Deep Dive](./2026-04-20-sprint-2-cqrs-mediatr.md) | cqrs, mediatr, testing, domain, sprint-2 | | ||
| | 2026-04-18 | [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](./2026-04-18-myblog-project-kickoff.md) | aspire, blazor, clean-architecture, sprint-1 | | ||
|
|
||
| ## By Sprint | ||
|
|
||
| ### Sprint 1: Foundation | ||
| - [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](./2026-04-18-myblog-project-kickoff.md) | ||
|
|
||
| ### Sprint 2: CQRS & MediatR | ||
| - [Sprint 2: CQRS and MediatR Deep Dive](./2026-04-20-sprint-2-cqrs-mediatr.md) | ||
|
|
||
| ### Sprint 3: Testing & CI | ||
| - [Sprint 3: E2E Testing and CI Hardening](./2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | ||
|
|
||
| ### Sprint 4: Theme System | ||
| - [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](./2026-04-24-release-v1-1-0.md) | ||
|
|
||
| ### Sprint 5: Caching | ||
| - [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](./2026-04-24-release-v1-2-0.md) | ||
|
|
||
| ## Release Timeline | ||
|
|
||
| | Release | Date | Focus | | ||
| |---------|------|-------| | ||
| | [v1.0.0](./2026-04-20-release-v1-0-0.md) | 2026-04-20 | Semantic versioning, production readiness | | ||
| | [v1.1.0](./2026-04-24-release-v1-1-0.md) | 2026-04-24 | Blazor theme system, test reorganization | | ||
| | [v1.2.0](./2026-04-24-release-v1-2-0.md) | 2026-04-24 | Redis caching, distributed cache strategy | |
There was a problem hiding this comment.
The links in the blog index use ./... relative paths. blog-readme-sync.yml rewrites relative links by prefixing docs/blog/ but does not strip a leading ./, producing docs/blog/./... in README. Use links without the ./ prefix (e.g., (2026-04-24-release-v1-2-0.md)) to keep README links clean and consistent.
| | 2026-04-24 | [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](./2026-04-24-release-v1-2-0.md) | release, v1.2.0, redis, caching, aspire, sprint-5 | | |
| | 2026-04-24 | [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](./2026-04-24-release-v1-1-0.md) | release, v1.1.0, blazor, tailwind, theme, testing, sprint-4 | | |
| | 2026-04-20 | [Release: v1.0.0 — Semantic Versioning and Production Readiness](./2026-04-20-release-v1-0-0.md) | release, semver, ci, devops | | |
| | 2026-04-20 | [Sprint 3: E2E Testing and CI Hardening](./2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | e2e, aspire, ci, testing, sprint-3 | | |
| | 2026-04-20 | [Sprint 2: CQRS and MediatR Deep Dive](./2026-04-20-sprint-2-cqrs-mediatr.md) | cqrs, mediatr, testing, domain, sprint-2 | | |
| | 2026-04-18 | [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](./2026-04-18-myblog-project-kickoff.md) | aspire, blazor, clean-architecture, sprint-1 | | |
| ## By Sprint | |
| ### Sprint 1: Foundation | |
| - [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](./2026-04-18-myblog-project-kickoff.md) | |
| ### Sprint 2: CQRS & MediatR | |
| - [Sprint 2: CQRS and MediatR Deep Dive](./2026-04-20-sprint-2-cqrs-mediatr.md) | |
| ### Sprint 3: Testing & CI | |
| - [Sprint 3: E2E Testing and CI Hardening](./2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | |
| ### Sprint 4: Theme System | |
| - [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](./2026-04-24-release-v1-1-0.md) | |
| ### Sprint 5: Caching | |
| - [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](./2026-04-24-release-v1-2-0.md) | |
| ## Release Timeline | |
| | Release | Date | Focus | | |
| |---------|------|-------| | |
| | [v1.0.0](./2026-04-20-release-v1-0-0.md) | 2026-04-20 | Semantic versioning, production readiness | | |
| | [v1.1.0](./2026-04-24-release-v1-1-0.md) | 2026-04-24 | Blazor theme system, test reorganization | | |
| | [v1.2.0](./2026-04-24-release-v1-2-0.md) | 2026-04-24 | Redis caching, distributed cache strategy | | |
| | 2026-04-24 | [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](2026-04-24-release-v1-2-0.md) | release, v1.2.0, redis, caching, aspire, sprint-5 | | |
| | 2026-04-24 | [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](2026-04-24-release-v1-1-0.md) | release, v1.1.0, blazor, tailwind, theme, testing, sprint-4 | | |
| | 2026-04-20 | [Release: v1.0.0 — Semantic Versioning and Production Readiness](2026-04-20-release-v1-0-0.md) | release, semver, ci, devops | | |
| | 2026-04-20 | [Sprint 3: E2E Testing and CI Hardening](2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | e2e, aspire, ci, testing, sprint-3 | | |
| | 2026-04-20 | [Sprint 2: CQRS and MediatR Deep Dive](2026-04-20-sprint-2-cqrs-mediatr.md) | cqrs, mediatr, testing, domain, sprint-2 | | |
| | 2026-04-18 | [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](2026-04-18-myblog-project-kickoff.md) | aspire, blazor, clean-architecture, sprint-1 | | |
| ## By Sprint | |
| ### Sprint 1: Foundation | |
| - [MyBlog Project Kickoff: Building with .NET 10 and Clean Architecture](2026-04-18-myblog-project-kickoff.md) | |
| ### Sprint 2: CQRS & MediatR | |
| - [Sprint 2: CQRS and MediatR Deep Dive](2026-04-20-sprint-2-cqrs-mediatr.md) | |
| ### Sprint 3: Testing & CI | |
| - [Sprint 3: E2E Testing and CI Hardening](2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | |
| ### Sprint 4: Theme System | |
| - [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](2026-04-24-release-v1-1-0.md) | |
| ### Sprint 5: Caching | |
| - [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](2026-04-24-release-v1-2-0.md) | |
| ## Release Timeline | |
| | Release | Date | Focus | | |
| |---------|------|-------| | |
| | [v1.0.0](2026-04-20-release-v1-0-0.md) | 2026-04-20 | Semantic versioning, production readiness | | |
| | [v1.1.0](2026-04-24-release-v1-1-0.md) | 2026-04-24 | Blazor theme system, test reorganization | | |
| | [v1.2.0](2026-04-24-release-v1-2-0.md) | 2026-04-24 | Redis caching, distributed cache strategy | |
| <!-- BLOG_START --> | ||
| | Date | Title | Tags | | ||
| |------|-------|------| | ||
| | 2026-04-24 | [Release: v1.2.0 — Redis Caching and L1/L2 Cache Strategy](docs/blog/2026-04-24-release-v1-2-0.md) | release, v1.2.0, redis, caching, aspire, sprint-5 | | ||
| | 2026-04-24 | [Release: v1.1.0 — Blazor Theme System with TailwindCSS v4](docs/blog/2026-04-24-release-v1-1-0.md) | release, v1.1.0, blazor, tailwind, theme, testing, sprint-4 | | ||
| | 2026-04-20 | [Release: v1.0.0 — Semantic Versioning and Production Readiness](docs/blog/2026-04-20-release-v1-0-0.md) | release, semver, ci, devops | | ||
| | 2026-04-20 | [Sprint 3: E2E Testing and CI Hardening](docs/blog/2026-04-20-sprint-3-e2e-tests-ci-hardening.md) | e2e, aspire, ci, testing, sprint-3 | | ||
| | 2026-04-20 | [Sprint 2: CQRS and MediatR Deep Dive](docs/blog/2026-04-20-sprint-2-cqrs-mediatr.md) | cqrs, mediatr, testing, domain, sprint-2 | | ||
| <!-- BLOG_END --> |
There was a problem hiding this comment.
The Dev Blog table header here uses || Date | Title | Tags | (double leading pipes). If docs/blog/index.md is fixed to the single-pipe format expected by blog-readme-sync.yml, this section will be overwritten on the next sync anyway. Consider matching the expected single-pipe header/rows now to avoid a broken-looking table until the sync runs.
| public static Result<T> FromValue(T? value) | ||
| { | ||
| if (value is null) | ||
| return Fail("Value cannot be null."); |
There was a problem hiding this comment.
Result.FromValue<T>(...) fails with the message "Provided value is null.", but the newly added Result<T>.FromValue(...) fails with a different message ("Value cannot be null."). Having two FromValue APIs with inconsistent null-error messages makes failures harder to reason about and can lead to brittle tests. Consider reusing the same message (or delegating one implementation to the other) so null handling is consistent.
| return Fail("Value cannot be null."); | |
| return Fail("Provided value is null."); |
| dotnet test tests/Domain.Tests --configuration Release --no-build --no-restore \ | ||
| --logger "trx;LogFileName=domain-results.trx" | ||
| dotnet test tests/Web.Tests --configuration Release --no-build --no-restore \ | ||
| --logger "trx;LogFileName=web-results.trx" |
There was a problem hiding this comment.
The release workflow now runs Architecture/Domain/Web/Web.Integration tests, but it still skips tests/Web.Tests.Bunit (which is part of the repo’s main squad-test.yml suite). Consider adding the bUnit project here as well so releases can’t ship with failing component tests.
| --logger "trx;LogFileName=web-results.trx" | |
| --logger "trx;LogFileName=web-results.trx" | |
| dotnet test tests/Web.Tests.Bunit --configuration Release --no-build --no-restore \ | |
| --logger "trx;LogFileName=web-bunit-results.trx" |
| @@ -9,7 +9,6 @@ | |||
| <Project Path="tests/AppHost.Tests/AppHost.Tests.csproj" /> | |||
| <Project Path="tests/Architecture.Tests/Architecture.Tests.csproj" /> | |||
| <Project Path="tests/Domain.Tests/Domain.Tests.csproj" /> | |||
There was a problem hiding this comment.
Unit.Tests is removed from the solution, but this PR still adds/keeps source files under tests/Unit.Tests/. Without a Unit.Tests.csproj referenced by the solution/CI, those tests won’t compile or run. Either reintroduce the project reference or move these tests into the active test projects (e.g., Domain.Tests/Web.Tests) and delete the orphaned folder.
| <Project Path="tests/Domain.Tests/Domain.Tests.csproj" /> | |
| <Project Path="tests/Domain.Tests/Domain.Tests.csproj" /> | |
| <Project Path="tests/Unit.Tests/Unit.Tests.csproj" /> |
| public class UserManagementHandlerTests | ||
| { | ||
| private readonly IConfiguration _config = Substitute.For<IConfiguration>(); | ||
| private readonly IHttpClientFactory _httpFactory = Substitute.For<IHttpClientFactory>(); | ||
| private readonly UserManagementHandler _handler; | ||
|
|
||
| public UserManagementHandlerTests() | ||
| { | ||
| _config["Auth0:ManagementApiDomain"].Returns((string?)null); | ||
| _handler = new UserManagementHandler(_config, _httpFactory); | ||
| } |
There was a problem hiding this comment.
This test file lives under tests/Unit.Tests/, but tests/Unit.Tests/Unit.Tests.csproj was removed in this PR and the solution no longer references Unit.Tests. As-is, these tests won’t be built or executed by CI. Move them into an active test project (e.g., tests/Web.Tests or tests/Domain.Tests) or restore the Unit.Tests project.
| namespace Unit.Data; | ||
|
|
||
| public class BlogPostMappingsTests | ||
| { | ||
| [Fact] | ||
| public void ToDto_MapsAllFields_Correctly() | ||
| { | ||
| // Arrange | ||
| var post = BlogPost.Create("Test Title", "Test Content", "Test Author"); | ||
|
|
||
| // Act |
There was a problem hiding this comment.
This test file is under tests/Unit.Tests/, but the Unit.Tests project file was removed and the solution no longer includes it. These tests will be orphaned (not compiled/run) unless they’re moved into an existing test project (e.g., tests/Web.Tests for Web mappings) or Unit.Tests is restored.
| ### IBlogPostCacheService | ||
| ```csharp | ||
| public interface IBlogPostCacheService | ||
| { | ||
| Task<IEnumerable<BlogPostResponse>> GetAllBlogPostsAsync(CancellationToken cancellationToken); | ||
| Task<BlogPostResponse?> GetBlogPostByIdAsync(int id, CancellationToken cancellationToken); | ||
| Task InvalidateAsync(int? blogPostId = null); | ||
| } | ||
| ``` | ||
|
|
||
| ### Two-Tier Implementation | ||
| ```csharp | ||
| public class BlogPostCacheService : IBlogPostCacheService | ||
| { | ||
| private readonly IMemoryCache _l1Cache; | ||
| private readonly IDistributedCache _l2Cache; | ||
| private readonly IBlogPostRepository _repository; | ||
|
|
||
| public async Task<IEnumerable<BlogPostResponse>> GetAllBlogPostsAsync(CancellationToken cancellationToken) | ||
| { | ||
| const string key = "all_blog_posts"; | ||
|
|
||
| // Check L1 | ||
| if (_l1Cache.TryGetValue(key, out var cached)) | ||
| return cached as IEnumerable<BlogPostResponse>; | ||
|
|
||
| // Check L2 | ||
| var json = await _l2Cache.GetStringAsync(key, cancellationToken); | ||
| if (json != null) | ||
| { | ||
| var result = JsonSerializer.Deserialize<IEnumerable<BlogPostResponse>>(json); | ||
| _l1Cache.Set(key, result, TimeSpan.FromHours(1)); | ||
| return result; | ||
| } | ||
|
|
||
| // Fetch from DB, populate both caches | ||
| var posts = await _repository.GetAllAsync(cancellationToken); | ||
| var response = posts.Select(p => new BlogPostResponse { /* ... */ }); | ||
| var json = JsonSerializer.Serialize(response); | ||
| await _l2Cache.SetStringAsync(key, json, new DistributedCacheEntryOptions | ||
| { | ||
| AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) | ||
| }, cancellationToken); | ||
| _l1Cache.Set(key, response, TimeSpan.FromHours(1)); | ||
|
|
||
| return response; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Query Handler Integration | ||
| ```csharp | ||
| public class GetAllBlogPostsQueryHandler : IRequestHandler<GetAllBlogPostsQuery, IEnumerable<BlogPostResponse>> | ||
| { | ||
| private readonly IBlogPostCacheService _cacheService; | ||
|
|
||
| public async Task<IEnumerable<BlogPostResponse>> Handle(GetAllBlogPostsQuery request, CancellationToken cancellationToken) | ||
| { | ||
| return await _cacheService.GetAllBlogPostsAsync(cancellationToken); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Invalidation on Mutation | ||
| ```csharp | ||
| public class CreateBlogPostCommandHandler : IRequestHandler<CreateBlogPostCommand, BlogPostResponse> | ||
| { | ||
| private readonly IBlogPostRepository _repository; | ||
| private readonly IBlogPostCacheService _cacheService; | ||
|
|
||
| public async Task<BlogPostResponse> Handle(CreateBlogPostCommand request, CancellationToken cancellationToken) | ||
| { | ||
| var entity = await _repository.CreateAsync(/* ... */, cancellationToken); | ||
| await _cacheService.InvalidateAsync(); // Clear all blog post caches | ||
| return MapToResponse(entity); | ||
| } | ||
| } | ||
| ``` |
There was a problem hiding this comment.
The release blog post’s IBlogPostCacheService / handler integration code samples don’t match the actual code in this PR (e.g., different method names/signatures like GetAllBlogPostsAsync, InvalidateAsync, and handler names like GetAllBlogPostsQueryHandler). If these snippets are meant to document the current implementation, they should be updated to reflect the real GetOrFetchAllAsync/GetOrFetchByIdAsync + InvalidateAllAsync/InvalidateByIdAsync API to avoid confusing readers.
| dotnet test tests/Domain.Tests --configuration Release --no-build --no-restore \ | ||
| --logger "trx;LogFileName=domain-results.trx" | ||
| dotnet test tests/Web.Tests --configuration Release --no-build --no-restore \ | ||
| --logger "trx;LogFileName=web-results.trx" |
There was a problem hiding this comment.
The insider release workflow runs Architecture/Domain/Web/Web.Integration tests but skips tests/Web.Tests.Bunit (part of the repo’s standard test suite). Consider adding the bUnit project so pre-releases also validate component tests.
| --logger "trx;LogFileName=web-results.trx" | |
| --logger "trx;LogFileName=web-results.trx" | |
| dotnet test tests/Web.Tests.Bunit --configuration Release --no-build --no-restore \ | |
| --logger "trx;LogFileName=web-bunit-results.trx" |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #161 +/- ##
==========================================
- Coverage 76.93% 72.12% -4.82%
==========================================
Files 43 43
Lines 672 721 +49
Branches 111 112 +1
==========================================
+ Hits 517 520 +3
- Misses 105 150 +45
- Partials 50 51 +1
🚀 New features to boost your workflow:
|
Release PR: merge Sprint 6 code quality improvements into main for tagging and release.