Skip to content

Invoke-WcdStep: one Step runner behind every Module #18

Description

@DireDoch

Every Module writes the same twelve lines around the one line that does the
work:

Invoke-WcdProgressCallback ... -Event 'Start'
try {
    <the work>
    Write-WcdLog -Level 'INFO' ...
    Invoke-WcdProgressCallback ... -Event 'Finish' -Kind 'success'
    $results += [pscustomobject]@{ Step = $key; Success = $true; Error = '' }
} catch {
    Write-WcdLog -Level 'ERROR' ...
    Invoke-WcdProgressCallback ... -Event 'Finish' -Kind 'error'
    $results += [pscustomobject]@{ Step = $key; Success = $false; Error = $_.Exception.Message; RemedyKey = '...' }
}

The Result shape is a literal written 71 times across 12 files. Its optional
fields — Severity, RemedyKey, RemedyArgs, Applied, RebootPending —
have no schema anywhere. A typo in a property name is not an error; the
Diagnostic reads $null and the row quietly renders as a plain success.

The runner

$results += Invoke-WcdStep -Module 'Config-Power' -Key $key `
    -LogPath $resolvedLogPath -ProgressCallback $ProgressCallback `
    -SuccessLog 'Power: screen timeout on AC set to 15 min.' `
    -FailureLabel 'Screen timeout on AC' -FailureRemedy 'PowerCfgFailed' `
    -Action { Invoke-WcdPowerCfg '/change' 'monitor-timeout-ac' '15' }

Invoke-WcdStep owns the progress events, both log lines, the try/catch, and
the Result shape. The Action returns nothing on success, or emits a Result
fragment when the Step has something to say beyond OK.

What it has to absorb

Not every Step is the simple case, and the runner is only worth it if it covers
these without a -Raw escape hatch that half the callers use:

  • Steps that succeed with a warning. Config-Power unelevated returns
    Success = $true; Severity = 'WARNING'; RemedyKey = 'RequiresAdmin' without
    running anything. The Action needs a way to say "did not run, here is why".
  • Steps that carry extra fields. Applied on ComputerName / DomainJoin,
    RebootPending on WindowsUpdateReboot. Both are read by the Diagnostic to
    decide whether to raise the restart row.
  • Steps whose severity depends on the reading. Config-Disk and
    Config-BitLocker pick OK / WARNING from what the machine reported, not from
    whether the call threw.
  • Steps with RemedyArgs. The remediation template takes format arguments.
  • One Module, many dynamic Steps. Config-Applications and
    Config-Printer loop over manifest entries.

If those five need five parameters, this is not a deepening — reconsider.

Do it incrementally

This touches all 12 Modules and all 12 test files. Convert Config-Power and
Config-TaskbarLeft first and stop there. Two adapters is enough to know
whether the interface holds; twelve at once is enough to know only that the
tests still pass.

Do #17 first — it settles what a Module owes the orchestrator, and this
issue settles what a Step owes a Module. Wrong order and this gets rewritten.

Done when

  • Invoke-WcdStep in src/WcdHelpers.ps1, with comment-based help
  • tests/WcdHelpers.Tests.ps1 covers: success, throw, did-not-run-with-reason,
    severity chosen by the Action, extra fields carried through, RemedyArgs
  • Config-Power and Config-TaskbarLeft converted
  • Their existing tests pass unchanged — the Results are identical
  • A short note in the manual on when a Module should use the runner and when
    it should not
  • Remaining 10 Modules left alone, deliberately, for a follow-up

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:architectureModule seams, orchestrator, test surfacerefactorRestructuring without changing behaviour

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions