A GitHub Actions workflow for PowerShell scripts
Using GitHub Actions to automate the publication of PowerShellGet script packages to multiple release channels.
Published in Articles on by Michiel van Oosterhout ~ 4 min read
This article demonstrates an implementation of the simple Git-based workflow described in the previous article. The workflow, implemented using GitHub Actions, will publish a PowerShell script package to either a prerelease or a release channel.

Git repository layout
The code for the script package will be hosted in a dedicated GitHub repository. The name of this dedicated GitHub repository should be the same as the name of the script package. The script file and its unit tests file should be added to the root of the repository. GitHub workflows are YAML files and must be saved in the .github/workflows
directory of a GitHub repository.
Assuming a GitHub repository named Example
, the repository layout should be as follows:
.github/
workflows/
publish-powershell-script.yaml
Example.ps1
Example.Tests.ps1
Publish-PowerShellScript.ps1
(The Publish-PowerShellScript.ps1
file is described in detail in the next article.)
GitHub workflow
Triggers
Triggers are events that cause a workflow to run. We can configure a workflow to run when a specific activity happens, at a scheduled time, or when an event outside of GitHub occurs.
on:
push:
branches:
- main
tags:
- v[0-9]+.[0-9]+.[0-9]+
pull_request: {}
Our workflow should be triggered when commits are pushed to the main branch, when a pull request is (re)opened or its head branch is updated, and when a version tag (e.g. v1.2.3
) is created.

push
event
Defaults
The defaults
key can be used to set default settings that will apply to all steps in the workflow. We use it to set the shell to PowerShell:
defaults:
run:
shell: pwsh
Release channels
The workflow consists of two jobs. The first job selects the GitHub environment that the script package will be published to in the second job. Environment in this context should be understood to mean release channel as explained in the previous article.
jobs:
prepare:
name: Prepare
runs-on: ubuntu-latest
outputs:
environment: ${{ steps.select.outputs.environment }}
steps:
- name: Select environment
id: select
run: 'Write-Host ("::set-output name=environment::" + ("${{ github.ref_type }}" -eq "tag" ? "PowerShell Gallery" : "MyGet"))'
We use a workflow command to set an output parameter named environment
depending on the event that triggered the workflow. The environment will be PowerShell Gallery when the job is triggered by the creation of a tag, otherwise it will be MyGet. These environments should be added to the GitHub repository. During development new versions of the script package, including prerelease versions, become available on MyGet, and only after a particular version is tagged does it become generally available available on the PowerShell Gallery.


Checkout
The second job starts only after the first job completes (due to the needs
property). The environment property is set using the first job's environment
output. The first step checks out the code.
publish:
name: Publish
runs-on: ubuntu-latest
needs: prepare
environment: ${{ needs.prepare.outputs.environment }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
The fetch-depth
must be set to at least 2, in order for the script to be able to compare a commit on the main branch to its parent.
Publish
The next step does the actual publishing by dot sourcing a script and executing the publish function defined by it.
- name: Publish
run: |
. ./Publish-PowerShellScript.ps1
Publish-PowerShellScript `
-Ref ("${{ github.event_name }}" -eq "pull_request" ? "${{ github.head_ref }}" : "${{ github.ref_name }}") `
-Build ${{ github.run_number }} `
-NuGetApiKey "${{ secrets.NUGET_API_KEY }}" `
-NuGetUrl "${{ secrets.NUGET_URL }}" `
-InformationAction Continue
The value of the -Ref
parameter is either the name of the pull request branch (github.head_ref
), or the name of the main branch or the tag (github.ref_name
). This will be used by the script to determine the correct versioning strategy.
The value of the -Build
parameter is an incrementing number for this particular workflow (github.run_number
), and will be used by the script to generate a unique prerelease label for each iteration of a pull request.
Notice that the values for both -NuGet
parameters are provided by GitHub secrets. These secrets should be set in each GitHub environment. This way the script does not need to know about any specific release channel.
Summary
Triggers in GitHub Actions can be combined with GitHub environments to automate the publishing of PowerShell Get script packages to multiple release channels. The next article will describe the script in detail.
Links
Updates
- Added mention of GitHub Packages and PowerShellGet 3.0.
- Added an explanation of the
fetch-depth: 2
requirement