ci: add CI workflow with build, test, and coverage reporting #4

Merged
bjoern merged 3 commits from ci/add-ci-workflow into main 2026-06-28 11:52:58 +02:00
Member

Summary

Adds .github/workflows/ci.yml — a two-job CI pipeline based on the TeamAI admin snippet, adapted to this repo's layout and extended with code coverage reporting.

Jobs

build

Checkout → dotnet restoredotnet build -c Release --no-restore.
Fast-fails on compile errors without spinning up the test runner. All dotnet steps set working-directory: backend since the solution (DoujinManager.slnx) lives there.

test (needs: build)

Checkout → restore → build → dotnet test --no-build --collect:"XPlat Code Coverage" → merge cobertura XML → upload HTML report as artifact.

  • Coverage: coverlet.collector is already a transitive reference in every test project, so --collect:"XPlat Code Coverage" produces coverage.cobertura.xml per test project with zero extra wiring.
  • Merging: the per-project cobertura files are merged into a single HTML report via dotnet-reportgenerator-globaltool (installed inline, pinned to 5.4.4).
  • Artifact: the merged coverage-report/ directory is uploaded as a build artifact (coverage-report), downloadable from the Actions run page. if-no-files-found: error catches the case where coverage collection silently produced nothing.

Verification

Built and tested locally against main HEAD before opening this PR:

dotnet restore
dotnet build --configuration Release --no-restore   # 0 warnings, 0 errors
dotnet test  --configuration Release --no-build      # 45/45 passed

Coverlet attachments confirmed present per test project:

  • ApplicationCore.Tests/TestResults/<guid>/coverage.cobertura.xml
  • Infrastructure.Tests/TestResults/<guid>/coverage.cobertura.xml
  • IntegrationTests/TestResults/<guid>/coverage.cobertura.xml
  • RestAdapter.Tests/TestResults/<guid>/coverage.cobertura.xml

Notes

  • Triggered on push to main and pull_request against main (per the admin snippet).
  • runs-on: dotnet — the self-hosted runner label provided by the admin.
  • No changes to source, tests, or project files — CI-only.
