Skip to content

Splat build.ps1 arguments as a hashtable so the CI dispatch inputs work - #1727

Open
Rafael-SOWNet wants to merge 1 commit into
angularsen:masterfrom
Rafael-SOWNet:fix/ci-dispatch-splat
Open

Splat build.ps1 arguments as a hashtable so the CI dispatch inputs work#1727
Rafael-SOWNet wants to merge 1 commit into
angularsen:masterfrom
Rafael-SOWNet:fix/ci-dispatch-splat

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown

The problem

CI Build's workflow_dispatch inputs cannot be used. Setting any of them to false fails the
run immediately:

build.ps1: A positional parameter cannot be found that accepts argument '-SkipCoverage'.

$buildArguments is an array, and PowerShell array splatting binds positionally.
Build/build.ps1 declares only switches (SkipTests, SkipCoverage, SkipPack,
SkipArchive) and no positional parameters, so the first element has nowhere to bind.

Only the all-defaults path works, because that leaves the array empty and splats nothing. That
is why push and pull_request have never hit this — neither populates the inputs, so every
value resolves true and every branch of the if is skipped.

The fix

Splat a hashtable instead, which binds by parameter name.

Why it is worth fixing

Beyond the inputs doing what they say: dispatching this workflow by hand is the only way to get
a full matrix run on a branch that has no pull request open, and it is the practical way for a
first-time contributor to produce CI evidence while pull_request runs are gated behind
approval. Right now that path only works if you want the slowest possible run — full coverage,
pack and archive — because asking to skip any of it is what breaks it.

Validation

Same workflow, same inputs, before and after. Both runs on my fork.

Beforeci.yml exactly as it is on master, dispatched with
run_tests=true, collect_coverage=false, pack_nugets=false, upload_artifacts=false:

https://github.com/Rafael-SOWNet/UnitsNet/actions/runs/31124240783failure, at
Build selected components, with the message quoted above.

After — this branch, identical inputs:

https://github.com/Rafael-SOWNet/UnitsNet/actions/runs/31136388644success.

Passed! - Failed: 0, Passed: 52560, Skipped: 16, Total: 52576
Passed! - Failed: 0, Passed:  1731, Skipped:  0, Total:  1731
Passed! - Failed: 0, Passed:  1731, Skipped:  0, Total:  1731
Passed! - Failed: 0, Passed:   213, Skipped:  0, Total:   213
Passed! - Failed: 0, Passed:   241, Skipped:  0, Total:   241
Passed! - Failed: 0, Passed:     1, Skipped:  0, Total:     1
Passed! - Failed: 0, Passed:     1, Skipped:  0, Total:     1

Upload coverage to Codecov, Upload artifacts and Upload NuGet packages were all skipped,
which is what the inputs asked for and what previously could not be expressed.

What this does not do

No change to Build/build.ps1, to the default behaviour of push or pull_request, or to any
other workflow. .github/workflows/unitsnet-modular-ci.yml uses a plain run: and is
unaffected.

The workflow_dispatch inputs have no effect except to break the run. Array
splatting binds positionally, and build.ps1 declares only switches with no
positional parameters, so any non-default input fails the build immediately:

  build.ps1: A positional parameter cannot be found that accepts argument
  '-SkipCoverage'.

Only the all-defaults path works today, because that leaves the array empty.
Splatting a hashtable binds by parameter name instead.

This is invisible on push and pull_request, which never populate the inputs,
so it only bites someone dispatching the workflow by hand -- which is also the
only way to get a matrix run on a branch with no pull request open.
@Rafael-SOWNet

Copy link
Copy Markdown
Author

CI evidence, since this PR shows no checks (first-time-contributor gate) — and in this case the
evidence is the point, because the failure only appears at dispatch time and never in a PR build.

The bug needs at least one input set to a non-default value. With everything left at its default
the array stays empty, ./Build/build.ps1 @buildArguments splats nothing, and the run passes — which
is why this has gone unnoticed. Both runs below therefore dispatch with upload_artifacts: false
and every other input at its default.

Before — current master (3bf1ef4b3), unmodified:
https://github.com/Rafael-SOWNet/UnitsNet/actions/runs/31479700997failure, 5 seconds into
Build selected components, before anything was built:

CREATE_ARCHIVE: false

build.ps1: /home/runner/work/_temp/....ps1:7
Line |
   7 |  ./Build/build.ps1 @buildArguments
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | A positional parameter cannot be found that accepts argument '-SkipArchive'.

After — this PR's branch (681c96d1a), dispatched with the same inputs:
https://github.com/Rafael-SOWNet/UnitsNet/actions/runs/31479698969success.

Passed! - Failed: 0, Passed: 52560, Skipped: 16, Total: 52576  UnitsNet.Tests
Passed! - Failed: 0, Passed:  1731, Skipped:  0, Total:  1731  UnitsNet.NumberExtensions.Tests
Passed! - Failed: 0, Passed:  1731, Skipped:  0, Total:  1731  UnitsNet.NumberExtensions.Tests (the
                                                               CS14 project shares the assembly name)
Passed! - Failed: 0, Passed:   241, Skipped:  0, Total:   241  UnitsNet.Serialization.SystemTextJson.Tests
Passed! - Failed: 0, Passed:   213, Skipped:  0, Total:   213  UnitsNet.Serialization.JsonNet.Tests
Passed! - Failed: 0, Passed:     1, Skipped:  0, Total:     1  UnitsNet.GlobalSetup.Tests
Passed! - Failed: 0, Passed:     1, Skipped:  0, Total:     1  UnitsNet.GlobalSetup.DefaultFirst.Tests

The part worth more than the green tick: in the passing run the Upload artifacts step is
skipped
, while Upload NuGet packages and the coverage upload still ran. That is the input
being honoured, which is the state the workflow currently cannot reach at all — today any attempt
to skip a stage kills the job instead of skipping the stage.

Both runs are workflow_dispatch on the trees as they stand, with no delta commit: the "after" run
is dispatched directly on this PR's branch, and the "before" run on ci-check/ci-dispatch-splat-before,
which is 3bf1ef4b3 byte-for-byte. I am keeping that branch so the failing run stays reproducible.

Two notes on the change itself:

  • Hashtable splatting binds by name, so the order of the if blocks stops mattering, and adding
    a fifth switch later needs no thought about position.
  • Build/build.ps1 declares only [switch] parameters and no positional ones, so there is no
    arrangement of an array that would bind correctly — the array form is not merely fragile here, it
    cannot work for any non-empty case.

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.

2 participants