Distribution & release
FS.Skia.UI is distributed as public NuGet.org packages — 11 FS.Skia.UI.* libraries
plus the FS.Skia.UI.Template project template. An external developer consumes it without
cloning this repository. (This supersedes the "distribution deferred / local-feed-only"
narrative; see ADR 0001.)
Consumer install flow
|
The generated NuGet.config references the public nuget.org feed only — no machine-local
path — so a fresh checkout restores on any machine.
Feeds and the preview/stable channel
- Public feed:
https://api.nuget.org/v3/index.json. -
Channel is explicit in the version value:
-preview.N(or-rc.N) ⇒ preview; a bareMAJOR.MINOR.PATCH⇒ stable. The packages are published on the preview channel (libraries0.1.68-preview.1, template0.1.87-preview.1). -
A private or staging feed is a configuration change only — add it to
NuGet.config, or for the publish target setFSSKIA_PUBLISH_FEED. No code change.
Consumer upgrade — one edit
Every generated project pins all FS.Skia.UI.* packages and the in-process build engine
to a single <FsSkiaUiVersion> in Directory.Packages.props. Change that one value, run
dotnet restore, and libraries + engine move together. Full procedure ships in the generated
project at docs/UPGRADING.md.
Maintainer release + publish flow
Recommended: CI publish via GitHub Actions trusted publishing
The production push runs in CI with no stored API key, using NuGet
Trusted Publishing
(GitHub OIDC). .github/workflows/publish.yml exchanges the job's signed OIDC token for a
short-lived (~1 h, single-use) nuget.org key via NuGet/login@v1, exposed as NUGET_API_KEY
— the exact env var the Publish target already reads, so there is zero publish-specific
code and nothing to leak or rotate.
-
Bump the version (
<FsSkiaUiVersion>for the libs; the template version independently) and merge tomain. - Actions → "Publish to nuget.org" → Run workflow (manual
workflow_dispatchonly). -
The job pauses at the protected
releaseenvironment for maintainer approval, then runs the full pre-publish gate (PrePublishCheck→PackLocal/TemplatePack) and pushes all 12 packages with--skip-duplicate.
One-time setup: a nuget.org Trusted Publishing policy (owner / repo / workflow publish.yml /
env release), the release environment with required reviewers, and user: <nuget profile>
in the workflow. The CI runner provisions a headless graphics stack (Xvfb + Mesa lavapipe +
GLFW libs) so the Silk.NET/Vulkan pre-publish GUI suite runs without a display or GPU.
Manual / local fallback
|
The credential follows the same ambient-environment model as gh: dotnet nuget push
reads NUGET_API_KEY (NuGet 7.6+, .NET SDK 10.0.300+), so the key is never passed as a
command-line argument — there is nothing to leak. (FSSKIA_PUBLISH_API_KEY is accepted as an
alias and is likewise forwarded only via the environment.)
- Idempotent: re-running for versions already on the feed skips them (no error); a partial-failure re-run pushes only the remainder.
- Pre-publish gate: verifies the template's pins reference the shipped versions, the build-engine pin matches (single-source), the consumer config carries no machine-local path, and every package + the template carry license / repository URL / authors / description / README. A malformed or inconsistent release cannot be pushed.
-
First production push is irreversible: a published version can only be unlisted, never
deleted, and the push permanently claims the
FS.Skia.UI.*package-ID namespace. It is the maintainer's final step, gated behind a greenPrePublishCheck.
Publish target reference
Env var |
Default |
Meaning |
|---|---|---|
|
|
target feed (nuget.org URL, a private feed, or a local directory for staging). |
|
(unset) |
push credential, read from the environment by |
|
(unset) |
alias for the credential (forwarded to the child as |
|
(unset) |
when set, plan only — no network push. |
|
(unset) |
when set on a real push, also attach the 12 |
The publish machinery is validated against a throwaway local-directory staging feed (credential-free) before any live nuget.org push.
Credential safety: the push credential uses the same ambient-environment model as gh
(gh reads GH_TOKEN; dotnet nuget push reads NUGET_API_KEY), so the key is never on a
command line — nothing to leak. As belt-and-braces, captured output is also redacted before it
is written to any log. The gh release upload likewise authenticates via the stored gh auth
token.
GitHub Release artifacts (optional supplement)
Setting FSSKIA_PUBLISH_GH_RELEASE_TAG=<tag> on a real push additionally uploads the 12
.nupkg to a GitHub Release (gh release create/upload --clobber). This is archival
only — GitHub Releases is not a NuGet feed, so consumers still install/restore from
nuget.org (and GitHub Packages is excluded because it requires authentication even to read
public packages, breaking the no-setup consumer restore). The GitHub upload is best-effort: a
gh failure is logged but never fails the (already-completed) nuget.org push.