Skip to content

Record each run's mode and outcome; fix the 100-second download timeout - #52

Merged
rodchristiansen merged 2 commits into
mainfrom
feature/run-reporting
Oct 4, 2026
Merged

rodchristiansen merged 2 commits into
mainfrom
feature/run-reporting

Conversation

@rodchristiansen

@rodchristiansen rodchristiansen commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Closes #51.

Run type

session.json starts with run_type: provisioning. Once the preflight decides, it is rewritten as skip, baseline or provisioning. A failed preflight stays provisioning.

last-run.json

C:\ProgramData\ManagedBootstrap\last-run.json is written atomically (temporary file, then rename) when the run starts, with status running, and again when the session closes. It holds the session id, run type, status, version, times, errors and warnings, and every item's name, stage, result (installed / skipped / failed) and a short error. The schema and value names match the macOS build.

--last-run

Prints the record as one line of at most 1000 characters, made for a remediation script's output column:

<time ISO to the minute, with offset> <run_type> <status> v<version> installed=N skipped=N failed=N[: name: error; ...]

It prints no run recorded when there is no file. It always exits 0, and it runs before the elevation check and the single-instance lock, so it opens no session.

Downloads

HttpClient's default 100-second Timeout covers the whole response body, so a large MSI on a slow link was cancelled mid-transfer. Downloads now stream with Timeout = Infinite:

  • An attempt fails after 60 seconds with no data, or after 30 minutes in total.
  • Stalls, network errors and 5xx responses are retried up to three attempts, with 10- and 20-second waits between them.

Tests

  • LastRunTests: formatter, length cap, run-type mapping, error shortening, atomic write and read-back. 41/41 tests pass.
  • The signed end-to-end results are below.

Signed end-to-end run (x64 CLI, signed through build.ps1, already-provisioned Windows 11 PC, local manifest)

Run Exit --last-run Detection exit
before any run 0 no run recorded -
baseline, ledger hit 0 2026-10-04T19:20Z baseline completed v2026.10.04.1218 installed=0 skipped=1 failed=0 0
manifest returns 404 1 2026-10-04T19:20Z provisioning failed v2026.10.04.1218 installed=0 skipped=0 failed=0 1
baseline, one stalled download 2 ... baseline partial_failure ... installed=0 skipped=1 failed=1: Stalled Download: Download stalled: no data for 60 seconds 1
  • Slow download. A 1.6 MB item served at about 12 KB/s took 136 s and installed. The old client cancelled at 100 s.
  • Stalled download. An item that sent headers and then nothing failed each attempt at 60 s. It was retried after 10 s and then 20 s, and failed after the third attempt.
  • last-run.json while running. run_type: provisioning, status: running, end_time: null, duration_seconds: null, items: [].
  • At finish. run_type: baseline (session.json matches), with per-item results. Only failed items carry error.
  • Nothing visible. No dialog process appeared in any baseline run.

session.json now starts as run_type "provisioning" and is relabelled
"skip", "baseline" or "provisioning" once the preflight decides. A failed
preflight stays "provisioning".

A new last-run.json in ProgramData is written atomically when the run
starts (status "running") and again when the session closes. It carries the
session id, run type, status, version, times, error and warning counts, and
each item's name, stage, result (installed, skipped, failed) and a short
error. The schema matches the macOS build. --last-run prints it as one line
of at most 1000 characters for a remediation script. It prints
"no run recorded" when there is none, and always exits 0 without elevation
or a session directory.

Package downloads used HttpClient's default 100-second timeout, which covers
the whole body, so a large MSI on a slow link was cancelled mid-transfer.
Downloads now stream with no overall client timeout. An attempt fails after
60 seconds without data or 30 minutes in total, and stalls, network errors
and 5xx responses are retried up to three attempts.

Closes #51
…time

The --last-run time is UTC to the minute (2026-10-04T19:00Z). A failed
preflight, or a manifest that cannot be loaded, now ends the session as
"failed" rather than "partial_failure". At start, last-run.json writes
end_time and duration_seconds as null rather than leaving them out.

Refs #51
@rodchristiansen
rodchristiansen merged commit 44826e6 into main Oct 4, 2026
2 checks passed
@rodchristiansen
rodchristiansen deleted the feature/run-reporting branch October 4, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report each run's mode and outcome; fix the 100-second download timeout

1 participant