Extend Chocolatey With PowerShell Modules (extensions)

Extend Chocolatey With PowerShell Modules (extensions)

For years Chocolatey has allowed you to extend Chocolatey with your own PowerShell modules and functions. These are known as extensions.

Overview

Extensions allow you to package up PowerShell functions that you may reuse across packages as a package that other packages can use and depend on. This allows you to use those same functions as if they were part of Chocolatey itself. Chocolatey loads these PowerShell modules up as part of the regular module import load that it does for built-in PowerShell modules.

Why Would I Create an Extension?

To reduce code in your Chocolatey automation scripts. Packaging up logic as functions into a PowerShell module that you can version independently, fix issues in, and enhance without needing to touch existing packages that you have is pretty powerful.

Creating a Chocolatey Extension

When it comes to extensions, Chocolatey takes a conventional approach. You must create a package with the suffix ".extension" and have a extensions folder with at least one PowerShell module in it.

The name of the package should be "extensionname.extension". The name of the package minus ".extension" will be the name of the extension that is installed.

  • To create an extension package, run choco new name.extension and then delete everything but the nuspec.
  • Then create an extensions folder in the root of the package.
  • In the extensions folder, create your PowerShell module.
  • The important file you will need is a PSM1 (PowerShell Module) file that loads up and ensures functions are available. Have a look at profile module and chocolatey-core.extensions module.
  • When those functions are loaded by Chocolatey, they will already be available when your scripts run so you won't need to load up the files again in your install scripts - the functions will already be available!

Here's an example: https://community.chocolatey.org/packages/chocolatey-core.extension. The source is at https://github.com/chocolatey-community/chocolatey-packages/tree/master/extensions

Yes, it is really that easy. Enjoy!

Recommendations

Naming Your Extension

Avoid "Chocolatey" as part of the name. Yes the example is named that, but this extension is owned by the Core Chocolatey team, so it makes sense for that to be the name.

PowerShell Modules

  • The recommendation is typically as few PowerShell modules as possible in an extension, just enough to represent what that extension does. Strive for one module per extension package, although that may not be realistic.
  • The module should explicitly export the functions, aliases, and cmdlets that are wanted to be used in Chocolatey automation scripts.

Taking a Dependency on an Extension Package

When taking a dependency on an extension package, it is recommended to take a minimum version dependency. If there is functionality that is enhanced in that extension, you should bump that dependency version.

Minimum Version Depdendencies

What does a minimum version depdency look like?

<dependencies>
  <dependency id="chocolatey-core.extension" version="1.1.0" />
</dependencies>

Avoid Version Ranges For Extensions

Avoid version ranges when it comes to extensions as it can lock out fixes and enhancements in the future.


<dependencies>
  <!-- This means at least 1.0.0, and anything less than 2 -->
  <dependency id="chocolatey-core.extension" version="[1.0.0, 2)" />
  <!-- This means anything between 1.0.0 and 2.0.1 (including 2.0.1) is good to go -->
  <dependency id="another.extension" version="[1.0.0, 2.0.1]" />
</dependencies>

Avoid Exact Version Dependencies For Extensions at All Costs

Try to never lock into an exact version dependency:

<!-- DO NOT DO THIS -->
<dependencies>
  <dependency id="chocolatey-core.extension" version="[1.1.0]" />
</dependencies>

This locks every other package into that singular version and does not allow for upgrades and fixes.

Version-less Dependencies

There is also the concept of versionless dependencies.

<dependencies>
  <dependency id="chocolatey-core.extension" />
</dependencies>

Folks typically have used these in the past. They are less bad, but it just means that any version will do.