## Summary Adds `.github/workflows/ci.yml` — a two-job CI pipeline based on the TeamAI admin snippet, adapted to this repo's layout and extended with code coverage reporting. ## Jobs ### `build` Checkout → `dotnet restore` → `dotnet build -c Release --no-restore`. Fast-fails on compile errors without spinning up the test runner. All `dotnet` steps set `working-directory: backend` since the solution (`DoujinManager.slnx`) lives there. ### `test` (needs: build) Checkout → restore → build → `dotnet test --no-build --collect:"XPlat Code Coverage"` → merge cobertura XML → upload HTML report as artifact. - **Coverage**: coverlet.collector is already a transitive reference in every test project, so `--collect:"XPlat Code Coverage"` produces `coverage.cobertura.xml` per test project with zero extra wiring. - **Merging**: the per-project cobertura files are merged into a single HTML report via `dotnet-reportgenerator-globaltool` (installed inline, pinned to 5.4.4). - **Artifact**: the merged `coverage-report/` directory is uploaded as a build artifact (`coverage-report`), downloadable from the Actions run page. `if-no-files-found: error` catches the case where coverage collection silently produced nothing. ## Verification Built and tested locally against `main` HEAD before opening this PR: ``` dotnet restore dotnet build --configuration Release --no-restore # 0 warnings, 0 errors dotnet test --configuration Release --no-build # 45/45 passed ``` Coverlet attachments confirmed present per test project: - `ApplicationCore.Tests/TestResults/<guid>/coverage.cobertura.xml` - `Infrastructure.Tests/TestResults/<guid>/coverage.cobertura.xml` - `IntegrationTests/TestResults/<guid>/coverage.cobertura.xml` - `RestAdapter.Tests/TestResults/<guid>/coverage.cobertura.xml` ## Notes - Triggered on `push` to `main` and `pull_request` against `main` (per the admin snippet). - `runs-on: dotnet` — the self-hosted runner label provided by the admin. - No changes to source, tests, or project files — CI-only.
ci: add CI workflow with build, test, and coverage reporting
Some checks failed
CI / build (pull_request) Successful in 15s
CI / test (pull_request) Failing after 29s
f91a787674
Two-job pipeline: build (fast fail on compile errors) then test
(runs xUnit with coverlet, merges cobertura XML via reportgenerator
into an HTML report uploaded as a build artifact). Solution lives in
backend/, so working-directory is set there on every dotnet step.
ci: use Forgejo upload-artifact fork (GitHub's v4 rejects GHES backends)
All checks were successful
CI / build (pull_request) Successful in 14s
CI / test (pull_request) Successful in 25s
ad7e1d6378
ci: coverage comment on PR + fix artifact .zip download name
All checks were successful
CI / build (pull_request) Successful in 15s
CI / test (pull_request) Successful in 21s
1aab73e17c

Summary

Summary
Generated on: 06/28/2026 - 09:43:35
Coverage date: 06/28/2026 - 09:43:31 - 06/28/2026 - 09:43:33
Parser: MultiReport (4x Cobertura)
Assemblies: 3
Classes: 49
Files: 49
Line coverage: 22.6% (500 of 2206)
Covered lines: 500
Uncovered lines: 1706
Coverable lines: 2206
Total lines: 3545
Branch coverage: 22.9% (73 of 318)
Covered branches: 73
Total branches: 318
Method coverage: Feature is only available for sponsors

Coverage

DoujinManager.ApplicationCore - 76.7%
Name Line Branch
DoujinManager.ApplicationCore 76.7% ****
DoujinManager.ApplicationCore.Entities.Chapter 87.5%
DoujinManager.ApplicationCore.Entities.Circle 0%
DoujinManager.ApplicationCore.Entities.Doujin 100%
DoujinManager.ApplicationCore.Entities.DoujinCircle 0%
DoujinManager.ApplicationCore.Entities.DoujinPerson 80%
DoujinManager.ApplicationCore.Entities.DoujinTag 75%
DoujinManager.ApplicationCore.Entities.ImageFile 90.9%
DoujinManager.ApplicationCore.Entities.Page 70%
DoujinManager.ApplicationCore.Entities.Person 85.7%
DoujinManager.ApplicationCore.Entities.Tag 100%
DoujinManager.ApplicationCore.Entities.Title 83.3%
DoujinManager.ApplicationCore.Entities.Variant 83.3%
DoujinManager.ApplicationCore.Ids.ChapterId 66.6%
DoujinManager.ApplicationCore.Ids.CircleId 66.6%
DoujinManager.ApplicationCore.Ids.DoujinId 100%
DoujinManager.ApplicationCore.Ids.ImageFileId 66.6%
DoujinManager.ApplicationCore.Ids.PageId 66.6%
DoujinManager.ApplicationCore.Ids.PersonId 66.6%
DoujinManager.ApplicationCore.Ids.TagId 66.6%
DoujinManager.ApplicationCore.Ids.TitleId 66.6%
DoujinManager.ApplicationCore.Ids.VariantId 66.6%
DoujinManager.ApplicationCore.Ports.ExtractedImage 100%
DoujinManager.ApplicationCore.Ports.ImageInspection 100%
DoujinManager.Infrastructure - 21.8%
Name Line Branch
DoujinManager.Infrastructure 21.8% 73%
DoujinManager.Infrastructure.Archives.ZipExtractor 100% 87.5%
DoujinManager.Infrastructure.Data.Configurations.ChapterConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.CircleConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.DoujinCircleConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.DoujinConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.DoujinPersonConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.DoujinTagConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.ImageFileConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.PageConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.PersonConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.TagConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.TitleConfiguration 100%
DoujinManager.Infrastructure.Data.Configurations.VariantConfiguration 100%
DoujinManager.Infrastructure.Data.DoujinManagerDbContext 62.5%
DoujinManager.Infrastructure.Data.GuidIdGenerator 0%
DoujinManager.Infrastructure.Data.Migrations.DoujinManagerDbContextModelSna
pshot
0%
DoujinManager.Infrastructure.Data.Migrations.InitialCreate 0%
DoujinManager.Infrastructure.Data.ModelBuilderExtensions 50%
DoujinManager.Infrastructure.Data.StronglyTypedIdConverterFactory 69.2%
DoujinManager.Infrastructure.Images.SkiaSharpImageInspector 88.2% 69.3%
DoujinManager.Infrastructure.Images.SkiaSharpThumbnailGenerator 94.5% 66.6%
DoujinManager.Infrastructure.Storage.FilesystemImageStorage 100% 100%
DoujinManager.Infrastructure.Storage.FilesystemThumbnailStorage 95% 75%
DoujinManager.Server - 0%
Name Line Branch
DoujinManager.Server 0% 0%
Microsoft.AspNetCore.OpenApi.Generated 0% 0%
Program 0% 0%
System.Runtime.CompilerServices 0%
<!-- coverage-comment --> # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 06/28/2026 - 09:43:35 | | Coverage date: | 06/28/2026 - 09:43:31 - 06/28/2026 - 09:43:33 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 3 | | Classes: | 49 | | Files: | 49 | | **Line coverage:** | 22.6% (500 of 2206) | | Covered lines: | 500 | | Uncovered lines: | 1706 | | Coverable lines: | 2206 | | Total lines: | 3545 | | **Branch coverage:** | 22.9% (73 of 318) | | Covered branches: | 73 | | Total branches: | 318 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>DoujinManager.ApplicationCore - 76.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**DoujinManager.ApplicationCore**|**76.7%**|****| |DoujinManager.ApplicationCore.Entities.Chapter|87.5%|| |DoujinManager.ApplicationCore.Entities.Circle|0%|| |DoujinManager.ApplicationCore.Entities.Doujin|100%|| |DoujinManager.ApplicationCore.Entities.DoujinCircle|0%|| |DoujinManager.ApplicationCore.Entities.DoujinPerson|80%|| |DoujinManager.ApplicationCore.Entities.DoujinTag|75%|| |DoujinManager.ApplicationCore.Entities.ImageFile|90.9%|| |DoujinManager.ApplicationCore.Entities.Page|70%|| |DoujinManager.ApplicationCore.Entities.Person|85.7%|| |DoujinManager.ApplicationCore.Entities.Tag|100%|| |DoujinManager.ApplicationCore.Entities.Title|83.3%|| |DoujinManager.ApplicationCore.Entities.Variant|83.3%|| |DoujinManager.ApplicationCore.Ids.ChapterId|66.6%|| |DoujinManager.ApplicationCore.Ids.CircleId|66.6%|| |DoujinManager.ApplicationCore.Ids.DoujinId|100%|| |DoujinManager.ApplicationCore.Ids.ImageFileId|66.6%|| |DoujinManager.ApplicationCore.Ids.PageId|66.6%|| |DoujinManager.ApplicationCore.Ids.PersonId|66.6%|| |DoujinManager.ApplicationCore.Ids.TagId|66.6%|| |DoujinManager.ApplicationCore.Ids.TitleId|66.6%|| |DoujinManager.ApplicationCore.Ids.VariantId|66.6%|| |DoujinManager.ApplicationCore.Ports.ExtractedImage|100%|| |DoujinManager.ApplicationCore.Ports.ImageInspection|100%|| </details> <details><summary>DoujinManager.Infrastructure - 21.8%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**DoujinManager.Infrastructure**|**21.8%**|**73%**| |DoujinManager.Infrastructure.Archives.ZipExtractor|100%|87.5%| |DoujinManager.Infrastructure.Data.Configurations.ChapterConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.CircleConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.DoujinCircleConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.DoujinConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.DoujinPersonConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.DoujinTagConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.ImageFileConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.PageConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.PersonConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.TagConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.TitleConfiguration|100%|| |DoujinManager.Infrastructure.Data.Configurations.VariantConfiguration|100%|| |DoujinManager.Infrastructure.Data.DoujinManagerDbContext|62.5%|| |DoujinManager.Infrastructure.Data.GuidIdGenerator|0%|| |DoujinManager.Infrastructure.Data.Migrations.DoujinManagerDbContextModelSna<br/>pshot|0%|| |DoujinManager.Infrastructure.Data.Migrations.InitialCreate|0%|| |DoujinManager.Infrastructure.Data.ModelBuilderExtensions|50%|| |DoujinManager.Infrastructure.Data.StronglyTypedIdConverterFactory|69.2%|| |DoujinManager.Infrastructure.Images.SkiaSharpImageInspector|88.2%|69.3%| |DoujinManager.Infrastructure.Images.SkiaSharpThumbnailGenerator|94.5%|66.6%| |DoujinManager.Infrastructure.Storage.FilesystemImageStorage|100%|100%| |DoujinManager.Infrastructure.Storage.FilesystemThumbnailStorage|95%|75%| </details> <details><summary>DoujinManager.Server - 0%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**DoujinManager.Server**|**0%**|**0%**| |Microsoft.AspNetCore.OpenApi.Generated|0%|0%| |Program|0%|0%| |System.Runtime.CompilerServices|0%|| </details>
bjoern merged commit 37dd456152 into main 2026-06-28 11:52:58 +02:00
bjoern deleted branch ci/add-ci-workflow 2026-06-28 11:52:58 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/doujin-manager!4
No description provided.