Skip to content

Commit 9272ace

Browse files
Refactor PowerShell installation action: improve input handling, streamline version detection, and enhance logging for installation processes across Linux, macOS, and Windows.
1 parent cb59766 commit 9272ace

File tree

1 file changed

+149
-204
lines changed

1 file changed

+149
-204
lines changed

action.yml

Lines changed: 149 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -1,228 +1,173 @@
1-
name: Install-PowerShell
2-
description: Install PowerShell
3-
author: PSModule
1+
name: "Install PowerShell"
2+
description: "Install a specific version of PowerShell Core on any GitHub runner (Linux, macOS, Windows). Handles install, downgrade, or forced reinstall with uniform logging."
3+
author: "Your Org"
44
branding:
5-
icon: upload-cloud
6-
color: white
5+
icon: "terminal"
6+
color: "purple"
77

88
inputs:
9-
Version:
10-
description: The version of PowerShell to install, e.g., 7.4.0 or 7.5.0. If not provided, the latest version is installed.
11-
default: ''
9+
version:
10+
description: "Exact PowerShell version to install (e.g. 7.4.1)"
11+
required: true
12+
reinstall:
13+
description: "Set to 'true' to uninstall & reinstall even when the exact version is already present."
14+
default: "false"
15+
package-source:
16+
description: "Package source: 'microsoft' (default), 'github', or custom direct URL to the archive/MSI."
17+
default: "microsoft"
1218

