Wire Darling into the release pipeline#1340
Merged
Merged
Conversation
Release builds now publish the Darling headless edition (Windows-service collector + WPF viewer) and ship it as one portable zip, alongside the existing Dashboard/Lite/Installer artifacts. - Publish PerformanceMonitor.Darling.Service and .Viewer framework-dependent, mirroring the Dashboard/Lite publish steps. - Build the bundled pg-runtime.zip (pinned EDB PostgreSQL 17.10 + TimescaleDB 2.28.1) via Darling/tools/fetch-pg-runtime.ps1, release-only (it downloads ~340MB) and cached with actions/cache keyed on the fetch script's own content hash, so re-releases with unchanged pins skip the download. - Package PerformanceMonitorDarling-<version>.zip from the SIGNED binaries: service at the archive root with pg-runtime.zip beside its exe (where DarlingManagedPostgres extracts it on first run) and the viewer in a viewer/ subfolder. darling.sample.json is already in the service publish output. Checksums + release upload already glob releases/*.zip. - Sign our own Darling exes/dlls through the existing SignPath flow; the EDB PostgreSQL binaries inside pg-runtime.zip are uploaded to SignPath NEVER (the zip is placed after signing) and ship as opaque data. Two new artifact-configuration slugs (DarlingService/DarlingViewer) must be created on signpath.io before the next release. - Stamp the service/viewer csprojs with the shared Version/AssemblyVersion/ FileVersion (3.1.0) to match the other shipped entrypoints. No Velopack for Darling v1 (a Windows service has a different update story, deliberately deferred) - plain zip only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…requires pwsh 7 Validation follow-ups to the release wiring: - The one-zip layout puts the viewer in viewer\ while the operator's darling.json lives beside the service exe — the viewer's resolution (explicit -> DARLING_CONFIG -> beside binary) would miss it out of the box. ViewerSettings now probes the parent directory as a viewer-only final fallback, pinned by a packaged-layout resolution test (beside- binary still wins; miss-both still reports the viewer's own path). - fetch-pg-runtime.ps1 now #Requires -Version 7.0: under Windows PowerShell 5.1 it runs on .NET Framework, whose ZipFile.CreateFromDirectory writes backslash entry separators — a non-conformant zip (Info-ZIP mangles it) that byte-differs from the CI-built one (shell: pwsh). Caught when unzip refused the locally built pg-runtime.zip during validation. Validated: 186/186 fully gated (PG fixture + SQL2022 + PGRUNTIME), with the bootstrap E2E consuming a runtime extracted from the artifact zip itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wires the Darling headless edition (Windows-service collector + WPF viewer + bundled managed PostgreSQL, backend finished in #1338) into the release pipeline in
.github/workflows/build.yml. Part of #1262.Everything mirrors the existing Dashboard/Lite/Installer steps; the heavy/opaque parts (the ~340MB PostgreSQL runtime download, the EDB binaries) are handled deliberately.
What runs on a release now
On top of the existing Dashboard/Lite/Installer flow, a
release: publishedbuild now also:PerformanceMonitor.Darling.ServiceandPerformanceMonitor.Darling.Viewerframework-dependent (-c Release -o publish/DarlingService/publish/DarlingViewer), exactly like Dashboard/Lite. These publish on every non-doc build too (build verification), same gate as Dashboard/Lite.pg-runtime.zipviaDarling/tools/fetch-pg-runtime.ps1(pinned EDB PostgreSQL 17.10 + TimescaleDB 2.28.1, SHA256-verified) — release-only, behind anactions/cache.PerformanceMonitorDarling-<version>.zipfrom the SIGNED binaries, withpg-runtime.zipplaced beside the service exe.releases/*.zip).Artifact list delta
Release assets gain exactly one file:
PerformanceMonitorDarling-<version>.zip(and its line inSHA256SUMS.txt)No other artifact changes.
pg-runtime.zipis not a standalone asset — it ships inside the Darling zip.Decision: one zip vs two
One zip. The existing artifact set is one-zip-per-product (Dashboard, Lite, and Installer-with-its-SQL-scripts are each a single zip), so Darling — one product with two exes — is one zip too. Layout mirrors the Installer's "primary tool at root + a subfolder" shape:
pg-runtime.zipat the root is load-bearing:DarlingManagedPostgreslooks for it atAppContext.BaseDirectory(verified inDarlingManagedPostgres.cs:98) and extracts it on first run, so the zip is ready tosc createin place with zero extra steps.Decision: cache keyed on the fetch script's content hash
actions/cache@v4caches the assembledDarling/artifacts/pg-runtime.zipwith keypg-runtime-${{ runner.os }}-${{ hashFiles('Darling/tools/fetch-pg-runtime.ps1') }}.actions/cachesaves in its post step, so even if a later step fails the runtime stays cached for the retry.Signing situation
wait-for-completion), reading frompublish/DarlingService/publish/DarlingViewerand writingsigned/DarlingService/signed/DarlingViewer. The final zip is built from the signed output.pg-runtime.zipis never sent to SignPath. It is placed into the package after signing, so the EDB PostgreSQL binaries inside ship as opaque data and are never touched by our signing flow (per the ground rules).artifact-configuration-slugvalues —DarlingServiceandDarlingViewer— must be created on signpath.io. That config (which files in the uploaded artifact get signed) is not stored in the repo, so I did not guess it; configure each to sign the apphost exe +PerformanceMonitor.*dlls and leave third-party assemblies alone. Until both slugs exist, the two new Sign steps will fail the release. This is flagged in anACTION REQUIREDcomment in the workflow too.Velopack deferral
No Velopack for Darling v1 — plain zip only. A Windows service has a different update story than the WPF apps' Setup.exe/Velopack model, and it's deliberately deferred. Noted in a workflow comment and the CHANGELOG.
Version stamping
The service and viewer csprojs had no version. Every other shipped entrypoint (Dashboard, Lite, Installer, Installer.Core) carries
<Version>3.1.0</Version>+<AssemblyVersion>3.1.0.0</AssemblyVersion>+<FileVersion>3.1.0.0</FileVersion>, so I added the same triplet to both Darling entrypoints. The zip name itself reuses the Dashboard-derivedVERSION(unchanged), so this only affects the binaries' own file metadata. Note for release cuts: these two csprojs now join the set of files to version-bump (thecheck-version-bumpgate still only reads Dashboard.csproj, unchanged).What I validated locally
actionlintisn't installed, so I parsed all three workflows with PyYAML and asserted structure: all 9 new steps present, no duplicate step ids, the Sign steps reference the correct upload-artifact ids/slugs/output dirs, and the cache step is wired (id: cache-pg-runtime,actions/cache@v4, correct path, and the Build step gated oncache-hit != 'true'). All green.dotnet publishboth Darling projects (Release) to a temp dir, staged a simulatedsigned/+Darling/artifacts/pg-runtime.zip(copied from a prebuilt runtime — no 340MB re-download), and ran the verbatimPackage Darling (signed)+Generate checksumscommands. Result: a 133.6 MBPerformanceMonitorDarling-3.1.0.zipand a correct SHA256 line.zipfile.namelist()— 242 entries, all forward-slash separators):PerformanceMonitor.Darling.Service.exe,pg-runtime.zip(51.8 MB),darling.sample.jsonviewer/PerformanceMonitor.Darling.Viewer.exeruntimes/…service assetspg-runtime.zipappears at root only (not underviewer/, not inside the signed upload).darling.sample.jsonis in the service publish output (README claim holds; no csproj fix needed).dotnet test Darling/Darling.Tests -c Debug→ 169 passed, 16 skipped (env-gatedDARLING_TEST_PG*E2E), 0 failed.Could NOT validate (CI-only)
actions/cachehit/miss + save behavior on the real runner.Nothing found broken
fetch-pg-runtime.ps1 pins untouched;
Darling/artifacts/is already gitignored; the localpackage-release.cmd/build-*.cmdhelpers are intentionally left out of scope (they don't sign or fetch the runtime, so they can't produce a complete Darling package).🤖 Generated with Claude Code