Add publish.ps1, and stop trimming release artifacts #5

Merged
hannah-vernon merged 2 commits from feature/publish-script into dev 2026-08-21 14:05:41 -05:00

Summary

Adds publish.ps1, and removes PublishTrimmed from the release workflow after finding it produces artifacts that cannot start.

publish.ps1

Wraps the dotnet publish invocation so the flag combination does not have to be remembered. Output goes to publish/<runtime>/, which is already gitignored (.gitignore:4).

.\publish.ps1                          # tests, then current OS
.\publish.ps1 -Runtime all -Clean      # every supported runtime, fresh output
.\publish.ps1 -Runtime linux-x64 -SkipTests

Tests run first by default, so a failing build produces no artifact. The script prints the version read from the csproj, the resolved output paths and sizes, and the next deployment steps.

The trimming bug

I built the trimmed variant to check whether the release workflow was safe. It is not.

PublishTrimmed disables reflection-based serialization. SiteConfig and SiteState are both bound with System.Text.Json reflection, so the build emits six IL2026 warnings and the resulting binary throws before reading the first config file:

Unhandled exception. System.InvalidOperationException: Reflection-based serialization
has been disabled for this application. Either use the source generator APIs or
explicitly configure the 'JsonSerializerOptions.TypeInfoResolver' property.
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String, JsonSerializerOptions)
   at VigilanceSentinel.Program.RunAsync(String, ConsoleWriter) in Program.cs:line 135

release.yml carried -p:PublishTrimmed=true on both the linux-x64 and win-x64 steps, so tagging any v* release would have published two artifacts that cannot start. No tags exist in this repository yet, so nothing broken was ever shipped. Removed from both steps.

Size difference, for the record: 14.1 MB trimmed and broken, 64.4 MB untrimmed and working.

publish.ps1 deliberately offers no trimming switch, because a switch that produces a non-functional binary is a trap. Re-enabling it would need a JsonSerializerContext source generator for those two models, and that requirement is recorded in the script header, README.md, and ARCHITECTURE.md so it is not naively re-added.

Verification

  • publish.ps1 parse-validated with [Parser]::ParseFile, 0 errors. CRLF throughout, comment-based help present.
  • Untrimmed output run against a real site config: all five checks reported, exit code 0.
  • Trimmed output run against the same config: crashed on startup, as quoted above.
  • dotnet test: 22 passed, 0 failed.

History reconciliation

This branch was cut from dev and then fast-forwarded to origin/main, so it also carries the release merge commit that dev was missing. Merging this clears the "out-of-date with the base branch" warning without needing a separate reconcile PR.

The merge was a genuine fast-forward with no content change, because main is a strict descendant of dev here (git merge-base --is-ancestor origin/dev origin/main returns 0).

Assumptions

  • publish/ is the intended output location, per the existing .gitignore entry.
  • Windows is the primary development platform, so the runtime defaults to the current OS rather than always building everything.
  • Removing trimming is preferred over adding a source generator in this PR. The generator is the better long-term fix if binary size matters; 64 MB is large for a monitoring utility.
  • Tests running before publish is desirable. -SkipTests exists for the case where they have just been run.
