choco icon indicating copy to clipboard operation
choco copied to clipboard

(#3344) Adds ParameterBlock Handling to Chocolatey Script Runner

Open JPRuskin opened this issue 9 months ago • 0 comments

Description Of Changes

This PR introduces the ability for ChocolateyInstall, ChocolateyBeforeModify, and ChocolateyUninstall scripts to have and utilise PowerShell param() blocks to handle parameters.

It does this by adding a function (Get-PackageScriptParameters), which calculates what parameters a script has and passes any parameters found by the existing function Get-PackageParameters that match the parameter names to the script. Optionally, we could handle aliases, but this implementation does not yet.

The new function is called within the ChocolateyScriptRunner before invoking the script, and the resultant hashtable is "splatted" with the call. When no matching parameters are found (on the script and in packageparameters), this results in no change to behaviour.

It's worth noting that though this does allow for usage of parameter attributes and validation, such as [Parameter(Mandatory)], [ValidateSet()] and the like, Chocolatey can currently swallow some useful output (e.g. with SomeString being a mandatory parameter): image vs the PowerShell default: image This could possibly be improved in the future.

It adds the functionality, but doesn't remove the existing parameter handling - so all existing packages will continue working.

SMA Update

As a part of this, because of the use of the System.Management.Automation.Language to assess the param block, the System.Management.Automation assembly present in the lib/powershell folder was updated from a version matching the version shipped with PowerShell 2.0 (best guess) to a version from our earliest currently supported version of Windows - 2012.

This DLL isn't shipped in any of our builds; it's just used to ensure our code uses methods et al that are supported by the specific DLL we have embedded in the repository.

Specifically, I grabbed this from the uncertain/fun provenance of a Windows Server 2012 VM, in the folder C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35. There's not a similar version on nuget.org, annoyingly, which only has versions from 2018 onwards starting at 6.0.4.

There is an argument that this is a breaking change, as it may no longer work on machines we don't support - but that "break" has already happened. We do not support Windows versions prior to 2012 (and that only in Azure). Everything else is additive-only, and backwards compatible via a "lovely" new extension I'm looking to publish.

Motivation and Context

This allows for standardisation of how package maintainers handle parameters within their scripts, and helps Chocolatey Community Repository users and moderators to more easily understand what parameters can be used, what default values are used, and what (if any) validation is in place.

Testing

  • Grab https://chocolatey.org/install.ps1 and the modified version of the Chocolatey nupkg package, copy them to your test environment.
  • Set-ExecutionPolicy RemoteSigned Process -Force and Install with .\Install.ps1 -ChocolateyDownloadUrl .\Path\To\chocolatey.nupkg
  • Optional: install a random package without parameters to ensure I've not broken the existing functionality choco install cloudflared --confirm
  • Optional: install a random package with parameters to ensure I've not broken the existing functionality choco install Temurin21jre --params="/ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome" --confirm
  • Grab a package with param blocks available, e.g. testextension.1.0.0.zip (attached as a zip, as nupkg is not a supported file type) and copy it to the test environment (or have it in a repository)
  • choco install testextension --params='/SomeString:A String Value' --confirm (some massaging required for source) image

NB: testextension will fail to install if the PowerShell parameter value "SomeString" provided doesn't match the package parameter found by Get-PackageParameters. The install script is partially shown below:

param(
    [string]$SomeString
)

$PackageParameters = Get-PackageParameters

if ($PackageParameters.SomeString -ne $SomeString) {
    throw "'$SomeString' was not equal to '$($PackageParameters.SomeString)'"
}

Operating Systems Testing

  • Windows Server 2012 image
  • Windows Server 2022 image
  • Windows 11 (Sandbox) image

I also have an extension package that adds the same functionality to any other extension-supporting version of Chocolatey CLI. This hopefully means that this can be an acceptable thing to use for Community packages.

image

I am very excited about this, despite the code being utterly despicable.

I have had to slightly revise my backwards compatibility happiness - it doesn't work with the earliest mention of Chocolatey extensions (0.9.10) because Get-PackageParameters doesn't exist at that point. I could fix this by packing a backup version fo the function in the extension, but I feel like supporting back to the 0.10.8 is enough for any unreasonable expectation: image

Change Types Made

  • ~[ ] Bug fix (non-breaking change).~
  • [x] Feature / Enhancement (non-breaking change).
  • ~[ ] Breaking change (fix or feature that could cause existing functionality to change).~ See SMA update.
  • ~[ ] Documentation changes.~
  • [x] PowerShell code changes.

Change Checklist

  • ~[ ] Requires a change to the documentation.~
  • ~[ ] Documentation has been updated.~
  • [x] Tests to cover my changes, have been added.
  • [x] All new and existing tests passed?
  • [x] PowerShell code changes: PowerShell v3 compatibility checked?

Related Issue

Resolves #3344

JPRuskin avatar Jun 04 '25 19:06 JPRuskin