Skip to content

Release Process

AmirHosseinMp02 edited this page Aug 1, 2026 · 1 revision

Release Process

How QueryForge is built, tested and published. Useful if you maintain the repository or want to understand what a published version has been through.


Versioning

All four packages share a version and are released together. It is set per project in the .csproj:

<Version>2.0.0</Version>

Semantic versioning:

Change Bump
A breaking change to a public type, member, or the JSON contract major
A new capability, a new provider, a new dialect minor
A fix that does not change a documented behaviour patch

Behaviour that is documented in Query Semantics or Cross-Provider Parity counts as public surface. Changing null ordering or what a negated group returns is a major change even though no signature moves.


The workflow

.github/workflows/publish-nuget.yml has three jobs.

build-and-test — every push and pull request

- dotnet restore
- dotnet build -c Release --no-restore
- dotnet test  -c Release --no-build --verbosity normal

It sets none of the QUERYFORGE_* variables, so the server-backed suites skip themselves and the job needs no service containers. Fast, and runs on every change.

database-tests — manual dispatch and release tags

if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/v')

Spins up PostgreSQL 16, MySQL 8, SQL Server 2022 and Oracle Free 23 as service containers, each with a health check, and runs the full matrix with:

QUERYFORGE_REQUIRE_DB: '1'

which turns an unreachable engine from a skip into a failure. Without it, a container that never came up would skip its suites and hand the publish gate a green run that tested nothing.

publish — release tags only

needs: [ build-and-test, database-tests ]
if: startsWith(github.ref, 'refs/tags/v')
- dotnet pack QueryForge.slnx -c Release -o ./nupkgs
- NuGet/login@v1                       # OIDC Trusted Publishing — no long-lived API key
- dotnet nuget push ./nupkgs/*.nupkg --skip-duplicate

Because publish depends on database-tests, a version cannot reach NuGet without having been exercised against every engine the Dapper provider claims to support.


Cutting a release

  1. Bump the version in all four .csproj files. They are released together and must match.
  2. Update the READMEs if anything user-visible changed — the root one, and each package's.
  3. Update this wiki for behaviour or API changes. The wiki is the reference; the READMEs are the introduction.
  4. Run the database job by hand on the commit you intend to tag: Actions → Build, Test, and Publish NuGet → Run workflow.
  5. Confirm it is green, including the Oracle and SQL Server suites. Check the skip count — a silently skipped engine is what QUERYFORGE_REQUIRE_DB exists to prevent, but read the numbers anyway.
  6. Tag and push:
    git tag v2.0.1
    git push origin v2.0.1
  7. Watch the run. All three jobs must pass before anything is pushed to NuGet.

Step 4 is not optional in practice. A release tag is a bad place to discover a broken engine — the tag exists, the run is red, and you are cutting a new version to fix the tooling rather than the code. The dispatch is the same job on the same containers, so a green dispatch means the tag will get the same answer.


What ships in a package

Each .csproj sets:

<GenerateDocumentationFile>true</GenerateDocumentationFile>   <!-- XML docs for IntelliSense -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>             <!-- symbols for debugging -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>icon.png</PackageIcon>
<NoWarn>$(NoWarn);1591</NoWarn>                               <!-- missing XML comment -->

So every package carries its README, the icon, IntelliSense documentation and a symbol package.

Dependencies

Package References
PepperX.QueryForge none
PepperX.QueryForge.Dapper core, Dapper 2.1.79, Microsoft.Extensions.DependencyInjection.Abstractions 10.0.9
PepperX.QueryForge.EFCore core, Microsoft.EntityFrameworkCore 10.0.0
PepperX.QueryForge.InMemory core

No package references a database driver. Consumers bring only the one they use.


Trusted Publishing

Publishing uses NuGet's OIDC Trusted Publishing rather than a stored API key:

permissions:
  id-token: write
  contents: read
- uses: NuGet/login@v1
  id: login
  with:
    user: AmirHosseinMp02

The workflow exchanges a short-lived GitHub OIDC token for a NuGet key valid for that run. There is no long-lived secret in the repository to leak or rotate.

--skip-duplicate makes a re-run of the same tag a no-op rather than a failure.


Local build and pack

dotnet build QueryForge.slnx -c Release
dotnet test  QueryForge.slnx -c Release
dotnet pack  QueryForge.slnx -c Release -o ./nupkgs

To test a package before publishing, add the output folder as a source:

dotnet nuget add source ./nupkgs --name local
dotnet add package PepperX.QueryForge.Dapper --version 2.0.1 --source local

Clear the local NuGet cache between attempts, or a stale copy of the same version will be used:

dotnet nuget locals all --clear

Release checklist

  • Version bumped in all four .csproj files, and they match
  • dotnet build -c Release is clean — 0 warnings, 0 errors
  • dotnet test -c Release passes locally
  • The database-tests job dispatched manually and green on the target commit
  • Oracle and SQL Server suites genuinely ran — check the skip counts
  • Root README and all four package READMEs updated
  • This wiki updated for any behaviour or API change
  • Migration notes updated if anything is breaking
  • Tag pushed, all three jobs green
  • Packages visible on NuGet

Clone this wiki locally