Conversation
Reviewer's GuideAdds a new GitHub Actions workflow that automates versioning, build, tests with coverage, code quality analysis, packaging, NuGet publishing, and GitHub Releases on pushes to main. Flow diagram for build, test, package, and release pipelineflowchart TB
Trigger["Push to main branch"] --> StartJob["Start Release job"]
subgraph Setup["Environment setup"]
Checkout["Checkout repository (fetch-depth 0)"]
DotNet["Setup .NET 10 SDK"]
Java["Setup Java 21"]
GitVersionInstall["Install GitVersion"]
SonarTool["Install dotnet-sonarscanner"]
StartJob --> Checkout --> DotNet --> Java --> GitVersionInstall --> SonarTool
end
subgraph Versioning["Version resolution"]
GitVersionRun["Run GitVersion (compute semVer)"]
PatchProps["Patch *.props versions with semVer"]
ResolveSln["Resolve solution name (*.sln)"]
SonarTool --> GitVersionRun --> PatchProps --> ResolveSln
end
subgraph AnalysisBuildTest["Code analysis, build, tests"]
Restore["dotnet restore"]
SonarBegin["SonarCloud begin scan"]
Build["dotnet build --no-restore"]
Test["dotnet test for each Tests/*.csproj with coverage"]
PublishTestResults["Upload JUnit test results as artifact"]
SonarEnd["SonarCloud end scan"]
ResolveSln --> Restore --> SonarBegin --> Build --> Test --> PublishTestResults --> SonarEnd
end
subgraph CoverageReporting["Coverage reporting"]
ToCodecov["Upload coverage to Codecov"]
ToCodacy["Upload coverage to Codacy"]
SonarEnd --> ToCodecov --> ToCodacy
end
subgraph Packaging["Collect and package artifacts"]
CollectArtifacts["Collect binaries and coverage into Artifacts/"]
ZipArchives["Create per-TFM and coverage zip archives in Zips/"]
CollectNuGet["Collect .nupkg and .snupkg into Zips/"]
ToCodacy --> CollectArtifacts --> ZipArchives --> CollectNuGet
end
subgraph PublishAndRelease["Publish and release"]
PushNuGet["Push .nupkg to NuGet.org (skip-duplicate)"]
TagVersion["Create and push git tag v<semVer>"]
CreateRelease["Create GitHub Release with Zips/* and autogenerated notes"]
CollectNuGet --> PushNuGet --> TagVersion --> CreateRelease
end
CreateRelease --> End["Release pipeline complete"]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughA new GitHub Actions workflow for automated release management on the Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The CouchDB service is configured with hardcoded credentials in the workflow; consider moving the username/password to encrypted GitHub Secrets and referencing them via
${{ secrets.* }}to avoid exposing credentials in the repo. - The workflow references
net9.0(e.g., inTARGET_FRAMEWORKSand coverage file paths) but only installs the.NET 10.0.xSDK; ensure the .NET SDK version(s) required to build/test all target frameworks (includingnet9.0) are explicitly installed withactions/setup-dotnet.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The CouchDB service is configured with hardcoded credentials in the workflow; consider moving the username/password to encrypted GitHub Secrets and referencing them via `${{ secrets.* }}` to avoid exposing credentials in the repo.
- The workflow references `net9.0` (e.g., in `TARGET_FRAMEWORKS` and coverage file paths) but only installs the `.NET 10.0.x` SDK; ensure the .NET SDK version(s) required to build/test all target frameworks (including `net9.0`) are explicitly installed with `actions/setup-dotnet`.
## Individual Comments
### Comment 1
<location path=".github/workflows/release.yml" line_range="128-136" />
<code_context>
+ run: dotnet build --no-restore --verbosity minimal ${{ steps.solution.outputs.name }}.sln
+
+ # ── Test + coverage ───────────────────────────────────────────────────────
+ - name: Test with coverage
+ run: |
+ for TEST_PROJ in $(find ./Tests -name "*.csproj" -type f); do
+ dotnet test "$TEST_PROJ" \
+ --no-build \
+ --verbosity minimal \
+ /p:CollectCoverage=true \
+ /p:CoverletOutputFormat='"cobertura,opencover,lcov"' \
+ --logger:"junit;LogFilePath=test-results.xml"
+ done
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Coverage report file naming may not match the hardcoded paths used later for Sonar/Codecov/Codacy.
`dotnet test` is run with Coverlet enabled but without an explicit `CoverletOutput` (or per-framework outputs). With multiple TFMs/projects, Coverlet typically generates framework/project-specific filenames (e.g. `coverage.net9.0.opencover.xml`), while later steps assume a single fixed path (`Tests/${SLN}.Tests/coverage.net9.0.opencover.xml`) for SonarCloud/Codecov/Codacy. This mismatch can cause those tools to miss or fail on coverage. Consider either setting `CoverletOutput` explicitly per test project/TFM to match the expected path, or using globs and merging coverage reports before passing them on.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| - name: Test with coverage | ||
| run: | | ||
| for TEST_PROJ in $(find ./Tests -name "*.csproj" -type f); do | ||
| dotnet test "$TEST_PROJ" \ | ||
| --no-build \ | ||
| --verbosity minimal \ | ||
| /p:CollectCoverage=true \ | ||
| /p:CoverletOutputFormat='"cobertura,opencover,lcov"' \ | ||
| --logger:"junit;LogFilePath=test-results.xml" |
There was a problem hiding this comment.
issue (bug_risk): Coverage report file naming may not match the hardcoded paths used later for Sonar/Codecov/Codacy.
dotnet test is run with Coverlet enabled but without an explicit CoverletOutput (or per-framework outputs). With multiple TFMs/projects, Coverlet typically generates framework/project-specific filenames (e.g. coverage.net9.0.opencover.xml), while later steps assume a single fixed path (Tests/${SLN}.Tests/coverage.net9.0.opencover.xml) for SonarCloud/Codecov/Codacy. This mismatch can cause those tools to miss or fail on coverage. Consider either setting CoverletOutput explicitly per test project/TFM to match the expected path, or using globs and merging coverage reports before passing them on.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
.github/workflows/release.yml (1)
225-250: The package-on-build configuration is already in place; consider hardening the publish loop for safety.
Directory.Build.propsalready has<GeneratePackageOnBuild>true</GeneratePackageOnBuild>enabled, so packages will be generated during the build step. However, the publish loop should still guard against empty glob expansion:Defensive guard for the publish loop
- name: Push to NuGet.org run: | - for PKG in Zips/*.nupkg; do + shopt -s nullglob + PACKAGES=(Zips/*.nupkg) + [ ${`#PACKAGES`[@]} -gt 0 ] || { echo "No .nupkg files found in Zips/"; exit 1; } + for PKG in "${PACKAGES[@]}"; do echo "Publishing $PKG …" dotnet nuget push "$PKG" \ --api-key "${{ secrets.NUGET_TOKEN }}" \ --source https://api.nuget.org/v3/index.json \ --skip-duplicate done🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release.yml around lines 225 - 250, The "Push to NuGet.org" publish loop (step name "Push to NuGet.org", loop variable PKG over Zips/*.nupkg) currently risks iterating a literal pattern when no packages exist; add a defensive guard before the loop to ensure there are matching files (e.g., test with compgen -G "Zips/*.nupkg" or ls/check -e) and skip/passthrough the publish step when none are found so the dotnet nuget push loop only runs when real .nupkg files exist.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release.yml:
- Line 121: The workflow currently passes a hard-coded report path
"/d:sonar.cs.opencover.reportsPaths=Tests/${SLN}.Tests/coverage.net9.0.opencover.xml"
which only includes the `${SLN}.Tests` project; update these reporter/copy
arguments (the Sonar `sonar.cs.opencover.reportsPaths`, the Codecov/Codacy
upload and any copy steps referenced at the same locations) to accept a glob
that aggregates all test project coverage files such as
`Tests/**/coverage.net9.0.opencover.xml` (or build the list from the
`Tests/**/*.csproj` step), ensuring the Sonar/Codecov/Codacy parameters use that
aggregated list instead of the single `Tests/${SLN}.Tests/...` path; apply the
same change to the other occurrences mentioned (the blocks around the other
lines referenced) so all test projects’ coverage is uploaded.
- Line 27: The PACKAGE_PROJECTS environment list in the release workflow is
missing the CouchDB project, so update the PACKAGE_PROJECTS value (the variable
named PACKAGE_PROJECTS in the release.yml workflow) to include "CouchDB" among
the space-separated projects used by the binary/NuGet collection and publish
loops; ensure the entry matches the project folder/name (e.g., add CouchDB to
the existing string "Configuration ElasticSearch Elmah EventLog I18n.PtBr
Log4Net RabbitMQ Redis Utils") so the
Src/CrispyWaffle.CouchDB/CrispyWaffle.CouchDB.csproj artifacts are picked up and
published.
- Line 28: The TARGET_FRAMEWORKS value in the release workflow is out of sync
with the project files: update the TARGET_FRAMEWORKS variable (the symbol
TARGET_FRAMEWORKS) from "netstandard2.0 netstandard2.1 net6.0 net9.0" to include
net8.0 instead of net6.0 (e.g. "netstandard2.0 netstandard2.1 net8.0 net9.0") so
the artifact creation loop picks up the real net8.0 build outputs rather than
creating empty net6.0 zips.
- Around line 255-261: The "Tag release version" step currently always runs git
tag -a "$VERSION" which will fail on reruns if the tag already exists; update
the step to be idempotent by detecting whether the tag already exists (e.g., use
git ls-remote --tags origin "$VERSION" or git rev-parse -q --verify
"refs/tags/$VERSION") and only create and push the tag if it is missing,
otherwise skip tagging; reference the VERSION variable, the git tag -a command
and the git push origin "$VERSION" invocation when implementing the conditional
check.
---
Nitpick comments:
In @.github/workflows/release.yml:
- Around line 225-250: The "Push to NuGet.org" publish loop (step name "Push to
NuGet.org", loop variable PKG over Zips/*.nupkg) currently risks iterating a
literal pattern when no packages exist; add a defensive guard before the loop to
ensure there are matching files (e.g., test with compgen -G "Zips/*.nupkg" or
ls/check -e) and skip/passthrough the publish step when none are found so the
dotnet nuget push loop only runs when real .nupkg files exist.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e274053e-9aa8-47eb-9669-7d08f475f686
📒 Files selected for processing (1)
.github/workflows/release.yml
| # ── Projects to package (mirrors AppVeyor $PROJECTS) ────────────────────── | ||
| # Update this list if you add or remove sub-projects. | ||
| env: | ||
| PACKAGE_PROJECTS: "Configuration ElasticSearch Elmah EventLog I18n.PtBr Log4Net RabbitMQ Redis Utils" |
There was a problem hiding this comment.
Add CouchDB to PACKAGE_PROJECTS.
Src/CrispyWaffle.CouchDB/CrispyWaffle.CouchDB.csproj:1-10 already carries package metadata, but this list omits it. The binary and NuGet loops below therefore never collect or publish the CouchDB artifacts.
Suggested fix
- PACKAGE_PROJECTS: "Configuration ElasticSearch Elmah EventLog I18n.PtBr Log4Net RabbitMQ Redis Utils"
+ PACKAGE_PROJECTS: "Configuration CouchDB ElasticSearch Elmah EventLog I18n.PtBr Log4Net RabbitMQ Redis Utils"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml at line 27, The PACKAGE_PROJECTS environment
list in the release workflow is missing the CouchDB project, so update the
PACKAGE_PROJECTS value (the variable named PACKAGE_PROJECTS in the release.yml
workflow) to include "CouchDB" among the space-separated projects used by the
binary/NuGet collection and publish loops; ensure the entry matches the project
folder/name (e.g., add CouchDB to the existing string "Configuration
ElasticSearch Elmah EventLog I18n.PtBr Log4Net RabbitMQ Redis Utils") so the
Src/CrispyWaffle.CouchDB/CrispyWaffle.CouchDB.csproj artifacts are picked up and
published.
| # Update this list if you add or remove sub-projects. | ||
| env: | ||
| PACKAGE_PROJECTS: "Configuration ElasticSearch Elmah EventLog I18n.PtBr Log4Net RabbitMQ Redis Utils" | ||
| TARGET_FRAMEWORKS: "netstandard2.0 netstandard2.1 net6.0 net9.0" |
There was a problem hiding this comment.
Sync TARGET_FRAMEWORKS with Directory.Build.props.
Directory.Build.props:2-4 and Src/CrispyWaffle/CrispyWaffle.csproj:1-10 currently build netstandard2.0;netstandard2.1;net8.0;net9.0. Keeping net6.0 here means the artifact loops below skip the real net8.0 output and still create empty net6.0 release zips.
Suggested fix
- TARGET_FRAMEWORKS: "netstandard2.0 netstandard2.1 net6.0 net9.0"
+ TARGET_FRAMEWORKS: "netstandard2.0 netstandard2.1 net8.0 net9.0"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml at line 28, The TARGET_FRAMEWORKS value in the
release workflow is out of sync with the project files: update the
TARGET_FRAMEWORKS variable (the symbol TARGET_FRAMEWORKS) from "netstandard2.0
netstandard2.1 net6.0 net9.0" to include net8.0 instead of net6.0 (e.g.
"netstandard2.0 netstandard2.1 net8.0 net9.0") so the artifact creation loop
picks up the real net8.0 build outputs rather than creating empty net6.0 zips.
| "/d:sonar.branch.name=main" \ | ||
| "/d:sonar.exclusions=**/bin/**/*,**/obj/**/*" \ | ||
| "/d:sonar.coverage.exclusions=**/${SLN}.Tests/**,**/*Tests.cs" \ | ||
| "/d:sonar.cs.opencover.reportsPaths=Tests/${SLN}.Tests/coverage.net9.0.opencover.xml" |
There was a problem hiding this comment.
Aggregate coverage from all test projects, not just ${SLN}.Tests.
The test step runs every Tests/**/*.csproj, but all reporting/copy steps only read Tests/${SLN}.Tests/.... The repo already has Tests/CrispyWaffle.IntegrationTests, so its coverage will never reach SonarCloud, Codecov, Codacy, or the coverage bundle.
Also applies to: 128-137, 147-163, 198-201
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml at line 121, The workflow currently passes a
hard-coded report path
"/d:sonar.cs.opencover.reportsPaths=Tests/${SLN}.Tests/coverage.net9.0.opencover.xml"
which only includes the `${SLN}.Tests` project; update these reporter/copy
arguments (the Sonar `sonar.cs.opencover.reportsPaths`, the Codecov/Codacy
upload and any copy steps referenced at the same locations) to accept a glob
that aggregates all test project coverage files such as
`Tests/**/coverage.net9.0.opencover.xml` (or build the list from the
`Tests/**/*.csproj` step), ensuring the Sonar/Codecov/Codacy parameters use that
aggregated list instead of the single `Tests/${SLN}.Tests/...` path; apply the
same change to the other occurrences mentioned (the blocks around the other
lines referenced) so all test projects’ coverage is uploaded.
| - name: Tag release version | ||
| run: | | ||
| VERSION="v${{ steps.gitversion.outputs.semVer }}" | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git tag -a "$VERSION" -m "Release $VERSION" | ||
| git push origin "$VERSION" |
There was a problem hiding this comment.
Make tag creation idempotent.
git tag -a will fail on any rerun for the same version. That blocks recovery from a transient failure after packages were already pushed, unless someone manually deletes the tag first.
Suggested fix
- name: Tag release version
run: |
VERSION="v${{ steps.gitversion.outputs.semVer }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- git tag -a "$VERSION" -m "Release $VERSION"
- git push origin "$VERSION"
+ if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then
+ echo "Tag $VERSION already exists; skipping"
+ else
+ git tag -a "$VERSION" -m "Release $VERSION"
+ git push origin "$VERSION"
+ fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Tag release version | |
| run: | | |
| VERSION="v${{ steps.gitversion.outputs.semVer }}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag -a "$VERSION" -m "Release $VERSION" | |
| git push origin "$VERSION" | |
| - name: Tag release version | |
| run: | | |
| VERSION="v${{ steps.gitversion.outputs.semVer }}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then | |
| echo "Tag $VERSION already exists; skipping" | |
| else | |
| git tag -a "$VERSION" -m "Release $VERSION" | |
| git push origin "$VERSION" | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml around lines 255 - 261, The "Tag release
version" step currently always runs git tag -a "$VERSION" which will fail on
reruns if the tag already exists; update the step to be idempotent by detecting
whether the tag already exists (e.g., use git ls-remote --tags origin "$VERSION"
or git rev-parse -q --verify "refs/tags/$VERSION") and only create and push the
tag if it is missing, otherwise skip tagging; reference the VERSION variable,
the git tag -a command and the git push origin "$VERSION" invocation when
implementing the conditional check.
PR Review 🔍
|
PR Code Suggestions ✨
|
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 13768420 | Triggered | Generic Password | 1266094 | .github/workflows/release.yml | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
|
✅ Build CrispyWaffle 10.0.1277 completed (commit 6676bcf50f by @guibranco) |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #868 +/- ##
==========================================
+ Coverage 40.53% 40.62% +0.08%
==========================================
Files 83 83
Lines 3631 3631
Branches 519 519
==========================================
+ Hits 1472 1475 +3
+ Misses 2057 2053 -4
- Partials 102 103 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Not up to standards ⛔🟢 Coverage
|
| Metric | Results |
|---|---|
| Coverage variation | ✅ +0.00% coverage variation (-1.00%) |
| Diff coverage | ✅ ∅ diff coverage |
Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (da73900) 3681 1620 44.01% Head commit (641687a) 3681 (+0) 1620 (+0) 44.01% (+0.00%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>
Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#868) 0 0 ∅ (not applicable) Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
TIP This summary will be updated as you push new changes. Give us feedback
|
✅ Build CrispyWaffle 10.0.1308 completed (commit 89be9e768e by @gstraccini[bot]) |
|
Infisical secrets check: ✅ No secrets leaked! 💻 Scan logs2026-04-21T15:43:57Z INF scanning for exposed secrets...
3:43PM INF 796 commits scanned.
2026-04-21T15:43:58Z INF scan completed in 1.19s
2026-04-21T15:43:58Z INF no leaks found
|
|
|
❌ Build CrispyWaffle 10.0.1543 failed (commit acd1a8a5c8 by @guibranco) |



User description
📑 Description
Create release.yml
✅ Checks
☢️ Does this introduce a breaking change?
Summary by Sourcery
Add an automated release workflow that builds, tests, analyzes, packages, and publishes the project on pushes to the main branch.
CI:
Summary by CodeRabbit
Description
Changes walkthrough 📝
release.yml
Comprehensive Automated Release Workflow Implementation.github/workflows/release.yml