• Stars
    star
    273
  • Rank 145,447 (Top 3 %)
  • Language
    PowerShell
  • License
    MIT License
  • Created almost 8 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

PowerShell Dependency Handler

Build status

PSDepend

This is a simple PowerShell dependency handler. You might loosely compare it to bundle install in the Ruby world or pip install -r requirements.txt in the Python world.

PSDepend allows you to write simple requirements.psd1 files that describe what dependencies you need, which you can invoke with Invoke-PSDepend

WARNING:

  • Minimal testing. This is in my backlog, but PRs would be welcome!
  • This borrows quite heavily from PSDeploy. There may be leftover components that haven't been adapted, have been improperly adapted, or shouldn't have been adapted
  • Would love ideas, feedback, pull requests, etc., but if you rely on this, consider pinning a specific version to avoid hitting breaking changes.

Getting Started

Installing PSDepend

# PowerShell 5
Install-Module PSDepend

# PowerShell 3 or 4, curl|bash bootstrap. Read before running something like this : )
iex (new-object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/RamblingCookieMonster/PSDepend/master/Examples/Install-PSDepend.ps1')

# Git
    # Download the repository
    # Unblock the zip
    # Extract the PSDepend folder to a module path (e.g. $env:USERPROFILE\Documents\WindowsPowerShell\Modules\)

# Import and start exploring
Import-Module PSDepend
Get-Command -Module PSDepend
Get-Help about_PSDepend

Example Scenarios

In-depth:

Recipes:

Defining Dependencies

Store dependencies in a PowerShell data file, and use *.depend.psd1 or requirements.psd1 to allow Invoke-PSDepend to find your files for you.

What does a dependency file look like?

Simple syntax

Here's the simplest syntax. If this meets your needs, you can stop here:

@{
    psake        = 'latest'
    Pester       = 'latest'
    BuildHelpers = '0.0.20'  # I don't trust this Warren guy...
    PSDeploy     = '0.1.21'  # Maybe pin the version in case he breaks this...

    'RamblingCookieMonster/PowerShell' = 'master'
}

And what PSDepend sees:

DependencyName                   DependencyType  Version Tags
--------------                   --------------  ------- ----
psake                            PSGalleryModule latest
BuildHelpers                     PSGalleryModule 0.0.20
Pester                           PSGalleryModule latest
RamblingCookieMonster/PowerShell GitHub          master
PSDeploy                         PSGalleryModule 0.1.21

There's a bit more behind the scenes - we assume you want PSGalleryModules or GitHub repos unless you specify otherwise, and we hide a few dependency properties.

We can also indicate the dependency type more explicitly if desired:

@{
    'PSGalleryModule::InvokeBuild' = 'latest'
    'GitHub::RamblingCookieMonster/PSNeo4j' = 'master'
}

Flexible syntax

What else can we put in a dependency? Here's an example using a more flexible syntax. You can mix and match.

@{
    psdeploy = 'latest'

    buildhelpers_0_0_20 = @{
        Name = 'buildhelpers'
        DependencyType = 'PSGalleryModule'
        Parameters = @{
            Repository = 'PSGallery'
            SkipPublisherCheck = $true
        }
        Version = '0.0.20'
        Tags = 'prod', 'test'
        PreScripts = 'C:\RunThisFirst.ps1'
        DependsOn = 'some_task'
    }

    some_task = @{
        DependencyType = 'task'
        Target = 'C:\RunThisFirst.ps1'
        DependsOn = 'nuget'
    }

    nuget = @{
        DependencyType = 'FileDownload'
        Source = 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe'
        Target = 'C:\nuget.exe'
    }
}

This example illustrates using a few different dependency types, using DependsOn to sort things (e.g. some_task runs after nuget), tags, and other options.

You can inspect the full output as needed. For example:

# List the dependencies, get the third item, show all props
$Dependency = Get-Dependency \\Path\To\complex.depend.ps1
$Dependency[2] | Select *
DependencyFile : \\Path\To\complex.depend.psd1
DependencyName : buildhelpers_0_0_20
DependencyType : PSGalleryModule
Name           : buildhelpers
Version        : 0.0.20
Parameters     : {Repository,SkipPublisherCheck}
Source         :
Target         :
AddToPath      :
Tags           : {prod, test}
DependsOn      : some_task
PreScripts     : C:\RunThisFirst.ps1
PostScripts    :
Raw            : {Version, Name, Tags, DependsOn...}

Note that we replace certain strings in Target and Source fields:

  • $PWD (or .) refer to the current path
  • $ENV:USERPROFILE, $ENV:TEMP, $ENV:ProgramData, $ENV:APPDATA
  • Variables need to be in single quotes or the $ needs to be escaped. We replace the raw strings with the values for you. This will not work: Target = "$PWD\dependencies". This will: Target = '$PWD\dependencies'
  • If you call Invoke-PSDepend -Target $Something, we override any value for target
  • Thanks to Mike Walker for the idea!

Repository Credentials

If you are using a PowerShell module repository that requires authentication then add those to your dependency. When working with credentials there are two parts we need to consider:

  • Credential property of our dependency.
  • Credentials parameter for Invoke-PSDepend.
@{
    psdeploy = 'latest'

    buildhelpers_0_0_20 = @{
        Name = 'buildhelpers'
        DependencyType = 'PSGalleryModule'
        Parameters = @{
            Repository = 'PSGallery'
            SkipPublisherCheck = $true
        }
        Version = '0.0.20'
        Credential = 'must_match'
    }
}

Now create a PSCredential object with the credentials to access the repository and run it:

Invoke-PSDepend -Path C:\requirements.psd1 -Credentials @{ 'must_match' = $creds }

Make sure whatever you use as must_match is the same in the dependency as it is in the hashtable you pass to the Credentials parameter.

Exploring and Getting Help

Each DependencyType - PSGalleryModule, FileDownload, Task, etc. - might treat these standard properties differently, and may include their own Parameters. For example, in the BuildHelpers node above, we specified a Repository and SkipPublisherCheck parameters.

How do we find out what these mean? First things first, let's look at what DependencyTypes we have available:

Get-PSDependType
DependencyType  Description                                                 DependencyScript
--------------  -----------                                                 ----------------
PSGalleryModule Install a PowerShell module from the PowerShell Gallery.    C:\...\PSDepend\PSDepen...
Task            Support dependencies by handling simple tasks.              C:\...\PSDepend\PSDepen...
Noop            Display parameters that a depends script would receive...   C:\...\PSDepend\PSDepen...
FileDownload    Download a file                                             C:\...\PSDepend\PSDepen...

Now that we know what types are available, we can read the comment-based help. Hopefully the author took their time to write this:

Get-PSDependType -DependencyType PSGalleryModule -ShowHelp
...
DESCRIPTION
    Installs a module from a PowerShell repository like the PowerShell Gallery.

    Relevant Dependency metadata:
        Name: The name for this module
        Version: Used to identify existing installs meeting this criteria, and as RequiredVersion for installation.  Defaults to 'latest'
        Target: Used as 'Scope' for Install-Module.  If this is a path, we use Save-Module with this path.  Defaults to 'AllUsers'

PARAMETERS
...
    -Repository <String>
        PSRepository to download from.  Defaults to PSGallery
    -SkipPublisherCheck <Switch>
        Bypass the catalog signing check.  Defaults to $false

In this example, we see how PSGalleryModule treats the Name, Version, and Target in a depend.psd1, and we see Parameter's specific to this DependencyType, 'Repository' and 'SkipPublisherCheck'

Finally, we have a few about topics, and individual commands have built in help:

Get-Help about_PSDepend
Get-Help about_PSDepend_Definitions
Get-Help Get-Dependency -Full

Extending PSDepend

PSDepend is extensible. To create a new dependency type:

  • Pick a name. We'll use Nothing as an example
  • Create DependencyType.ps1 (substituting in your name, e.g. Nothing.ps1) in the PSDependScripts folder
  • Your DependencyType.ps1 (Nothing.ps1 in this example) should...
    • Have comment based help
    • Include details on how you use Dependency metadata. For example, in Git.ps1, Version is used in git checkout
    • Include a PSDependAction parameter that takes Install, Test, Import, or a subset of these. Example parameter declaration
    • Depending on which PSDependAction is specified by the user, your script should install, test (return true or false depending on whether the dependency exists - sometimes this is impossible to check), and import (import the dependency - if appropriate, this might import a module or dot source code, for example)
  • Add your new dependency type to PSDependMap.psd1

So! In our example, we would create PSDepend\PSDependScripts\Nothing.ps1, with the following code:

<#
    .SYNOPSIS
        Example Dependency

    .DESCRIPTION
        Example Dependency

        Relevant Dependency metadata:
            Version: Used for nonsense output

    .PARAMETER Dependency
        Dependency to process

    .PARAMETER StringParameter
        An example parameter that does nothing

    .PARAMETER PSDependAction
        Test, Install, or Import the dependency.  Defaults to Install

        Test: Return true or false on whether the dependency is in place
        Install: Install the dependency
        Import: Import the dependency
#>
[cmdletbinding()]
param (
    [PSTypeName('PSDepend.Dependency')]
    [psobject[]]$Dependency,

    [ValidateSet('Test', 'Install', 'Import')]
    [string[]]$PSDependAction = @('Install'),

    [string]$StringParameter
)

$Output = [PSCustomobject]@{
    DependencyName = $Dependency.DependencyName
    Status = "Invoking $PSDependAction action"
    BoundParameters = $PSBoundParameters.Keys
    Message = "Version [$Version]"
}

# Notice that we end the script if we're testing.
if( $PSDependAction -Contains 'Test' )
{
    Write-Verbose $Output
    return $true
}

$Output

Finally, we'll add an entry to PSDependMap.psd1:

    Nothing = @{
        Script= 'Nothing.ps1'
        Description = 'Example dependency'
    }

Lastly, we'll define a requirements.psd1 using this dependency:

@{
    ExampleDependency = @{
        DependencyType = 'Nothing'
        Version = 1
        Parameters = @{
            StringParameter = 'A thing'
        }
    }
}

Finally, run it!

Invoke-PSDepend -Path C:\requirements.psd1 -Test -Quiet

True

Invoke-PSDepend -Path C:\requirements.psd1
DependencyName    Status                  BoundParameters                               Message
--------------    ------                  ---------------                               -------
ExampleDependency Invoking Install action {StringParameter, PSDependAction, Dependency} Version [1]
Invoke-PSDepend -Path C:\requirements.psd1 -Import
DependencyName    Status                 BoundParameters                               Message
--------------    ------                 ---------------                               -------
ExampleDependency Invoking Import action {StringParameter, PSDependAction, Dependency} Version [1]

Notes

Major props to Michael Willis for the idea - check out his PSRequire, a similar but more feature-full solution.

More Repositories

1

PowerShell

Various PowerShell functions and scripts
PowerShell
934
star
2

Invoke-Parallel

Speed up PowerShell with simplified multithreading
PowerShell
374
star
3

PSDeploy

Simple PowerShell based deployments
PowerShell
343
star
4

PSSQLite

PowerShell module to query SQLite databases
PowerShell
287
star
5

PSSlack

PowerShell module for simple Slack integration
PowerShell
266
star
6

PSExcel

A simple Excel PowerShell module
PowerShell
243
star
7

BuildHelpers

Helper functions for PowerShell CI/CD scenarios
PowerShell
208
star
8

SecretServer

Secret Server PowerShell Module
PowerShell
87
star
9

PSStackExchange

PowerShell module to query Stack Exchange API
PowerShell
80
star
10

PSRabbitMq

PowerShell module to send and receive messages from a RabbitMq server
PowerShell
45
star
11

PSHTMLTable

PowerShell module to spice up ad hoc notifications and reports
PowerShell
37
star
12

Git-Presentation

Presentation materials for Git and GitHub TechSession
33
star
13

WritingModules

Material accompanying PowerShell + DevOps Summit session
PowerShell
31
star
14

PSDiskPart

DiskPart PowerShell Module
PowerShell
31
star
15

Infoblox

Infoblox PowerShell Module
PowerShell
30
star
16

PSNeo4j

Simple Neo4j PowerShell Wrapper
PowerShell
29
star
17

ADGrouper

Define dynamic AD security group membership via yaml
PowerShell
18
star
18

Dots

A janky, neo4j based CMDB glued together with PowerShell
PowerShell
15
star
19

Citrix.NetScaler

PowerShell module for working with Citrix NetScaler REST API
PowerShell
15
star
20

PSRT

PowerShell wrapper for Request Tracker
PowerShell
10
star
21

TireFire

A janky PowerShell module to simplify managing notes and their metadata
PowerShell
7
star
22

PSStash

Atlassian Stash PowerShell Module
PowerShell
7
star
23

PSPagerDuty

Simple PowerShell PagerDuty module
PowerShell
7
star
24

PSLDAPQueryLogging

PowerShell module to simplify configuring AD LDAP diagnostic logging
PowerShell
7
star
25

PSPuppetDB

Simple module for querying the PuppetDB API
PowerShell
6
star
26

Wait-Path

Wait for a path to exist
PowerShell
5
star
27

CommunityLightningDemos2017

Proposals, and eventually demo material for Community Lightning Demos
PowerShell
5
star
28

PSSensu

Simple PowerShell module for working with the Sensu Go API
PowerShell
3
star
29

SessionMaterials

Materials or links to materials from sessions I've participated in
PowerShell
3
star
30

AppVeyor-DSC-Test

POC to test DSC configurations on a fresh VM from AppVeyor
PowerShell
2
star
31

AppVReporting

App-V Reporting PowerShell Module
PowerShell
2
star
32

RamblingCookieMonster.github.io

CSS
2
star
33

lisa-kitchen-demo

Example used for Test-Kitchen demo
PowerShell
2
star
34

wip

Stuff that doesn't have a home yet
PowerShell
1
star
35

zAppVeyor-Explore

PowerShell
1
star