Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 33 additions & 5 deletions .github/workflows/Action-Test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
version: ['latest', '7.4.7', '7.5.0']
version: ['latest', 'prerelease', '7.4.7', '7.5.0', '7.6.0-preview.6']
runs-on: ${{ matrix.os }}
name: '${{ matrix.os }} - [${{ matrix.version }}]'
steps:
Expand All @@ -34,7 +34,8 @@ jobs:
- name: Action-Test
uses: ./
with:
Version: ${{ matrix.version }}
Version: ${{ matrix.version == 'prerelease' && 'latest' || matrix.version }}
Prerelease: ${{ matrix.version == 'prerelease' && 'true' || 'false' }}

- name: Verify installed version
shell: pwsh
Expand All @@ -44,8 +45,19 @@ jobs:
# Requested version that came from the matrix
$requested = '${{ matrix.version }}'

# When 'prerelease' → resolve to latest prerelease
if ($requested.Trim().ToLower() -eq 'prerelease') {
$releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases' `
-Headers @{
'Accept' = 'application/vnd.github+json'
'Authorization' = "Bearer $($env:GITHUB_TOKEN)"
'X-GitHub-Api-Version' = '2022-11-28'
}
$requested = ($releases | Where-Object { $_.prerelease -eq $true } | Select-Object -First 1).tag_name.TrimStart('v')
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
Write-Host "Resolved 'prerelease' → $requested"
Comment thread
MariusStorhaug marked this conversation as resolved.
}
# When empty / 'null' / 'latest' → resolve to latest stable release
if ([string]::IsNullOrWhiteSpace($requested) -or
elseif ([string]::IsNullOrWhiteSpace($requested) -or
$requested.Trim().ToLower() -in @('latest','null')) {

$requested = (
Expand All @@ -59,8 +71,24 @@ jobs:
Write-Host "Resolved 'latest' → $requested"
}

# Actual version installed by the action
$installed = ($PSVersionTable.PSVersion).ToString()
# On Windows, always verify by launching pwsh from the known install directory.
# This avoids relying on PATH resolution, which may still point to the pre-installed
# version if the runner's environment hasn't refreshed after the MSI install.
if ($IsWindows) {
$isPrerelease = $requested -match '-'
$majorVersion = ($requested -split '[\.-]')[0]
$installDir = if ($isPrerelease) { "$majorVersion-preview" } else { $majorVersion }
$pwshPath = "$env:ProgramFiles\PowerShell\$installDir\pwsh.exe"
Write-Host "Windows: verifying via subprocess at $pwshPath"
if (Test-Path $pwshPath) {
$installed = (& $pwshPath -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()')
} else {
Write-Host "Warning: Expected pwsh not found at $pwshPath, falling back to `$PSVersionTable"
$installed = ($PSVersionTable.PSVersion).ToString()
}
} else {
$installed = ($PSVersionTable.PSVersion).ToString()
}
Write-Host "Installed PowerShell version: $installed"
Write-Host "Expected PowerShell version: $requested"

Comment thread
MariusStorhaug marked this conversation as resolved.
Expand Down
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

A cross‑platform GitHub Action that installs a specific **PowerShell Core** version—or the latest stable release—on any GitHub‑hosted runner
(Linux, macOS, or Windows). The action automatically skips installation when the requested version is already present.
Prerelease versions (e.g. `7.6.0-preview.6`, `7.5.0-rc.1`) are also supported.

## Usage

Expand All @@ -25,11 +26,30 @@ jobs:
Write-Host "Using PowerShell $($PSVersionTable.PSVersion)"
```

### Installing a prerelease version

```yaml
- name: Install PowerShell Preview
uses: PSModule/install-powershell@v1
with:
Version: 7.6.0-preview.6
```

### Installing the latest prerelease

```yaml
- name: Install latest PowerShell Preview
uses: PSModule/install-powershell@v1
with:
Prerelease: true
```

## Inputs

| Input | Required | Default | Description |
| ----- | -------- | ------- | ----------- |
| `Version` | `false` | `latest` | Desired PowerShell Core version (e.g. `7.4.1`). Use `latest` to install the newest stable release. |
| `Version` | `false` | `latest` | Desired PowerShell Core version (e.g. `7.4.1`, `7.6.0-preview.6`). Use `latest` to install the newest stable release (or newest prerelease when `Prerelease` is `true`). |
| `Prerelease` | `false` | `false` | Install a prerelease version. When `true` and `Version` is `latest`, resolves to the latest prerelease. Similar to `-Prerelease` on `Install-PSResource`. |

## Secrets

Expand All @@ -43,7 +63,8 @@ This action does **not** generate any outputs.

* **Version resolution**
If `Version` is set to `latest` (case‑insensitive), the action queries the GitHub API for the newest stable release tag in the
`PowerShell/PowerShell` repository and substitutes that version.
`PowerShell/PowerShell` repository and substitutes that version. When `Prerelease` is `true`, it queries for the latest prerelease
instead. Explicit prerelease version strings (e.g. `7.6.0-preview.6`) are passed through directly.

* **Skip logic**
Before installing, the action checks the current runner to see whether the requested version is already available
Expand Down
127 changes: 96 additions & 31 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ branding:
inputs:
Version:
description: |
PowerShell version to install (e.g. `7.4.1`).
PowerShell version to install (e.g. `7.4.1` or `7.6.0-preview.6`).
Defaults to install the latest stable release.
Prerelease versions are supported (e.g. `7.6.0-preview.6`, `7.5.0-rc.1`).
required: false
default: 'latest'
Prerelease:
description: |
Install a prerelease version of PowerShell.
When `true` and `Version` is `latest`, installs the latest prerelease.
Similar to the `-Prerelease` switch on `Install-PSResource`.
required: false
default: 'false'

runs:
using: composite
Expand All @@ -25,24 +33,38 @@ runs:
working-directory: ${{ github.action_path }}
env:
REQUESTED_VERSION: ${{ inputs.Version }}
PRERELEASE: ${{ inputs.Prerelease }}
GITHUB_TOKEN: ${{ github.token }}
run: |
# Install-PowerShell
set -e
echo "Requested version: [$REQUESTED_VERSION]"
echo "Prerelease: [$PRERELEASE]"

# Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
case "${REQUESTED_VERSION:-}" in
[Ll][Aa][Tt][Ee][Ss][Tt])
REQUESTED_VERSION=$(
curl -s -f \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/PowerShell/PowerShell/releases/latest |
jq -r '.tag_name' | sed 's/^v//'
)
echo "Latest stable PowerShell release detected: $REQUESTED_VERSION"
if [[ "$PRERELEASE" == "true" ]]; then
REQUESTED_VERSION=$(
curl -s -f \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/PowerShell/PowerShell/releases |
jq -r '[.[] | select(.prerelease == true)] | .[0].tag_name' | sed 's/^v//'
)
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
Comment thread
MariusStorhaug marked this conversation as resolved.
echo "Latest prerelease PowerShell version detected: $REQUESTED_VERSION"
else
REQUESTED_VERSION=$(
curl -s -f \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/PowerShell/PowerShell/releases/latest |
jq -r '.tag_name' | sed 's/^v//'
)
echo "Latest stable PowerShell release detected: $REQUESTED_VERSION"
Comment thread
MariusStorhaug marked this conversation as resolved.
fi
Comment thread
MariusStorhaug marked this conversation as resolved.
;;
"")
echo "Error: Version input is required (or use 'latest')"
Expand Down Expand Up @@ -99,24 +121,38 @@ runs:
working-directory: ${{ github.action_path }}
env:
REQUESTED_VERSION: ${{ inputs.Version }}
PRERELEASE: ${{ inputs.Prerelease }}
GITHUB_TOKEN: ${{ github.token }}
run: |
# Install-PowerShell
set -e
echo "Requested version: [$REQUESTED_VERSION]"
echo "Prerelease: [$PRERELEASE]"

# Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
case "${REQUESTED_VERSION:-}" in
[Ll][Aa][Tt][Ee][Ss][Tt])
REQUESTED_VERSION=$(
curl -s -f \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/PowerShell/PowerShell/releases/latest |
jq -r '.tag_name' | sed 's/^v//'
)
echo "Latest stable PowerShell release detected: $REQUESTED_VERSION"
if [[ "$PRERELEASE" == "true" ]]; then
REQUESTED_VERSION=$(
curl -s -f \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/PowerShell/PowerShell/releases |
jq -r '[.[] | select(.prerelease == true)] | .[0].tag_name' | sed 's/^v//'
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
)
Comment thread
MariusStorhaug marked this conversation as resolved.
Comment thread
MariusStorhaug marked this conversation as resolved.
echo "Latest prerelease PowerShell version detected: $REQUESTED_VERSION"
else
REQUESTED_VERSION=$(
curl -s -f \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/PowerShell/PowerShell/releases/latest |
jq -r '.tag_name' | sed 's/^v//'
)
Comment thread
MariusStorhaug marked this conversation as resolved.
echo "Latest stable PowerShell release detected: $REQUESTED_VERSION"
Comment thread
MariusStorhaug marked this conversation as resolved.
fi
;;
"")
echo "Error: Version input is required (or use 'latest')"
Expand Down Expand Up @@ -160,23 +196,29 @@ runs:
working-directory: ${{ github.action_path }}
env:
REQUESTED_VERSION: ${{ inputs.Version }}
PRERELEASE: ${{ inputs.Prerelease }}
GITHUB_TOKEN: ${{ github.token }}
run: |
# Install-PowerShell
Write-Host "Requested version: [$env:REQUESTED_VERSION]"
Write-Host "Prerelease: [$env:PRERELEASE]"

# Resolve 'latest' → concrete version
$req = $env:REQUESTED_VERSION
if ($req -and $req.Trim().ToLower() -eq 'latest') {
$latest = (
Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest' `
-Headers @{
'Accept' = 'application/vnd.github+json'
'Authorization' = "Bearer $($env:GITHUB_TOKEN)"
$headers = @{
'Accept' = 'application/vnd.github+json'
'Authorization' = "Bearer $($env:GITHUB_TOKEN)"
'X-GitHub-Api-Version' = '2022-11-28'
}
).tag_name.TrimStart('v')
Write-Host "Latest stable PowerShell release detected: $latest"
}
if ($env:PRERELEASE -eq 'true') {
$releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases' -Headers $headers
$latest = ($releases | Where-Object { $_.prerelease -eq $true } | Select-Object -First 1).tag_name.TrimStart('v')
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
Write-Host "Latest prerelease PowerShell version detected: $latest"
Comment thread
MariusStorhaug marked this conversation as resolved.
} else {
$latest = (Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest' -Headers $headers).tag_name.TrimStart('v')
Write-Host "Latest stable PowerShell release detected: $latest"
Comment thread
MariusStorhaug marked this conversation as resolved.
Comment thread
MariusStorhaug marked this conversation as resolved.
}
$env:REQUESTED_VERSION = $latest
} elseif ([string]::IsNullOrWhiteSpace($req)) {
Write-Host "Error: Version input is required (or use 'latest')"
Expand All @@ -198,14 +240,20 @@ runs:
}

# Downgrade detection
# Strip prerelease suffix for [version] comparison (e.g. '7.6.0-preview.6' → '7.6.0')
$isDowngrade = $false
if ($detected -and $detected -ne $env:REQUESTED_VERSION) {
try {
$detectedVersion = [version]$detected
$requestedVersion = [version]$env:REQUESTED_VERSION
$detectedBase = ($detected -split '-')[0]
$requestedBase = ($env:REQUESTED_VERSION -split '-')[0]
$detectedVersion = [version]$detectedBase
$requestedVersion = [version]$requestedBase
if ($detectedVersion -gt $requestedVersion) {
Write-Host "Downgrade detected: $detected → $($env:REQUESTED_VERSION)"
$isDowngrade = $true
} elseif ($detectedVersion -eq $requestedVersion -and $detected -ne $env:REQUESTED_VERSION) {
# Same base version but different prerelease label, treat as a reinstall
Write-Host "Version change detected (same base, different label): $detected → $($env:REQUESTED_VERSION)"
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
} else {
Write-Host "Upgrade detected: $detected → $($env:REQUESTED_VERSION)"
}
Expand All @@ -224,13 +272,14 @@ runs:
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)

$isDetectedPreview = $detected -match '-preview|\-rc'
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
$pwshEntries = Get-ItemProperty -Path $regPaths -ErrorAction SilentlyContinue |
Where-Object {
$_.Publisher -eq 'Microsoft Corporation' -and
$_.DisplayName -like 'PowerShell 7*' -and
$_.DisplayName -notlike '*Preview*' -and
$(if ($isDetectedPreview) { $_.DisplayName -like '*Preview*' } else { $_.DisplayName -notlike '*Preview*' }) -and
$_.DisplayVersion -and
$_.DisplayVersion.StartsWith($detected)
$_.DisplayVersion.StartsWith(($detected -split '-')[0])
}
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated

$targetEntry = $pwshEntries | Select-Object -First 1
Expand Down Expand Up @@ -283,3 +332,19 @@ runs:
}

Write-Host "Installation complete. PowerShell [$($env:REQUESTED_VERSION)] is now available."

# Add the install directory to GITHUB_PATH so subsequent `shell: pwsh` steps
# resolve to the version we just installed — even for preview builds whose
# install directory (7-preview) is not on the runner's default PATH.
$isPrerelease = $env:REQUESTED_VERSION -match '-'
$installDir = if ($isPrerelease) {
"$env:ProgramFiles\PowerShell\7-preview"
} else {
"$env:ProgramFiles\PowerShell\7"
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated
}
if (Test-Path $installDir) {
Write-Host "Adding install directory to GITHUB_PATH: $installDir"
Add-Content -Path $env:GITHUB_PATH -Value $installDir
} else {
Write-Host "Warning: Expected install directory not found: $installDir"
}
Comment thread
MariusStorhaug marked this conversation as resolved.
Loading