## Summary Adds `publish.ps1`, and removes `PublishTrimmed` from the release workflow after finding it produces artifacts that cannot start. ## publish.ps1 Wraps the `dotnet publish` invocation so the flag combination does not have to be remembered. Output goes to `publish/<runtime>/`, which is already gitignored (`.gitignore:4`). ```powershell .\publish.ps1 # tests, then current OS .\publish.ps1 -Runtime all -Clean # every supported runtime, fresh output .\publish.ps1 -Runtime linux-x64 -SkipTests ``` Tests run first by default, so a failing build produces no artifact. The script prints the version read from the csproj, the resolved output paths and sizes, and the next deployment steps. ## The trimming bug I built the trimmed variant to check whether the release workflow was safe. It is not. `PublishTrimmed` disables reflection-based serialization. `SiteConfig` and `SiteState` are both bound with `System.Text.Json` reflection, so the build emits six IL2026 warnings and the resulting binary throws before reading the first config file: ``` Unhandled exception. System.InvalidOperationException: Reflection-based serialization has been disabled for this application. Either use the source generator APIs or explicitly configure the 'JsonSerializerOptions.TypeInfoResolver' property. at System.Text.Json.JsonSerializer.Deserialize[TValue](String, JsonSerializerOptions) at VigilanceSentinel.Program.RunAsync(String, ConsoleWriter) in Program.cs:line 135 ``` `release.yml` carried `-p:PublishTrimmed=true` on both the linux-x64 and win-x64 steps, so tagging any `v*` release would have published two artifacts that cannot start. **No tags exist in this repository yet, so nothing broken was ever shipped.** Removed from both steps. Size difference, for the record: 14.1 MB trimmed and broken, 64.4 MB untrimmed and working. `publish.ps1` deliberately offers no trimming switch, because a switch that produces a non-functional binary is a trap. Re-enabling it would need a `JsonSerializerContext` source generator for those two models, and that requirement is recorded in the script header, `README.md`, and `ARCHITECTURE.md` so it is not naively re-added. ## Verification - `publish.ps1` parse-validated with `[Parser]::ParseFile`, 0 errors. CRLF throughout, comment-based help present. - Untrimmed output run against a real site config: all five checks reported, exit code 0. - Trimmed output run against the same config: crashed on startup, as quoted above. - `dotnet test`: 22 passed, 0 failed. ## History reconciliation This branch was cut from `dev` and then fast-forwarded to `origin/main`, so it also carries the release merge commit that `dev` was missing. Merging this clears the "out-of-date with the base branch" warning without needing a separate reconcile PR. The merge was a genuine fast-forward with no content change, because `main` is a strict descendant of `dev` here (`git merge-base --is-ancestor origin/dev origin/main` returns 0). ## Assumptions - `publish/` is the intended output location, per the existing `.gitignore` entry. - Windows is the primary development platform, so the runtime defaults to the current OS rather than always building everything. - Removing trimming is preferred over adding a source generator in this PR. The generator is the better long-term fix if binary size matters; 64 MB is large for a monitoring utility. - Tests running before publish is desirable. `-SkipTests` exists for the case where they have just been run.
Merge pull request 'Release: daily post verification check' (#3) from dev into main
All checks were successful
Build and Test / build (push) Successful in 59s
0433dcc06c
Reviewed-on: #3
Add publish.ps1, and stop trimming release artifacts
All checks were successful
Build and Test / build (pull_request) Successful in 59s
15cdae4eb9
publish.ps1 wraps the dotnet publish invocation so a developer does not have to remember the flag combination.  It runs the tests first so a failing build produces no artifact, writes self-contained single-file binaries to publish/ (already gitignored), and supports -Runtime all for cross-platform builds.

Building the trimmed variant to check whether the release workflow was safe showed that it is not.  PublishTrimmed disables reflection-based serialization, and both SiteConfig and SiteState are bound with System.Text.Json reflection.  The build emits six IL2026 warnings and the resulting binary throws before reading the first config file:

    System.InvalidOperationException: Reflection-based serialization has been
    disabled for this application.

release.yml carried -p:PublishTrimmed=true on both the linux-x64 and win-x64 steps, so tagging any v* release would have published two artifacts that cannot start.  No tags exist yet, so nothing broken was ever shipped.  Removed from both steps.

publish.ps1 deliberately offers no trimming switch, because a switch that produces a non-functional binary is a trap.  Re-enabling it would require a JsonSerializerContext source generator for those two models; that requirement is recorded in the script header, README.md, and ARCHITECTURE.md so it is not naively re-added.

Verified: untrimmed publish output runs all five checks against the live site and exits 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
hannah-vernon/vigilance-sentinel!5
No description provided.