Automation can help with tasks that are mundane and time-consuming. It is important to be able to automate these tedious jobs, so they don’t take up too much of your precious time. If you need an example then look no further than the PSake project on GitHub where I will show you how easy it is to get started automating this way by using a tool called PowerShell!
This tutorial will teach you how to automate tasks with PSake and PowerShell. You can use the “psscriptanalyzer” command-line tool to analyze your scripts for errors or performance issues.
So you’ve learnt how to use a PowerShell script to automate operations. That’s fantastic! However, you now have a chaotic mass of scripts and modules, complete with a jumble of manual script executions, scheduled activities, and other other items. It’s time to bring some order to the chaos by using PowerShell PSake, an automation orchestration engine.
PSake is an orchestration engine implemented as a PowerShell module that provides you complete control over what executes when and under what circumstances. Despite the fact that PSake is a build automation tool with its main use in build scripts (which are often performed by a build server in release automation settings), it is sometimes disregarded in daily scripting circumstances. Let’s make a difference.
You’ll discover how PSake works in this video, as well as some amazing examples to put into practice right away!
This post will serve as a tutorial, with the expectation that you will follow along. If you want to follow along precisely as it is written, make sure you have the following items:
- Windows PowerShell 3+ is required. Windows PowerShell v5.1 is used in this lesson.
- PSake is a Github zip file. v4.9.0 is used in this lesson.
Configuring the PSake Module
If you’ve downloaded the PSake project from GitHub and installed it locally, you’ll need to go through a few steps to get it set up.
- Download the PSake zip file from GitHub and extract it.
- To ensure PowerShell is aware of the new module, copy the src folder from the unpacked ZIP file contents to a location under $env:PSModulePath.
- PSake should be the name of the src folder.
- To make sure it appears, run Get-Module PSake -ListAvailable. If you don’t get an error message, you’re good to go.
Understanding and Creating PowerShell Modules is a related topic.
Creating a PSake Script in PowerShell
To grasp PSake, you must first construct something. Let’s explore what we can achieve with a little PSake script.
- Make a single-task script called psakefile.ps1. A task should have a name and an action block at the very least. Although the name psakefile.ps1 is not required, it is the engine’s default name.
In its most basic form, a PSake job is quite similar to a PowerShell function: it’s a container for one or more commands that, when run together, accomplish a certain purpose. These instructions are placed in a script block, which is then supplied to the Action parameter. The benefits of a job over a function are many. As you read, you will become aware of these benefits.
Here’s an example of a psakefile.ps1 with a very straightforward task:
task HelloWorld -Action Write-Host ‘*** Hello World ***’ -ForegroundColor Yellow -Action Write-Host ‘*** Hello World ***’
2. Now that you’ve created the PSake file, you can use the Invoke-PSake command to run it from a PowerShell console, using the task name as an argument to the TaskList parameter.
PSake’s execution engine is called Invoke-PSake. This command executes the actions specified in the psakefile file. ps1. The TaskList option takes a task name or a list of comma-separated tasks. If you’re running many jobs at the same time, they’ll all run in the order you supplied them to TaskList, regardless of where they are in psakefile. ps1.
The HelloWorld job may be triggered in the following way:
-BuildFile C:Workpsakefile.ps1 -TaskList ‘HelloWorld’ Invoke-PSake
You may skip the BuildFile option and its value as long as the file is named psakefile.ps1 and the console is set to the location where it is stored.
- When you run Invoke-PSake, the console will display PSake output. When you run the tasks in psakefile.ps1, you’ll see something that looks like this.
Output from the Psake script
The following elements make up the output:
- The PSake version’s specifications.
- Right before it starts, the name of each construction task (PSake considers every task as a build task). In this case, HelloWorld is being run in cyan.
- Any output that the job had generated. In this case, Hello World is written in yellow.
- Message of success or failure. In this case, psake was successful… in green.
- Build Time Report is a time summary that includes the length of each job as well as the overall duration of the script.
Using PSake to install SQL
You didn’t do anything in the last part except run a fake PSake script. Now use everything you’ve learned and make a PSake script that installs SQL!
In this example, you’ll write a PSake script that does the following:
- Validates a machine’s free disk space.
- A SQL ZIP file is downloaded from a local repository.
- The ZIP file is extracted.
- Installs the program on the C or D drive (whichever of the two exists).
Next, we’ll look at how we can use PSake for the task.
Creating the Foundational Elements
PSake is all about task management. Each job should be given a distinct name and should preferably execute a single atomic action, similar to a PowerShell function. You may use this notion to explain the steps below and create a task for each.
You’re not really writing any code at this point; instead, you’re just laying out the tasks and generating the PSake file. In the tasks below, you’ll see Write-Host references; you’ll be adding to these later.
For each job, you should always utilize the Description option. When performing tasks and examining code, the Description parameter offers extra information about each task.
ValidateDiskSpace -Action Write-Host -Description ‘Validate Disk Free Space’ “‘n *** Checking disk free space ***’n” -ForegroundColor Yellow task DownloadSql -Description ‘Download SQL Setup’ -Action Write-Host “‘n *** Downloading SQL Setup from LAN ***’n” -ForegroundColor Yellow task DownloadSql -Description ‘Download SQL Setup’ -Action Write-Host “‘n *** ***’n” -ForegroundColor Yellow -Description ‘Extract SQL Setup’ -Action Write-Host “‘n” -ForegroundColor Yellow -Task ExtractSql -Description ‘Extract SQL Setup’ -Action Write-Host “‘n *** Extracting SQL Setup files ***n’ “-ForegroundColor Yellow -Description ‘Install SQL on C:’ task InstallSqlDriveC Write-Host -Action “*** in Please wait while SQL Server is installed on the C disk… ***n’ “-ForegroundColor Yellow -Description ‘Install SQL on D:’ job InstallSqlDriveD Write-Host -Action “n *** SQL Server is being installed on D disk… please wait… ***n’ “-Yellow for the foreground
Choosing a Task Execution Sequence
You now have a PSake file with a series of tasks in it. With the Invoke-PSake command, you can select to perform all of the tasks at once or merely a subset of them.
As in the basic example, you can use Invoke-PSake with the TaskList option to call certain (or all) tasks. Create an array and declare each task’s name as an item as shown below if you have more than one job to execute.
Each job will be executed in the order specified in the array by Invoke-PSake.
@taskList = $taskList () ‘ValidateDiskSpace’ += $taskList ‘DownloadSql’ += $taskList ‘ExtractSql’ += $taskList ‘InstallSqlDriveC’ += $taskList ‘InstallSqlDriveD’ += $taskList -TaskList Invoke-PSake $taskList
When you run the code above, you should get something like this:
Output from the Psake script
Incorporating a PreCondition
Maybe you only need to do something if a specific condition is satisfied. For example, before performing the task to activate the installer in this tutorial’s sample SQL installation script, you may want to check if the disk where the installer is stored is accessible.
The PreCondition argument may be used to run a piece of code that returns a boolean True or False that determines whether or not the job executes.
The variables $installSqlOn C Drive and $installSqlOn D Drive may be seen in the example below. These variables will have a True or False value depending on whether a C or D volume exists when Invoke-PSake runs this script.
You can see that each task includes a PreCondition scriptblock argument that carries the value of those variables on each task line. Depending on these settings, the InstallSqlDriveC or InstallSqlDriveD job will be executed at run time.
(Test-Path -Path ‘C:’) $installSqlOn C Drive = (Test-Path -Path ‘C:’) -and (-rather than (Test-Path -Path ‘D:’) (-not (Test-Path -Path ‘C:’)) $installSqlOn D Drive = (-not (Test-Path -Path ‘C:’) (Test-Path -Path ‘D:’) and (Test-Path -Path ‘D:’) -PreCondition $installSqlOn C Drive -Action Write-Host “‘n *** Installing SQL Server on C drive… please wait… ***’n” -ForegroundColor Yellow task InstallSqlDriveC -Description ‘Install SQL on C:’ -PreCondition $installSqlOn C Drive -Action Write-Host “‘n *** Installing SQL Server on C drive… please wait… *** -PreCondition $installSqlOn D Drive -Action Write-Host “‘n *** Installing SQL Server on D drive… please wait… ***’n” -ForegroundColor Yellow -Task InstallSqlDriveD -Description ‘Install SQL on D:’ -PreCondition $installSqlOn D Drive -Action Write-Host “‘n *** Installing SQL Server on D drive…
The parameters of the task
A task additionally supports the following parameters in addition to the Action and Description:
- PreCondition – A boolean value is returned by this script block. The relevant job is skipped if the answer is False. (An example of how to use it is provided above.)
- Validation step after PostCondition. A boolean value is returned by this script block. False indicates that validation failed, resulting in the script’s termination.
- PreAction – A script block that runs before the job is performed.
- PostAction — A script block that executes immediately after the job has finished successfully.
- Switch parameter ContinueOnError. Any mistakes that occur during the task runtime will not cause the whole script to fail if this option is utilized.
- Depends – The name of a task (or a collection of tasks) that must be completed before the present task may be completed. PSake will utilize this information to properly execute the task dependencies. If job A is reliant on task B, for example, the PSake engine will perform B first.
The dependence system seems to be a nice concept at first. It aids in the organization of duties. Using the Depends option, on the other hand, binds distinct jobs together, making it impossible to test separately afterwards. The usage of the Depends parameter may be eliminated entirely since the user can directly select the order in which tasks are executed and provide this order when calling the PSake file.
Let’s see next a usage example for some of these The parameters of the task:
PreAction and PostCondition are being added to the equation.
Perhaps you have an extra request for the installation, using the InstallSqlDriveD task from the previous example as a starting point.
It’s possible that you’ll need to keep track of when the installation begins and concludes. These timings must be recorded in two environment variables, SqlSetupStartDate and SqlSetupEndDate. Second, make sure the D:TempSqlFiles folder does not exist when the installation is complete.
Luckily, the PSake The parameters of the task PreAction, PostAction and PostCondition (respectively) meet exactly these new requirements. Below is an example of how it can be done:
InstallSqlDriveD is a task. ‘Install SQL on D:’ -Description -PreAction Write-Host ‘*** Setting the SQL install start time in the environment variable SqlSetupStartDate ***’ -Yellow -ForegroundColor Get-Date -Format ‘yyyy-MM-dd HH:mm:ss’ $date = Get-Date -Format ‘yyyy-MM-dd HH:mm:ss’ $date = Get-Date -For SetEnvironmentVariable(‘SqlSetupStartDate’,$date,’Machine’) in [Environment]::SetEnvironmentVariable(‘SqlSetupStartDate’,$date,’Machine’) in [Environment]::SetEnvironmentVariable( $installSqlOn D Drive -PreCondition -Action Write-Host ‘*** SQL Server installation on D disk… pls wait… ***’ -Yellow -ForegroundColor -PostAction Write-Host ‘*** Adding the SQL install finish time to the environment variable SqlSetupEndDate ***’ -Yellow -ForegroundColor $date = Get-Date -Format ‘yyyy-MM-dd HH:mm:ss’ SetEnvironmentVariable(‘SqlSetupEndDate’,$date,’Machine’) in [Environment]::SetEnvironmentVariable(‘SqlSetupEndDate’,$date,’Machine’) in [Environment]::SetEnvironmentVariable( # if the folder leaves, this will return False, forcing the whole script to terminate (-not (Test-Path -Path ‘D:TempSqlFiles’))
Pester Tests Using PSake Scripts
You can use a PSake file wherever you can run a PowerShell script. You may use PSake inside Pester tests if you’re writing infrastructure tests.
Writing Pester Tests in PowerShell is a related topic.
Perhaps you have a Pester test to ensure that the SQL setup ZIP file is there in a folder after you execute the DownloadSql job. In that instance, you create a basic Pester test, execute the DownloadSql job inside it, and check for the ZIP file when it completes.
Describe the ‘SQL install with PSake’ procedure. $setup = ‘C:DownloadsSqlSetup.zip’ It ‘Downloads Sql files’ if $setup (Test-Path -Path) Remove-Item -Path $setup # DownloadSql Invoke-PSake -BuildFile is the only task being tested here. -TaskList DownloadSql $setup | Should -Exist C:Workpsakefile.ps1
Using Tasks to Pass Parameters
You may wish to parametrize some of the jobs after you’ve started using PSake. Normally, you would supply multiple named arguments to PowerShell functions and scripts; however, PSake is different.
You may use a Properties block to send parameters to PSake files, which creates key/value pairs that PSake subsequently makes accessible within each job in the file.
Make that the Properties block is defined at the start of the PSake file. All PSake procedures are performed in a top-down manner.
For example, you may specify the dynamic SqlYear and SqlVersion variables as shown below to provide them to each job in the PSake file.
$SqlYear = ‘2017’ $SqlVersion = ‘14.0’ $SqlVersion = ‘14.0’ task -Name DownloadSql -Action Write-Host “SQL version to install: SQL $SqlYear (version $SqlVersion)” task -Name DownloadSql -Action Write-Host “SQL version to install: SQL $SqlYear (version $SqlVersion)”
You’ll get the following result if you use Invoke-PSake to invoke the PSake file. The values defined in the Properties block have been extended into the $SqlYear and $SqlVersion variables.
psake version 4.9.1 Copyright (c) 2010-2018 James Kovacs & Contributors Executing DownloadSql SQL version to install: SQL 2017 (version 14.0) psake succeeded executing C:WorkPSakefile.ps1 ————————————————– Build Time Report ————————————————– Name Duration —- ——– DownloadSql 00:00:00 —— ——– Total: 00:00:00
Using the Parameter Properties
PSake can assist you if you prefer to send parameters to a job through a conventional parameter. Although the Properties block must remain at the top of psakefile.ps1 as in the example above, PSake allows you to alter the values.
To do so, create a hashtable for each key/value combination you want to alter. The hashtable should then be sent to the Properties parameter. The values in the passed-in hashtable will be used instead of the ones supplied in the Properties block of the psakefile.ps1 script by the PSake engine.
Keep in mind that the Properties block and the Properties parameter have different syntax. Each line in the Properties block is a variable, so each item is a key, and is written without a leading $, while the Properties parameter is a hashtable, so each item is a key, and is written without a leading $. Another distinction is that the hashtable is prefixed by the @ symbol.
Below you can see an example of Using the Parameter Properties.
@ SqlYear = ‘2019’ SqlVersion = ‘15.0’ $myNewProperties = @ SqlYear = ‘2019’ SqlVersion = ‘15.0’ DownloadSql -Properties Invoke-PSake -TaskList $myNewProperties
Task Modularization in PSake: Files as Tasks
Your PSake file will almost certainly expand tremendously at some time, particularly if you need to coordinate huge automated operations. To guarantee that you can handle all of those responsibilities, you should concentrate on job modularization, or the division of work into smaller chunks.
Refactoring a PowerShell Script from Hell: How to Survive
You were given five objectives to complete in this tutorial:
Each of these tasks is specified in the pssakefile.ps1 script. If you expect to add many more activities in the future, you should divide them up into distinct files with each task within, such as ValidateDiskSpace.ps1, DownloadSql.ps1, InstallSqlDriveD.ps1, etc.
InstallSqlDriveD.ps1 will, for example, merely include the following code:
‘Install SQL on D:’ task InstallSqlDriveD -Description -Action Write-Host -PreCondition $installSqlOn D Drive “n *** SQL Server is being installed on D disk… please wait… ***`n” -Yellow for the foreground
Import the files into psakefile.ps1 using the Include function once the tasks have been moved out. After that, the content of psakefile.ps1 is reduced to the following code:
$installSqlOn C Drive = $true; $installSqlOn C Drive = $true; $installSql $false$installSqlOn D Drive$installSqlOn D Drive$installSqlOn D Drive$installS Be sure to include “Include “$PSScriptRootValidateDiskSpace.ps1” Include “$PSScriptRootDownloadSql.ps1″ Include ” $PSScriptRootExtractSql.ps1″ Include “$PSScriptRootInstallSqlOnD.ps1” in “$PSScriptRootInstallSqlOnC.ps1” in “$PSScriptRootInstallSqlOnC.ps1” in “$PSScriptRootInstallSqlOnC.ps1″ in”
When Invoke-PSake runs the psakefile.ps1 script, it doesn’t care whether the tasks are in the psake file or if they were imported via the Include method.
Steps to Follow
PSake is a robust script orchestrator that may be used for a variety of tasks, including software builds, continuous integration and delivery (CI/CD), package deployments, installer building, and more. Your creativity is the only limit. Getting accustomed to using PSake to create huge scripts requires you to think in terms of tasks (code building blocks). The notion of tasks is based on PowerShell syntax, and by utilizing tasks, you may expand your command-line skills.
PSake helps you write code that is more legible, manageable, and testable. You’ll find that splitting your stages into discrete tasks makes them simpler to write after some experience. In the medium and long run, the tiny amount of additional labor required pays off handsomely.
What role do you envisage PSake playing in your company’s projects?
- install module psake
- powershell build script