Currently at work, we have been improving our practices around coding in PowerShell and producing better and more sane automations. I have blogged before about the must-have tools for PowerShell development and in this post, will take a look at different alternatives to handle dependencies for PowerShell modules.
PowerShell has come a long way since its inception, but managing dependencies is still a source of issues for daily operations, specially when we have to deal with multiple repository locations for our modules and scripts, eg: PowerShell Gallery and an in-house Gallery.
Module installing vs importing #
Before diving any further into the analysis, we need to address the difference between installing a module (
Install-Module) and importing it (
Install-Module downloads modules from an external repository, by default PowerShell Gallery, and makes them available for use in other scripts and modules that run on the computer. On the other hand,
Import-Module brings the modules and their functions into your current PowerShell session, but only if the module is already installed. In most scenarios, you can bypass calling
Import-Module directly because the module will imported the first time a command is called from the module, as long as the module is already present on the system.
Available dependency management options #
Nowadays, there are several options available in the PowerShell ecosystem to handle dependencies. Below, we are going to briefly mention some of them and highlights some of its main points.
Bundled in PowerShell #
As part of the PowerShell definition of a module, it is possible to specify a Module Manifest. A Manifest, in essence, allows to include metadata about your module that can be used for multiple goals, among them, specifying dependencies.
- RequiredModules: As the documentation specifies, it contains he modules list to be loaded in the global environment. It is also pointed out, that this will only check if the modules are already loaded.
- NestedModules: As explained in the documentation, this is similar to calling
Import-Modulewithin your script. The main advantage is that this happens before actual module is loaded into the session.
A limitation of these metadata properties is that they don't work properly when dealing with dependencies that spawn multiple repositories.
Community-driven modules #
- PSDepend: Loosely based on the idea of
bundle installin Ruby or
pip installin Python, PSDepend is a dependency handler for PowerShell modules. It brings a flexible syntax for declaring dependencies and supports multiple types of dependencies, such as: gallery modules, github-based modules, file download. Types of dependencies can be added if required by implementing the appropiate definitions.
Library modules vs application modules #
Handling dependencies always depends on the project's type. This is true regarding of the language, framework or architecture. In particular for PowerShell, we can look at a classification of modules based on their end goal.
- Libraries: Refers to the PowerShell modules that provide reusable functionality to other modules, both library modules and applications.
- Applications: Usually, they are not depended upon. Applications are meant to be deployed to specific environments and running specific tasks
Modules that act as libraries should avoid pinning down specific dependencies as much as possible. They should aim to define abstract dependencies and avoid conflicts in their subdependencies.
On the contrary, modules that aim to work more as applications should use exact versions for all their dependencies. This improves determinism and repeatability of the deployment and execution.
In particular to PowerShell, the line between Libraries and Applications is a fuzzy one due to the nature of PowerShell itself. Nevertheless, most times it is not too difficult to classify a module based on its usage.
In this post, we went over an overview of the state of dependency management in PowerShell. We discussed first the way that PowerShell handles installation/import of modules and then compared different ways to solve this task. Finally, we analyzed how dependencies should be addressed based on the type of module.
To conclude, thanks you so much for reading this post. Hope you liked reading it as much as I did writing it and stay tuned for more!!