Skip to content

fix(ci-build-infra): document NuGet cache fallback safety and suppress System.Reactive packages.config warning (#730) - #747

Merged
drmoisan merged 8 commits into
mainfrom
bug/ci-build-infra-debt-730
Sep 3, 2026
Merged

fix(ci-build-infra): document NuGet cache fallback safety and suppress System.Reactive packages.config warning (#730)#747
drmoisan merged 8 commits into
mainfrom
bug/ci-build-infra-debt-730

Conversation

@drmoisan

@drmoisan drmoisan commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Suggested title

fix(ci-build-infra): document NuGet cache fallback safety and suppress System.Reactive packages.config warning (#730)

Summary

Why

  • Finding 1 (cache fallback): .github/workflows/_build-analyzers.yml, _build-nullable.yml, and _mstest-coverage.yml each use a bare-prefix restore-keys fallback (nuget-${{ runner.os }}-) with no lock-file hash and no restore-verification step. Research confirmed this is already safe for this repository's packages.config + classic nuget.exe restore model: every package is restored into a version-qualified directory (packages/{id}.{version}/) that exactly matches every HintPath, and nuget restore runs unconditionally after the cache step in all three workflows. The change documents this invariant rather than fixing a defect, since none exists.
  • Finding 2 (System.Reactive warning): packages.config pins System.Reactive 7.0.0, which is unsupported for packages.config-style references and emits an "unsupported scenario" warning (System.Reactive.PackagesConfigCheck.targets) on every build of the five consuming projects. No suppression existed. RxUseUnsupportedPackagesConfig=true is the package's own documented escape hatch for this exact, intentionally-accepted trade-off (this repository keeps its legacy VSTO / .NET Framework 4.8.1 projects on packages.config rather than migrating to PackageReference).

What Changed

Tooling / CI

  • .github/workflows/_build-analyzers.yml, _build-nullable.yml, _mstest-coverage.yml: identical 16-line explanatory comment block inserted immediately above restore-keys: in each file. Comment-only; key:, path:, uses: (actions/cache@v4), restore-keys: and its value, and the subsequent Restore solution step are byte-identical to before.

Build configuration

  • Directory.Build.props (new, repository root): sets RxUseUnsupportedPackagesConfig to true inside a <PropertyGroup>, with an inline XML comment documenting the accepted trade-off. Picked up automatically by all five System.Reactive-consuming projects via MSBuild's standard Directory.Build.props auto-import; inert for the other thirteen projects in the solution.

Docs / evidence

  • Feature folder (docs/features/active/2026-09-02-ci-build-infra-debt-730/): issue, spec, research, atomic plan (9 preflight/revision rounds, documented in the plan's own Framing section), and full baseline/post-change evidence (msbuild rebuild logs, csharpier check, vstest regression run, git-scope-boundary diffs).
  • A remediation cycle (also fully evidenced) fixed one artifact-hygiene finding: an absolute host path with the operator account name in research/research.2026-09-02T09-15.md line 8, replaced with the <repo-root> placeholder already used elsewhere in this feature's evidence.

Architecture / How It Fits Together

Both fixes are additive, independent, and configuration-only:

  • The comment block sits above an unmodified restore-keys: key; it has zero effect on YAML evaluation, cache key computation, or the cache/restore step's control flow.
  • Directory.Build.props is picked up by MSBuild's Microsoft.Common.props auto-import chain, the same mechanism already proven live in this repository through the existing Directory.Build.targets file. It supplies exactly one new property that no .csproj currently sets, so there is no override or collision risk with any of the eighteen projects in the solution.

Verification

Completed (evidence under docs/features/active/2026-09-02-ci-build-infra-debt-730/evidence/):

  • dotnet tool run csharpier check . — exit 0, no formatting drift.
  • msbuild TaskMaster.sln /t:Rebuild ... /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true — baseline: 5 System.Reactive.PackagesConfigCheck warnings (one per affected project: QuickFiler, TaskMaster, ToDoModel, UtilitiesCS, UtilitiesCS.Test), 0 errors. Post-change: 0 such warnings, 0 errors — genuine recompiles confirmed via csc.exe/CoreCompile invocation counts in both logs.
  • msbuild TaskMaster.sln /t:Rebuild ... /p:TreatWarningsAsErrors=true — same baseline-to-zero warning delta, 0 errors in both passes.
  • vstest.console.exe regression run (UtilitiesCS.Test + QuickFiler.Test, /EnableCodeCoverage /InIsolation) — 6095/6095 passed, 0 failed.
  • Workflow diffs independently verified comment-only (dual-parser deep comparison against origin/main during feature review).
  • Absolute-host-path sanitization: 0 residual matches for the operator account name across the entire changed-file set, confirmed via a run-time-derived (not hardcoded) sweep.

Recommended (not run by this branch, informational only):

  • Confirm on the first post-merge CI run of each of the three named workflows that cache hit/miss/fallback behavior is unaffected (expected, since the diff is comment-only).
  • Confirm on the first post-merge full solution rebuild that the five System.Reactive.PackagesConfigCheck warnings no longer appear.

Backward Compatibility / Migration Notes

None. Both fixes are fully backward compatible:

  • The comment insertion changes no evaluated YAML semantics.
  • Directory.Build.props introduces a new, additive property recognized only by System.Reactive.PackagesConfigCheck.targets; it is silently ignored by every other project in the solution.
  • No file rename, removal, or breaking change of any kind.

Risks and Mitigations

  • Solution-wide reach of Directory.Build.props. A root-level Directory.Build.props is auto-imported by all eighteen .csproj files in the solution, not just the five System.Reactive-consuming ones. Mitigation: this change adds exactly one property, confirmed inert for the thirteen non-System.Reactive projects; any future addition to this file should be re-evaluated for solution-wide impact before merging.
  • Vendor guard-target behavior not directly inspected. The exact System.Reactive.PackagesConfigCheck.targets XML was not read directly during research (packages were not yet restored in that session), so the property name/effect rests on corroborating evidence rather than a live read of the vendor file. Mitigation: the pre/post rebuild-transcript verification in this PR directly observes the real vendor guard target's behavior at build time (5 warnings → 0), closing this gap empirically.
  • Repository history still contains the pre-sanitization research document blob in four earlier commits on this branch (the file was modified, not added, so its prior content remains reachable via those commits' trees). Mitigation: recommend a squash merge for this PR so the pre-sanitization blob does not become reachable from main's history.

Review Guide

Suggested order:

  1. Directory.Build.props (new file, 19 lines) — the substantive change.
  2. The three workflow file diffs — mechanically identical 16-line comment insertions; diffing any one confirms the pattern for all three.
  3. docs/features/active/2026-09-02-ci-build-infra-debt-730/spec.md — acceptance criteria and scope boundaries.
  4. Evidence files under evidence/baseline/ and evidence/qa-gates/ — supporting proof, not required reading for a correctness review of the two fixes themselves.

Noisy/mechanical: four raw MSBuild rebuild logs (evidence/*.log, ~11.7–12k lines each) are committed as evidence; they are sanitized of host-identifying paths and do not need line-by-line review.

Follow-ups

  • Four references to the mutable path docs/features/active/2026-09-02-ci-build-infra-debt-730/... (three workflow comments, one Directory.Build.props comment) will go stale once this feature folder is archived. Not addressed in this PR to keep the change strictly scoped; a follow-up cleanup can drop the path prefix and rely on the issue #730 reference already present in each comment.
  • Cosmetic: the inserted comment block sits at 12-space indentation (matching the restore-keys: block-scalar value), one level deeper than the sibling key:/restore-keys: lines at 10 spaces. Confirmed functionally inert (dual-parser verification), but could be dedented for visual consistency in a future pass.

GitHub Auto-close

drmoisan and others added 8 commits September 2, 2026 09:42
…ic plan

Preparation-mode run for parallel_slug bugs-2026-09-02: promotes issue #730
(NuGet cache restore-keys documentation and RxUseUnsupportedPackagesConfig
suppression via a single repository-root Directory.Build.props), completes
research and spec.md, and lands an atomic plan cleared through three
preflight rounds (PREFLIGHT: ALL CLEAR). Atomic execution is deferred to
parallel-orchestrator per the preparation-mode contract.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LTjXvNFHVh7Fo7kYGgWsx2
…n spec/plan

The parallel-scheduling harvester reads every backtick-delimited,
whitespace-free, repository-relative-looking path token in spec.md and the
plan as a path this item WRITES, with no notion of exclusion vs. write
polarity. spec.md and the plan quoted scope-exclusion paths, must-not-touch
files, model/context references, and project names inside backticks,
falsely making this item appear to write the .claude, .codex, and .agents
trees plus the two published config/*.json files, two of which are shared
surfaces that would collapse the 13-item bugs-2026-09-02 run into fully
sequential cohorts.

Adds an explicit "## Write Set" section to spec.md naming exactly the four
files this plan's diff creates or modifies (the three workflow comment
insertions plus the new root Directory.Build.props), and removes backticks
from every scope-exclusion/must-not-touch/model-reference/project-name
mention elsewhere in spec.md and the plan, converting each to plain prose
while preserving sentence meaning. No task, acceptance-criterion substance,
command, or evidence path changed.

Cleared atomic-executor preflight (round 3, PREFLIGHT: ALL CLEAR) after two
prior rounds: round 1 found inconsistent .csproj backtick treatment in
spec.md (fixed), and round 2 found that the new Write Set section shifted
spec.md's Acceptance Criteria section down by 7 lines, staling 9 line-number
citations in the plan's Framing note and Phase 3 AC-traceability tasks
(fixed and re-verified against current tree state).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LTjXvNFHVh7Fo7kYGgWsx2
Reconcile before atomic execution; no conflicting files (verified via diff --name-only against no changes to .github/workflows/ or Directory.Build.props).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195CL93aqgKF19nj9h6trbt
…em.Reactive packages.config warning (#730)

Addresses the two findings in issue #730, both static build-infrastructure
configuration defects with no application source change.

Finding 1 — undocumented NuGet cache bare-prefix fallback. Adds an identical
16-line explanatory comment block immediately above `restore-keys:` in
`.github/workflows/_build-analyzers.yml`, `_build-nullable.yml`, and
`_mstest-coverage.yml`. The comment records why the bare-prefix fallback is
safe against stale package versions: `nuget restore` runs unconditionally
afterwards and is idempotent per package for packages.config-style restores,
which materialize each package under a version-qualified directory matching
every HintPath in this repository. Comment-only; the `key:`, `path:`, `uses:`,
`restore-keys:` value, and the subsequent restore step are byte-identical.

Finding 2 — missing System.Reactive suppression property. Adds a new
root-level `Directory.Build.props` setting `RxUseUnsupportedPackagesConfig`
to `true`, the package vendor's own documented switch for the packages.config
scenario this repository deliberately retains for its legacy non-SDK VSTO /
.NET Framework 4.8.1 projects. An inline XML comment records the
accepted-trade-off rationale.

Verification (evidence under
docs/features/active/2026-09-02-ci-build-infra-debt-730/evidence/):
- Baseline vs post-change `msbuild /t:Rebuild` for both the analyzer pass and
  the TreatWarningsAsErrors pass: System.Reactive.PackagesConfigCheck warnings
  5 -> 0, total warnings 5 -> 0, errors 0 -> 0 on both.
- `dotnet tool run csharpier check .`: exit 0.
- `vstest.console.exe` regression re-run of UtilitiesCS.Test and
  QuickFiler.Test: 6095/6095 passed, 0 failed, exit 0.
- Scope confirmed to exactly four changed files; no .csproj, packages.config,
  Directory.Build.targets, application source, coverage threshold, Pester job,
  or coverage gate is touched.
- The four raw MSBuild logs were sanitized of both absolute host-path prefixes
  (worktree root and main-checkout root) before commit; residual host-path
  match count is 0 and all four line counts are unchanged.

All eight acceptance criteria in spec.md are checked off.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195CL93aqgKF19nj9h6trbt
…on record (remediation cycle 1, round 2)

Remove operator account name and absolute host path from
research.2026-09-02T09-15.md line 8 and from remediation-plan.2026-09-02T23-56.md,
replacing each occurrence with the <repo-root> placeholder / a non-identifying
description per repository rule (no committed artifact may embed absolute host
paths or the operator account name).

Also commit the full feature-review-and-remediation record: plan.2026-09-02T08-57.md
checkbox residue, the four feature-review artifacts (code-review, feature-audit,
policy-audit, remediation-inputs, all dated 2026-09-02T23-47), this remediation
plan, and its sanitization-verification evidence.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195CL93aqgKF19nj9h6trbt
Residual checklist-metadata edit from the executor marking P0-T4 complete
after its own clean-tree verification passed; same pattern already
documented for plan.2026-09-02T08-57.md P3-T9.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195CL93aqgKF19nj9h6trbt
Adds policy-audit, code-review, and feature-audit (2026-09-03T00-33)
confirming the remediation commit closed PA-1/CR-1 with zero blocking
findings remaining, and refreshes the tracked PR context cache for #730.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195CL93aqgKF19nj9h6trbt
@drmoisan
drmoisan merged commit 196561c into main Sep 3, 2026
5 checks passed
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.

Bug: ci-build-infra-debt

1 participant