| name | release-fsharp-hotchocolate |
| description | Prepare and publish FSharp.HotChocolate releases. Use when updating release notes or package versions, creating release commits and tags, packing release artifacts, pushing release tags, watching tag CI/NuGet publication, or creating GitHub Releases. |
Release FSharp.HotChocolate
Overview
Use this skill to release FSharp.HotChocolate through the repo's normal tag-driven NuGet flow, then create a GitHub Release after the tag CI has successfully pushed the package to NuGet. Keep the release change small and user-facing: version fields, release notes, README updates when behavior changed, verification, commit, tag, push, CI/NuGet confirmation, and GitHub Release publication.
Workflow
-
Require a clean working directory before proceeding. If git status --short reports any changes, stop and ask the user whether to commit, stash, discard, or otherwise resolve them first.
-
Confirm the release shape before editing:
- Bump
Version in src/FSharp.HotChocolate/FSharp.HotChocolate.fsproj.
- Keep
PackageReleaseNotes pointing at the versioned GitHub Release URL:
<PackageReleaseNotes>https://github.com/cmeeren/FSharp.HotChocolate/releases/tag/v/$(Version)</PackageReleaseNotes>
- Verify Hot Chocolate versions in
Directory.Packages.props.
-
Prepare the release content:
- Update code and docs only as needed for the release.
- Update
RELEASE_NOTES.md with user-facing behavior, migration impact, and usage guidance.
- When the release includes any breaking change, create or keep a
#### Breaking subsection and place it before
other categorizing subsections. Put every breaking release-note entry there; do not bury breaking changes under
#### Changed, #### Fixed, or plain bullets.
- Use categorizing subsections such as
#### Added or #### Fixed only when the release notes are large enough
that grouping materially improves readability; for small releases, prefer plain bullets under the version heading.
- Within each release-note bullet list, whether under the version heading or a categorizing subsection, order entries
by user impact and breadth first. Put broad runtime correctness and behavior changes before narrow edge cases, and
put documentation/package-metadata-only entries last unless they are the main release purpose.
- Describe the observable effect from the user's perspective. Avoid naming internal mechanisms or implying an
opt-in/configuration choice unless users actually control it.
- Before tagging, rename the release notes heading from
### Unreleased to ### <Version> (<YYYY-MM-DD>), using
the release date.
- Inspect the versioned release notes before committing and tagging. The section should contain only intended public
release notes, with no stale
Unreleased heading and no private or implementation-only details.
- Keep implementation-only rationale out of
README.md and RELEASE_NOTES.md.
- Do not create or reuse the GitHub Release notes temp file yet; refresh it from the final tagged content after the
successful NuGet push.
-
Verify locally:
dotnet tool restore
dotnet fantomas --check .
dotnet test -c Release -maxCpuCount
- When packaging behavior or package metadata matters, pack locally:
dotnet pack -c Release src/FSharp.HotChocolate/FSharp.HotChocolate.fsproj
Check the produced package metadata when PackageReleaseNotes changed. Local pack can prove the versioned release
URL is embedded, but that URL cannot resolve until the GitHub Release exists.
-
Commit and tag:
- Load
git-commit-message before authoring the commit.
- Use
v/<Version> for releases, for example v/1.0.0.
-
Push the commit and tag. Successful tag CI publishes the package to NuGet.
-
Watch the tag CI run and confirm NuGet publication before creating a GitHub Release:
- Find the CI run for the pushed
v/<Version> tag, not just the branch push run.
- This repo's tag runs can be found with
gh run list --branch "v/<Version>":
$tag = "v/<Version>"
$repo = "cmeeren/FSharp.HotChocolate"
$run = @(gh run list --repo $repo --workflow ci.yml --branch $tag --event push --limit 1 --json databaseId,headBranch,status,conclusion,url | ConvertFrom-Json)
if (-not $run) { throw "No CI run found for tag $tag" }
$runId = $run[0].databaseId
gh run watch $runId --repo $repo --exit-status
- Confirm the tag run succeeded and that the
Push step performed a real NuGet upload. The workflow uses
--skip-duplicate, so a successful step can still mean the package already existed and was skipped. Inspect the
fresh run logs; if the push was skipped as a duplicate, the push logs are unavailable, or NuGet publication is
unclear, stop and inspect/report before creating a GitHub Release.
- Verify the exact package version is visible on NuGet before creating a GitHub Release:
$version = "<Version>".ToLowerInvariant()
$packageUrl = "https://api.nuget.org/v3-flatcontainer/fsharp.hotchocolate/$version/fsharp.hotchocolate.$version.nupkg"
for ($attempt = 1; $attempt -le 12; $attempt++) {
try {
Invoke-WebRequest -Method Head -Uri $packageUrl -UseBasicParsing | Out-Null
break
} catch {
if ($attempt -eq 12) { throw "NuGet package is not available: $packageUrl" }
Start-Sleep -Seconds 10
}
}
-
Refresh and inspect the GitHub Release notes immediately before creating the release:
- Copy the exact release section from the tagged
RELEASE_NOTES.md to a temporary file under the user's temp
directory, for example $env:TEMP\fsharp-hotchocolate-release-v<Version>.md on PowerShell.
- Prefer reading the tagged file with
git show "v/<Version>:RELEASE_NOTES.md" so the GitHub Release notes match the
commit that was packaged and published.
- Manually inspect the temporary notes file. It should contain only the released version's notes, not the whole
changelog and not a stale
Unreleased heading.
-
Create the GitHub Release only after the successful NuGet push and notes inspection:
$tag = "v/<Version>"
$repo = "cmeeren/FSharp.HotChocolate"
if (gh release view $tag --repo $repo 2>$null) { throw "GitHub Release already exists for $tag" }
gh release create $tag --repo $repo --verify-tag --title "FSharp.HotChocolate <Version>" --notes-file "$env:TEMP\fsharp-hotchocolate-release-v<Version>.md"
If the existing-release check finds a release, stop instead of creating a duplicate.
- Verify the created release and remove the temporary notes file when practical:
$tag = "v/<Version>"
$repo = "cmeeren/FSharp.HotChocolate"
gh release view $tag --repo $repo --json tagName,name,url
Confirm the release URL targets the same tag as the PackageReleaseNotes URL embedded in the package metadata.
Guardrails
- Do not start release steps from a dirty worktree.
- Do not create the GitHub Release before the tag CI has successfully pushed to NuGet.
- Use
gh release create --verify-tag so GitHub does not auto-create or retarget the release tag.
- Use
--repo cmeeren/FSharp.HotChocolate for gh release and run commands; do not rely on implicit gh repository
context.
- Check for an existing GitHub Release for the tag before creating one; do not create duplicates.
- Refresh release notes from tagged content after NuGet publication; do not reuse an older temp file.
- Do not treat the versioned
PackageReleaseNotes URL as fully verified until the matching GitHub Release exists.
- If Verify snapshots change, use the repo-local
verify-snapshots skill before accepting them.