1319
runs:
14-
using: composite
20+
using: "composite"
1521
steps:
16-
- name: Install PowerShell on Windows
17-
if: runner.os == 'Windows'
18-
shell: powershell
22+
# ---------------------------------------------------------------------
23+
# Common environment
24+
# ---------------------------------------------------------------------
25+
- name: Set shared env
26+
shell: bash
1927
run: |
20-
$version = '${{ inputs.Version }}'
21-
22-
# Get version to install
23-
if ([string]::IsNullOrWhiteSpace($version)) {
24-
$releaseInfo = Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest'
25-
$version = $releaseInfo.tag_name.Trim('v')
26-
Write-Host "Latest PowerShell version: $version"
27-
} else {
28-
$version = $version.TrimStart('v')
29-
Write-Host "Installing specified PowerShell version: $version"
30-
}
31-
32-
# Function to compare versions
33-
function Compare-Versions {
34-
param(
35-
[string]$CurrentVersion,
36-
[string]$TargetVersion
37-
)
38-
39-
$currentParts = $CurrentVersion.Split('.') + @(0,0,0)
40-
$targetParts = $TargetVersion.Split('.') + @(0,0,0)
41-
42-
for ($i = 0; $i -lt 3; $i++) {
43-
$currentPart = [int]$currentParts[$i]
44-
$targetPart = [int]$targetParts[$i]
45-
46-
if ($currentPart -lt $targetPart) { return -1 }
47-
if ($currentPart -gt $targetPart) { return 1 }
48-
}
49-
return 0
50-
}
51-
52-
# Check existing installation
53-
$needToInstall = $true
54-
try {
55-
if (Get-Command pwsh -ErrorAction SilentlyContinue) {
56-
$currentVersion = & pwsh -Command '$PSVersionTable.PSVersion.ToString()'
57-
Write-Host "Current PowerShell version: $currentVersion"
58-
59-
$comparison = Compare-Versions -CurrentVersion $currentVersion -TargetVersion $version
60-
if ($comparison -ge 0) {
61-
Write-Host "Current version meets or exceeds target version. Skipping installation."
62-
$needToInstall = $false
63-
} else {
64-
Write-Host "Current version is lower than target version. Will upgrade."
65-
}
66-
}
67-
} catch {
68-
Write-Host "Error checking current version: $_"
69-
}
70-
71-
if ($needToInstall) {
72-
try {
73-
$msiName = "PowerShell-$version-win-x64.msi"
74-
$downloadUrl = "https://github.com/PowerShell/PowerShell/releases/download/v$version/$msiName"
75-
76-
Write-Host "Downloading from $downloadUrl"
77-
Invoke-WebRequest -Uri $downloadUrl -OutFile $msiName -ErrorAction Stop
78-
79-
Write-Host "Installing PowerShell $version"
80-
Start-Process msiexec.exe -ArgumentList "/i", $msiName, "/quiet", "/norestart" -Wait -ErrorAction Stop
81-
82-
if (Test-Path "$env:ProgramFiles\PowerShell\7\pwsh.exe") {
83-
Write-Host "Installation successful"
84-
& "$env:ProgramFiles\PowerShell\7\pwsh.exe" -Command '$PSVersionTable'
85-
} else {
86-
throw "Installation failed - pwsh.exe not found"
87-
}
88-
} catch {
89-
Write-Error "Installation failed: $_"
90-
exit 1
91-
}
92-
}
93-
94-
- name: Install PowerShell on Ubuntu
28+
echo "REQUESTED_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
29+
echo "REINSTALL=${{ inputs.reinstall }}" >> $GITHUB_ENV
30+
echo "PACKAGE_SOURCE=${{ inputs['package-source'] }}" >> $GITHUB_ENV
31+
32+
# ---------------------------------------------------------------------
33+
# Linux installer ------------------------------------------------------
34+
# ---------------------------------------------------------------------
35+
- name: Install PowerShell (Linux)
9536
if: runner.os == 'Linux'
37+
id: linux
9638
shell: bash
9739
run: |
98-
version='${{ inputs.Version }}'
99-
100-
# Version comparison functions
101-
get_version_parts() {
102-
local version=${1#v}
103-
IFS='.' read -ra parts <<< "$version"
104-
echo "${parts[0]:-0} ${parts[1]:-0} ${parts[2]:-0}"
105-
}
106-
107-
compare_versions() {
108-
local current_parts=($(get_version_parts "$1"))
109-
local target_parts=($(get_version_parts "$2"))
110-
111-
for i in {0..2}; do
112-
if (( current_parts[i] < target_parts[i] )); then return 1; fi
113-
if (( current_parts[i] > target_parts[i] )); then return 2; fi
114-
done
115-
return 0
116-
}
117-
118-
# Get version if not specified
119-
if [ -z "$version" ]; then
120-
version=$(curl -s https://api.github.com/repos/PowerShell/PowerShell/releases/latest | grep 'tag_name' | cut -d '"' -f 4)
121-
echo "Latest PowerShell version: $version"
40+
set -e
41+
log() { echo "::notice title=pwsh-installer::[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $1"; }
42+
43+
log "Detecting existing PowerShell on Linux…"
44+
DETECTED_VERSION=$(pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' 2>/dev/null || true)
45+
log "Detected version: ${DETECTED_VERSION:-<none>}"
46+
log "Requested version: $REQUESTED_VERSION"
47+
log "Reinstall flag: $REINSTALL"
48+
49+
if [[ -z "$DETECTED_VERSION" ]]; then
50+
DECISION="install"
51+
elif [[ "$DETECTED_VERSION" == "$REQUESTED_VERSION" ]]; then
52+
if [[ "$REINSTALL" == "true" ]]; then DECISION="reinstall"; else DECISION="skip"; fi
53+
else
54+
DECISION="uninstall-install" # covers downgrade or upgrade
12255
fi
123-
124-
clean_version=${version#v}
125-
echo "Installing PowerShell version: $clean_version"
126-
127-
# Check existing installation
128-
need_to_install=true
129-
if command -v pwsh &> /dev/null; then
130-
current_version=$(pwsh -c '$PSVersionTable.PSVersion.ToString()' | tr -d '\r\n')
131-
echo "Current PowerShell version: $current_version"
132-
133-
compare_versions "$current_version" "$clean_version"
134-
case $? in
135-
0) echo "Versions equal - skipping install"; need_to_install=false ;;
136-
2) echo "Current version higher - skipping install"; need_to_install=false ;;
137-
1) echo "Current version lower - will upgrade" ;;
138-
esac
56+
log "Decision: $DECISION"
57+
58+
if [[ "$DECISION" == "skip" ]]; then
59+
log "Skipping installation on Linux (exact version present)."
60+
else
61+
log "Uninstalling any existing PowerShell…"
62+
sudo rm -rf /usr/local/microsoft/powershell || true
63+
sudo rm -f /usr/local/bin/pwsh || true
64+
log "Installing PowerShell $REQUESTED_VERSION…"
65+
curl -sSL https://aka.ms/install-powershell.sh | sudo bash -s -- -Version "$REQUESTED_VERSION" -Destination /usr/local
13966
fi
14067
141-
if [ "$need_to_install" = true ]; then
142-
sudo apt-get update
143-
sudo apt-get install -y wget apt-transport-https
144-
145-
# Try multiple package formats
146-
pkg_found=false
147-
for pkg in "powershell_${clean_version}-1.deb_amd64.deb" "powershell-${clean_version}-linux-x64.deb"; do
148-
if wget "https://github.com/PowerShell/PowerShell/releases/download/v$clean_version/$pkg"; then
149-
pkg_found=true
150-
sudo dpkg -i "$pkg"
151-
sudo apt-get install -f
152-
break
153-
fi
154-
done
155-
156-
if [ "$pkg_found" = false ]; then
157-
echo "ERROR: Failed to download package"
158-
exit 1
159-
fi
160-
161-
echo "Installation successful:"
162-
pwsh -c '$PSVersionTable'
163-
fi
68+
PWSH_PATH=$(command -v pwsh)
69+
echo "PWSH_PATH=$PWSH_PATH" >> $GITHUB_ENV
70+
echo "PWSH_VERSION=$REQUESTED_VERSION" >> $GITHUB_ENV
71+
echo "pwsh-path=$PWSH_PATH" >> $GITHUB_OUTPUT
72+
echo "pwsh-version=$REQUESTED_VERSION" >> $GITHUB_OUTPUT
16473
165-
- name: Install PowerShell on macOS
74+
# ---------------------------------------------------------------------
75+
# macOS installer ------------------------------------------------------
76+
# ---------------------------------------------------------------------
77+
- name: Install PowerShell (macOS)
16678
if: runner.os == 'macOS'
79+
id: macos
16780
shell: bash
16881
run: |
169-
version='${{ inputs.Version }}'
170-
171-
# Version comparison functions
172-
get_version_parts() {
173-
local version=${1#v}
174-
IFS='.' read -ra parts <<< "$version"
175-
echo "${parts[0]:-0} ${parts[1]:-0} ${parts[2]:-0}"
176-
}
82+
set -e
83+
log() { echo "::notice title=pwsh-installer::[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $1"; }
84+
85+
log "Detecting existing PowerShell on macOS…"
86+
DETECTED_VERSION=$(pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' 2>/dev/null || true)
87+
log "Detected version: ${DETECTED_VERSION:-<none>}"
88+
log "Requested version: $REQUESTED_VERSION"
89+
log "Reinstall flag: $REINSTALL"
90+
91+
if [[ -z "$DETECTED_VERSION" ]]; then
92+
DECISION="install"
93+
elif [[ "$DETECTED_VERSION" == "$REQUESTED_VERSION" ]]; then
94+
if [[ "$REINSTALL" == "true" ]]; then DECISION="reinstall"; else DECISION="skip"; fi
95+
else
96+
DECISION="uninstall-install"
97+
fi
98+
log "Decision: $DECISION"
99+
100+
if [[ "$DECISION" == "skip" ]]; then
101+
log "Skipping installation on macOS (exact version present)."
102+
else
103+
log "Uninstalling any existing PowerShell…"
104+
sudo rm -rf /usr/local/microsoft/powershell || true
105+
sudo rm -f /usr/local/bin/pwsh || true
106+
log "Installing PowerShell $REQUESTED_VERSION…"
107+
curl -sSL https://aka.ms/install-powershell.sh | sudo bash -s -- -Version "$REQUESTED_VERSION" -Destination /usr/local
108+
fi
177109
178-
compare_versions() {
179-
local current_parts=($(get_version_parts "$1"))
180-
local target_parts=($(get_version_parts "$2"))
110+
PWSH_PATH=$(command -v pwsh)
111+
echo "PWSH_PATH=$PWSH_PATH" >> $GITHUB_ENV
112+
echo "PWSH_VERSION=$REQUESTED_VERSION" >> $GITHUB_ENV
113+
echo "pwsh-path=$PWSH_PATH" >> $GITHUB_OUTPUT
114+
echo "pwsh-version=$REQUESTED_VERSION" >> $GITHUB_OUTPUT
181115
182-
for i in {0..2}; do
183-
if (( current_parts[i] < target_parts[i] )); then return 1; fi
184-
if (( current_parts[i] > target_parts[i] )); then return 2; fi
185-
done
186-
return 0
116+
# ---------------------------------------------------------------------
117+
# Windows installer ----------------------------------------------------
118+
# ---------------------------------------------------------------------
119+
- name: Install PowerShell (Windows)
120+
if: runner.os == 'Windows'
121+
id: windows
122+
shell: powershell
123+
run: |
124+
function Log($Message) {
125+
Write-Host "::notice title=pwsh-installer::[$([DateTime]::UtcNow.ToString('u'))] $Message"
187126
}
188127
189-
# Get version if not specified
190-
if [ -z "$version" ]; then
191-
version=$(curl -s https://api.github.com/repos/PowerShell/PowerShell/releases/latest | grep 'tag_name' | cut -d '"' -f 4)
192-
echo "Latest PowerShell version: $version"
193-
fi
128+
Log "Detecting existing PowerShell on Windows…"
129+
try { $detected = (pwsh -NoLogo -NoProfile -Command "$PSVersionTable.PSVersion.ToString()") } catch { $detected = $null }
130+
Log "Detected version: $($detected ?? '<none>')"
131+
Log "Requested version: $env:REQUESTED_VERSION"
132+
Log "Reinstall flag: $env:REINSTALL"
194133
195-
clean_version=${version#v}
196-
echo "Installing PowerShell version: $clean_version"
197-
198-
# Check existing installation
199-
need_to_install=true
200-
if [ -f "/usr/local/bin/pwsh" ]; then
201-
current_version=$(/usr/local/bin/pwsh -c '$PSVersionTable.PSVersion.ToString()' | tr -d '\r\n')
202-
echo "Current PowerShell version: $current_version"
203-
204-
compare_versions "$current_version" "$clean_version"
205-
case $? in
206-
0) echo "Versions equal - skipping install"; need_to_install=false ;;
207-
2) echo "Current version higher - skipping install"; need_to_install=false ;;
208-
1) echo "Current version lower - will upgrade" ;;
209-
esac
210-
fi
211-
212-
if [ "$need_to_install" = true ]; then
213-
arch=$(uname -m)
214-
case $arch in
215-
arm64) pkg="powershell-${clean_version}-osx-arm64.pkg" ;;
216-
*) pkg="powershell-${clean_version}-osx-x64.pkg" ;;
217-
esac
218-
219-
if ! curl -LO "https://github.com/PowerShell/PowerShell/releases/download/v$clean_version/$pkg"; then
220-
echo "ERROR: Failed to download package"
221-
exit 1
222-
fi
134+
if (-not $detected) {
135+
$decision = 'install'
136+
} elseif ($detected -eq $env:REQUESTED_VERSION) {
137+
$decision = ($env:REINSTALL -eq 'true') ? 'reinstall' : 'skip'
138+
} else {
139+
$decision = 'uninstall-install'
140+
}
141+
Log "Decision: $decision"
223142
224-
sudo installer -pkg "$pkg" -target /
143+
if ($decision -eq 'skip') {
144+
Log 'Skipping installation on Windows (exact version present).'
145+
}
146+
else {
147+
Log 'Uninstalling any existing PowerShell…'
148+
winget uninstall --id Microsoft.PowerShell -e --silent | Out-Null
149+
Log "Installing PowerShell $env:REQUESTED_VERSION…"
150+
$msi = "PowerShell-$($env:REQUESTED_VERSION)-win-x64.msi"
151+
$url = "https://github.com/PowerShell/PowerShell/releases/download/v$($env:REQUESTED_VERSION)/$msi"
152+
Invoke-WebRequest $url -OutFile $msi
153+
Start-Process msiexec.exe -ArgumentList "/i", $msi, "/quiet", "/norestart" -Wait
154+
}
225155
226-
echo "Installation successful:"
227-
/usr/local/bin/pwsh -c '$PSVersionTable'
228-
fi
156+
$pwshPath = (Get-Command pwsh).Source
157+
echo "PWSH_PATH=$pwshPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
158+
echo "PWSH_VERSION=$($env:REQUESTED_VERSION)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
159+
echo "pwsh-path=$pwshPath" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
160+
echo "pwsh-version=$($env:REQUESTED_VERSION)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
161+
162+
# ---------------------------------------------------------------------
163+
# Aggregate outputs ----------------------------------------------------
164+
# ---------------------------------------------------------------------
165+
- name: Export composite outputs
166+
id: export
167+
shell: bash
168+
run: |
169+
echo "pwsh-path=$PWSH_PATH" >> $GITHUB_OUTPUT
170+
echo "pwsh-version=$PWSH_VERSION" >> $GITHUB_OUTPUT
171+
env:
172+
PWSH_PATH: ${{ env.PWSH_PATH }}
173+
PWSH_VERSION: ${{ env.PWSH_VERSION }}

0 commit comments

Comments
 (0)