Simplify release workflow with NuGet trusted publishing - #105
Conversation
📝 WalkthroughWalkthroughThis PR migrates the project's CI/CD and build infrastructure from a legacy Cake-based build system to GitHub Actions. The workflow now runs on Linux, automatically publishes releases to NuGet based on version tags, and enforces deterministic builds. Old bootstrapper scripts, Cake configuration, and versioning settings are removed; project files are updated with NuGet metadata previously stored in a separate ChangesBuild System Migration to GitHub Actions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
README.md (2)
55-55: ⚡ Quick winClarify ambiguous phrasing.
The phrase "If you need .NET Framework 4.5 or older .NET Standard support" is ambiguous. Does this mean:
- .NET Framework 4.5 or older versions of .NET Standard, or
- .NET Framework 4.5 or older?
Consider rephrasing for clarity, for example: "If you need .NET Framework 4.5 support or target older .NET Standard versions, use version 1.1.5 or earlier."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` at line 55, Reword the ambiguous sentence in README.md that currently reads "If you need .NET Framework 4.5 or older .NET Standard support, use version 1.1.5 or earlier." to make the two options explicit; replace it with something like "If you need .NET Framework 4.5 support or need to target older .NET Standard versions, use version 1.1.5 or earlier." so it clearly indicates the alternatives (.NET Framework 4.5 support OR older .NET Standard versions).
55-55: ⚡ Quick winConsider documenting the framework compatibility change in the changelog.
The updated requirements indicate that .NET Framework 4.5 is no longer supported in the current version (which targets .NET Standard 2.0, compatible with .NET Framework 4.6.1+). However, this breaking change is not documented in the changelog. The only related entry is v1.0.0 (lines 37-43), which mentions dropping .NET 4.0 and below.
Consider adding a changelog entry for the version where .NET Framework 4.5 support was dropped to help users understand the compatibility timeline.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` at line 55, Add a changelog entry documenting the breaking change that removed .NET Framework 4.5 support: update CHANGELOG (or add a new entry) to note that the current release now targets ".NET Standard 2.0" and is compatible with .NET Framework 4.6.1+, and that users requiring .NET Framework 4.5 should use "version 1.1.5 or earlier"; place this entry alongside existing entries (see the v1.0.0 entry) so the compatibility timeline is clear.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/main.yml:
- Around line 7-8: The workflow currently triggers on tags matching "v*" and
releases whatever commit the tag points to; add a guard so releases only proceed
if that tagged commit is contained in master: modify .github/workflows/main.yml
where tags: - v* is declared to include a job step (e.g., "Verify tag is on
master") before publish that checks out with full history (actions/checkout
fetch-depth:0), fetches origin/master and verifies the tag commit (GITHUB_SHA or
github.ref) is contained in master using git merge-base --is-ancestor or git
branch --contains; if the check fails, fail the job to block releases from
non-master commits.
- Around line 21-25: The workflow uses mutable tags for GitHub Actions
(actions/checkout@v5, actions/setup-dotnet@v5, and NuGet/login@v1); update those
uses to pin to the corresponding full commit SHAs instead of the tag refs so the
pipeline cannot change if upstream retags. Locate the three occurrences of
actions/checkout, actions/setup-dotnet, and NuGet/login in the workflow and
replace the tag version with the exact commit SHA from each action’s repository
release you intend to target, keeping the rest of the step configuration
unchanged.
- Around line 21-22: The Checkout steps using actions/checkout@v5 currently omit
persist-credentials and can persist token info to .git/config; update both
Checkout usages (the steps named "Checkout" that call actions/checkout@v5) to
include the option persist-credentials: false so credentials are not written to
the checkout metadata. Ensure each checkout step adds the key
persist-credentials: false under its with: block.
In `@README.md`:
- Line 55: Update the README text to explicitly map the legacy package versions
to their target TFMs: state that version 1.1.5 targets .NETFramework4.5 and
.NETStandard1.3 (replace the ambiguous “.NET Framework 4.5 or older” phrasing)
and clarify which TFMs the older 0.1.8 release targets (look up the NuGet
package metadata to get the exact TFMs) so the two sentences (the “Compatible
with .NET Standard 2.0…” line and the “older .NET framework support”/0.1.8
reference) unambiguously list the exact framework versions for 1.1.5 and 0.1.8.
In `@src/Slack.Webhooks/Slack.Webhooks.csproj`:
- Line 16: The PackageReleaseNotes XML element currently claims an update to
Newtonsoft.Json which is inaccurate; edit the <PackageReleaseNotes> value in the
project file to accurately reflect only the packaging/metadata change (e.g.,
mention targets .NET Standard 2.0 and packaging/metadata updates) or remove the
Newtonsoft.Json reference so the note matches the actual changes made to the
project (locate the <PackageReleaseNotes> element to make this edit).
---
Nitpick comments:
In `@README.md`:
- Line 55: Reword the ambiguous sentence in README.md that currently reads "If
you need .NET Framework 4.5 or older .NET Standard support, use version 1.1.5 or
earlier." to make the two options explicit; replace it with something like "If
you need .NET Framework 4.5 support or need to target older .NET Standard
versions, use version 1.1.5 or earlier." so it clearly indicates the
alternatives (.NET Framework 4.5 support OR older .NET Standard versions).
- Line 55: Add a changelog entry documenting the breaking change that removed
.NET Framework 4.5 support: update CHANGELOG (or add a new entry) to note that
the current release now targets ".NET Standard 2.0" and is compatible with .NET
Framework 4.6.1+, and that users requiring .NET Framework 4.5 should use
"version 1.1.5 or earlier"; place this entry alongside existing entries (see the
v1.0.0 entry) so the compatibility timeline is clear.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a6e69ec4-bd0f-4e34-9106-7d89b6171e18
📒 Files selected for processing (10)
.github/workflows/main.ymlGitVersion.ymlREADME.mdbuild.cakebuild.ps1build.shcake.configsrc/Slack.Webhooks.Tests/Slack.Webhooks.Tests.csprojsrc/Slack.Webhooks/Slack.Webhooks.csprojsrc/Slack.Webhooks/Slack.Webhooks.nuspec
💤 Files with no reviewable changes (6)
- build.sh
- src/Slack.Webhooks/Slack.Webhooks.nuspec
- cake.config
- build.ps1
- build.cake
- GitVersion.yml
| tags: | ||
| - v* |
There was a problem hiding this comment.
Block releases from non-master commits.
Any v* tag push currently publishes the commit behind that tag, even if it never landed on master. That lets an unmerged branch commit become the NuGet release.
Suggested hardening
- name: Checkout
uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+
+ - name: Verify tagged commit is on master
+ run: git merge-base --is-ancestor "$GITHUB_SHA" origin/masterAlso applies to: 49-50
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/main.yml around lines 7 - 8, The workflow currently
triggers on tags matching "v*" and releases whatever commit the tag points to;
add a guard so releases only proceed if that tagged commit is contained in
master: modify .github/workflows/main.yml where tags: - v* is declared to
include a job step (e.g., "Verify tag is on master") before publish that checks
out with full history (actions/checkout fetch-depth:0), fetches origin/master
and verifies the tag commit (GITHUB_SHA or github.ref) is contained in master
using git merge-base --is-ancestor or git branch --contains; if the check fails,
fail the job to block releases from non-master commits.
| - name: Checkout | ||
| uses: actions/checkout@v5 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant sections of the workflow around the referenced line numbers
FILE=".github/workflows/main.yml"
echo "=== File exists? ==="
ls -l "$FILE" || true
echo "=== Context around lines 1-120 ==="
nl -ba "$FILE" | sed -n '1,140p'
echo "=== Grep for checkout steps ==="
rg -n "uses:\s*actions/checkout@" "$FILE" || true
echo "=== Extract checkout blocks (few lines around each match) ==="
rg -n "uses:\s*actions/checkout@" "$FILE" -n --context 6 || trueRepository: mrb0nj/Slack.Webhooks
Length of output: 259
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/main.yml"
echo "=== First 200 lines (with numbers) ==="
awk '{printf "%6d %s\n", NR, $0}' "$FILE" | sed -n '1,200p'
echo
echo "=== Find checkout steps ==="
rg -n "uses:\s*actions/checkout@" "$FILE" || true
echo
echo "=== Extract checkout blocks with ~15 lines context ==="
rg -n "uses:\s*actions/checkout@" "$FILE" -C 8 || trueRepository: mrb0nj/Slack.Webhooks
Length of output: 3878
Disable checkout credential persistence in PR workflows.
pull_request runs the repo’s code via dotnet test, and both actions/checkout@v5 steps currently omit persist-credentials: false, so credentials can be written to .git/config. Set persist-credentials: false on both checkouts (lines 21-22 and 56-57), since no later step needs persisted GitHub checkout credentials.
Suggested hardening
- name: Checkout
uses: actions/checkout@v5
+ with:
+ persist-credentials: false
...
- name: Checkout
uses: actions/checkout@v5
+ with:
+ persist-credentials: false📝 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: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| with: | |
| persist-credentials: false |
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 21-22: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 22-22: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/main.yml around lines 21 - 22, The Checkout steps using
actions/checkout@v5 currently omit persist-credentials and can persist token
info to .git/config; update both Checkout usages (the steps named "Checkout"
that call actions/checkout@v5) to include the option persist-credentials: false
so credentials are not written to the checkout metadata. Ensure each checkout
step adds the key persist-credentials: false under its with: block.
Source: Linters/SAST tools
| - name: Checkout | ||
| uses: actions/checkout@v5 | ||
|
|
||
| - name: Setup .NET | ||
| uses: actions/setup-dotnet@v5 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the workflow file(s)
ls -la .github/workflows || true
sed -n '1,200p' .github/workflows/main.yml
echo "----"
# Show the specific line ranges mentioned in the comment
nl -ba .github/workflows/main.yml | sed -n '1,140p' | sed -n '15,110p'
echo "----"
# Check for any action refs that are not pinned to SHAs
# (heuristic: looks for "uses: owner/repo@vX" or "uses: owner/repo@<branch/tag>")
rg -n --no-heading "uses:\s*[^@]+@v[0-9]+|uses:\s*[^@]+@v[0-9]+\.[0-9]+" .github/workflows/main.yml || true
rg -n --no-heading "uses:\s*[^@]+@v[0-9]+|uses:\s*[^@]+@refs/" .github/workflows/main.yml || true
# Look specifically for NuGet/login usage
rg -n --no-heading "NuGet/login" .github/workflows/main.yml || trueRepository: mrb0nj/Slack.Webhooks
Length of output: 2483
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/main.yml"
echo "---- file: $FILE ----"
wc -l "$FILE"
echo "---- uses: lines (with line numbers via awk) ----"
awk '
/uses:/ {
printf "%4d: %s\n", NR, $0
}
' "$FILE"
echo "---- line ranges mentioned in the comment ----"
echo "--- lines 21-25 ---"
awk 'NR>=21 && NR<=25 {printf "%4d: %s\n", NR, $0}' "$FILE"
echo "--- lines 56-60 ---"
awk 'NR>=56 && NR<=60 {printf "%4d: %s\n", NR, $0}' "$FILE"
echo "--- lines 81-82 ---"
awk 'NR>=81 && NR<=82 {printf "%4d: %s\n", NR, $0}' "$FILE"
echo "---- check whether any uses: are pinned to 40-hex SHAs ----"
# Print uses: lines where the ref looks like a full commit SHA (40 hex)
rg -n --no-heading "uses:\s*[^@]+@([0-9a-f]{40})\b" "$FILE" || true
echo "---- check whether checkout/setup-dotnet/NuGet/login are pinned to SHAs ----"
for action in "actions/checkout" "actions/setup-dotnet" "NuGet/login"; do
echo "== $action =="
rg -n --no-heading "uses:\s*$action@" "$FILE" || true
doneRepository: mrb0nj/Slack.Webhooks
Length of output: 1260
Pin workflow actions to immutable SHAs.
In .github/workflows/main.yml, actions/checkout@v5, actions/setup-dotnet@v5, and NuGet/login@v1 use mutable tag refs; pin them to full commit SHAs to prevent upstream retagging from changing the pipeline (lines 21-25, 56-60, 81-82).
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 21-22: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 22-22: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 25-25: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/main.yml around lines 21 - 25, The workflow uses mutable
tags for GitHub Actions (actions/checkout@v5, actions/setup-dotnet@v5, and
NuGet/login@v1); update those uses to pin to the corresponding full commit SHAs
instead of the tag refs so the pipeline cannot change if upstream retags. Locate
the three occurrences of actions/checkout, actions/setup-dotnet, and NuGet/login
in the workflow and replace the tag version with the exact commit SHA from each
action’s repository release you intend to target, keeping the rest of the step
configuration unchanged.
Source: Linters/SAST tools
| 1. You must first enable the Webhooks integration for your Slack Account to get the Token. You can enable it here: https://slack.com/services/new/incoming-webhook | ||
| 2. Slack.Webhooks depends on JSON.net | ||
| 3. Compatible with .NET 4.5+ and .NET Core. If you need .NET 3.5/4 you can use an older release, but this may be out of date. | ||
| 3. Compatible with .NET Standard 2.0. If you need .NET Framework 4.5 or older .NET Standard support, use version 1.1.5 or earlier. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check available versions of Slack.Webhooks package
curl -s 'https://api.nuget.org/v3/registration5-semver1/slack.webhooks/index.json' | jq -r '.items[].items[] | .catalogEntry | "\(.version) - \(.listed) - Targets: \(.dependencyGroups[].targetFramework // "N/A")"' | sort -VRepository: mrb0nj/Slack.Webhooks
Length of output: 1063
Clarify legacy framework version guidance in README.md (lines 55 vs 68)
NuGet confirms Slack.Webhooks 1.1.5 exists and targets .NETFramework4.5 and .NETStandard1.3, so the line 55 reference is valid. However, the README still doesn’t clearly define the cutoff for “older .NET framework support” (line 68 uses 0.1.8) versus the “.NET Framework 4.5 or older” wording on line 55—please specify which framework versions/TFMs map to 1.1.5 vs 0.1.8.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` at line 55, Update the README text to explicitly map the legacy
package versions to their target TFMs: state that version 1.1.5 targets
.NETFramework4.5 and .NETStandard1.3 (replace the ambiguous “.NET Framework 4.5
or older” phrasing) and clarify which TFMs the older 0.1.8 release targets (look
up the NuGet package metadata to get the exact TFMs) so the two sentences (the
“Compatible with .NET Standard 2.0…” line and the “older .NET framework
support”/0.1.8 reference) unambiguously list the exact framework versions for
1.1.5 and 0.1.8.
| <PackageIcon>slack.png</PackageIcon> | ||
| <PackageReadmeFile>README.md</PackageReadmeFile> | ||
| <PackageTags>Slack;Webhooks</PackageTags> | ||
| <PackageReleaseNotes>Targets .NET Standard 2.0, updates Newtonsoft.Json, and keeps compatibility for sending Slack webhook messages with attachments and blocks.</PackageReleaseNotes> |
There was a problem hiding this comment.
Keep PackageReleaseNotes accurate for this release.
The current text says this release updates Newtonsoft.Json, but this project still references 13.0.4 and the supplied diff context only moves build/packaging metadata. Publishing that note would misstate what changed.
Possible wording
- <PackageReleaseNotes>Targets .NET Standard 2.0, updates Newtonsoft.Json, and keeps compatibility for sending Slack webhook messages with attachments and blocks.</PackageReleaseNotes>
+ <PackageReleaseNotes>Moves package metadata into the SDK-style project, documents .NET Standard 2.0 compatibility, and switches releases to trusted publishing.</PackageReleaseNotes>📝 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.
| <PackageReleaseNotes>Targets .NET Standard 2.0, updates Newtonsoft.Json, and keeps compatibility for sending Slack webhook messages with attachments and blocks.</PackageReleaseNotes> | |
| <PackageReleaseNotes>Moves package metadata into the SDK-style project, documents .NET Standard 2.0 compatibility, and switches releases to trusted publishing.</PackageReleaseNotes> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/Slack.Webhooks/Slack.Webhooks.csproj` at line 16, The PackageReleaseNotes
XML element currently claims an update to Newtonsoft.Json which is inaccurate;
edit the <PackageReleaseNotes> value in the project file to accurately reflect
only the packaging/metadata change (e.g., mention targets .NET Standard 2.0 and
packaging/metadata updates) or remove the Newtonsoft.Json reference so the note
matches the actual changes made to the project (locate the <PackageReleaseNotes>
element to make this edit).
Summary
Validation
Summary by CodeRabbit
Documentation
Chores