From 222c5d34237ba98afb6f10085c2c85a4b3236b96 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 04:53:02 +0530 Subject: [PATCH 01/10] Allow "Preview" as an input --- action.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index b79cc2d..cf10f06 100644 --- a/action.yml +++ b/action.yml @@ -11,10 +11,17 @@ branding: inputs: Version: description: | - PowerShell version to install (e.g. `7.4.1`). + PowerShell version to install (e.g. `7.4.1` or `7.5.0-preview.1`). Defaults to install the latest stable release. + Use 'latest' for latest stable, or latest preview if Preview is true. required: false default: 'latest' + Preview: + description: | + Install PowerShell preview build instead of stable. + When true and Version is 'latest', installs the latest preview release. + required: false + default: 'false' runs: using: composite From ef2858cebf5c7676fce9390dbb0d2cb86f47e528 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 04:53:30 +0530 Subject: [PATCH 02/10] Implement Linux and macOS support --- action.yml | 66 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/action.yml b/action.yml index cf10f06..f120c0a 100644 --- a/action.yml +++ b/action.yml @@ -32,24 +32,39 @@ runs: working-directory: ${{ github.action_path }} env: REQUESTED_VERSION: ${{ inputs.Version }} + PREVIEW: ${{ inputs.Preview }} GITHUB_TOKEN: ${{ github.token }} run: | # Install-PowerShell set -e echo "Requested version: [$REQUESTED_VERSION]" + echo "Preview mode: [$PREVIEW]" # 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 [[ "${PREVIEW,,}" == "true" ]]; then + echo "Fetching latest preview release..." + 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//' + ) + echo "Latest preview PowerShell release 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" + fi ;; "") echo "Error: Version input is required (or use 'latest')" @@ -106,24 +121,39 @@ runs: working-directory: ${{ github.action_path }} env: REQUESTED_VERSION: ${{ inputs.Version }} + PREVIEW: ${{ inputs.Preview }} GITHUB_TOKEN: ${{ github.token }} run: | # Install-PowerShell set -e echo "Requested version: [$REQUESTED_VERSION]" + echo "Preview mode: [$PREVIEW]" # 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 [[ "${PREVIEW,,}" == "true" ]]; then + echo "Fetching latest preview release..." + 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//' + ) + echo "Latest preview PowerShell release 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" + fi ;; "") echo "Error: Version input is required (or use 'latest')" From e3bfd0bc3ae25c0e9259a7b9aab1b1a51dfe5af9 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 04:53:40 +0530 Subject: [PATCH 03/10] Implement Windows support --- action.yml | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/action.yml b/action.yml index f120c0a..d0dd1e2 100644 --- a/action.yml +++ b/action.yml @@ -197,23 +197,38 @@ runs: working-directory: ${{ github.action_path }} env: REQUESTED_VERSION: ${{ inputs.Version }} + PREVIEW: ${{ inputs.Preview }} GITHUB_TOKEN: ${{ github.token }} run: | # Install-PowerShell Write-Host "Requested version: [$env:REQUESTED_VERSION]" + Write-Host "Preview mode: [$env:PREVIEW]" # 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)" - 'X-GitHub-Api-Version' = '2022-11-28' - } - ).tag_name.TrimStart('v') - Write-Host "Latest stable PowerShell release detected: $latest" + if ($env:PREVIEW -eq 'true') { + Write-Host "Fetching latest preview release..." + $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' + } + $latestPreview = $releases | Where-Object { $_.prerelease -eq $true } | Select-Object -First 1 + $latest = $latestPreview.tag_name.TrimStart('v') + Write-Host "Latest preview PowerShell release detected: $latest" + } else { + $latest = ( + Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest' ` + -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" + } $env:REQUESTED_VERSION = $latest } elseif ([string]::IsNullOrWhiteSpace($req)) { Write-Host "Error: Version input is required (or use 'latest')" From 65f62d4fb26ac2cbf147884083ff3fff2a6c0738 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 05:37:29 +0530 Subject: [PATCH 04/10] Add tests for preview --- .github/workflows/Action-Test.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index b0238f2..756500d 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -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', 'preview', '7.4.7', '7.5.0'] runs-on: ${{ matrix.os }} name: '${{ matrix.os }} - [${{ matrix.version }}]' steps: @@ -34,7 +34,8 @@ jobs: - name: Action-Test uses: ./ with: - Version: ${{ matrix.version }} + Version: ${{ matrix.version == 'preview' && 'latest' || matrix.version }} + Preview: ${{ matrix.version == 'preview' && 'true' || 'false' }} - name: Verify installed version shell: pwsh @@ -44,8 +45,19 @@ jobs: # Requested version that came from the matrix $requested = '${{ matrix.version }}' + # When 'preview' → resolve to latest preview release + if ($requested.Trim().ToLower() -eq 'preview') { + $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') + Write-Host "Resolved 'preview' → $requested" + } # 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 = ( From 3e97e340a6f8cd827154bc2a75517043dd095be6 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 05:43:50 +0530 Subject: [PATCH 05/10] Try to fix macOS substitutions for bash3 --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index d0dd1e2..bff80fc 100644 --- a/action.yml +++ b/action.yml @@ -43,7 +43,7 @@ runs: # Only resolve to latest version if explicitly set to 'latest' (case-insensitive) case "${REQUESTED_VERSION:-}" in [Ll][Aa][Tt][Ee][Ss][Tt]) - if [[ "${PREVIEW,,}" == "true" ]]; then + if [[ "$(echo "$PREVIEW" | tr '[:upper:]' '[:lower:]')" == "true" ]]; then echo "Fetching latest preview release..." REQUESTED_VERSION=$( curl -s -f \ @@ -132,7 +132,7 @@ runs: # Only resolve to latest version if explicitly set to 'latest' (case-insensitive) case "${REQUESTED_VERSION:-}" in [Ll][Aa][Tt][Ee][Ss][Tt]) - if [[ "${PREVIEW,,}" == "true" ]]; then + if [[ "$(echo "$PREVIEW" | tr '[:upper:]' '[:lower:]')" == "true" ]]; then echo "Fetching latest preview release..." REQUESTED_VERSION=$( curl -s -f \ From 359723c0d0187cd445838284fbbcd6ace59cb59b Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 05:45:53 +0530 Subject: [PATCH 06/10] Simplify for macOS --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index bff80fc..bfc852e 100644 --- a/action.yml +++ b/action.yml @@ -43,7 +43,7 @@ runs: # Only resolve to latest version if explicitly set to 'latest' (case-insensitive) case "${REQUESTED_VERSION:-}" in [Ll][Aa][Tt][Ee][Ss][Tt]) - if [[ "$(echo "$PREVIEW" | tr '[:upper:]' '[:lower:]')" == "true" ]]; then + if [[ "$PREVIEW" == "true" ]]; then echo "Fetching latest preview release..." REQUESTED_VERSION=$( curl -s -f \ @@ -132,7 +132,7 @@ runs: # Only resolve to latest version if explicitly set to 'latest' (case-insensitive) case "${REQUESTED_VERSION:-}" in [Ll][Aa][Tt][Ee][Ss][Tt]) - if [[ "$(echo "$PREVIEW" | tr '[:upper:]' '[:lower:]')" == "true" ]]; then + if [[ "$PREVIEW" == "true" ]]; then echo "Fetching latest preview release..." REQUESTED_VERSION=$( curl -s -f \ From 0777397d786f5d177d106b3807d9e0fbde0aa6f3 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 05:54:46 +0530 Subject: [PATCH 07/10] `pwsh-preview` for Preview, not pwsh --- .github/workflows/Action-Test.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 756500d..67b2f07 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -72,7 +72,13 @@ jobs: } # Actual version installed by the action - $installed = ($PSVersionTable.PSVersion).ToString() + # Preview builds install the executable named 'pwsh-preview' on Windows, + # so query that binary + if ('${{ matrix.version }}'.Trim().ToLower() -eq 'preview' -and $IsWindows) { + $installed = (pwsh-preview -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') + } else { + $installed = ($PSVersionTable.PSVersion).ToString() + } Write-Host "Installed PowerShell version: $installed" Write-Host "Expected PowerShell version: $requested" From ca66e82a24f58d306534d8dd3b094438d1b6702f Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 06:39:32 +0530 Subject: [PATCH 08/10] Try something --- .github/workflows/Action-Test.yml | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 67b2f07..b9e43ca 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -71,14 +71,32 @@ jobs: Write-Host "Resolved 'latest' → $requested" } - # Actual version installed by the action - # Preview builds install the executable named 'pwsh-preview' on Windows, - # so query that binary - if ('${{ matrix.version }}'.Trim().ToLower() -eq 'preview' -and $IsWindows) { - $installed = (pwsh-preview -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') + # Parse the major version from the requested version string + $majorVersion = $requested -replace '-.*$', '' | ForEach-Object { ($_ -split '\.')[0] } + Write-Host "Detected major version: $majorVersion" + + # Determine the installation directory based on preview vs stable + $isPreview = '${{ matrix.version }}'.Trim().ToLower() -eq 'preview' -or $requested -match '-preview\.' + if ($isPreview) { + $installDir = "$majorVersion-preview" } else { - $installed = ($PSVersionTable.PSVersion).ToString() + $installDir = "$majorVersion" } + + $pwshPath = "$env:ProgramFiles\PowerShell\$installDir\pwsh.exe" + Write-Host "Expected pwsh location: $pwshPath" + + # Verify the file exists + if (-not (Test-Path $pwshPath)) { + Write-Host "ERROR: PowerShell executable not found at expected path: $pwshPath" + Write-Host "`nSearching for all pwsh.exe installations..." + Get-ChildItem "$env:ProgramFiles\PowerShell" -Recurse -Filter "pwsh.exe" -ErrorAction SilentlyContinue | + ForEach-Object { Write-Host " Found: $($_.FullName)" } + throw "PowerShell executable not found at: $pwshPath" + } + + # Get the version from the installed executable + $installed = (& $pwshPath -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') Write-Host "Installed PowerShell version: $installed" Write-Host "Expected PowerShell version: $requested" From 3b5438e3525c01ce92841450afcb1b1087670540 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 07:06:48 +0530 Subject: [PATCH 09/10] Fix Linux and macOS infinite loops --- .github/workflows/Action-Test.yml | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index b9e43ca..bae49d1 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -71,32 +71,15 @@ jobs: Write-Host "Resolved 'latest' → $requested" } - # Parse the major version from the requested version string - $majorVersion = $requested -replace '-.*$', '' | ForEach-Object { ($_ -split '\.')[0] } - Write-Host "Detected major version: $majorVersion" - - # Determine the installation directory based on preview vs stable - $isPreview = '${{ matrix.version }}'.Trim().ToLower() -eq 'preview' -or $requested -match '-preview\.' - if ($isPreview) { - $installDir = "$majorVersion-preview" + # Actual version installed by the action + if ($IsWindows) { + $majorVersion = ($requested -split '[\.-]')[0] + $installDir = if ($requested -match 'preview') { "$majorVersion-preview" } else { $majorVersion } + $installed = (& "$env:ProgramFiles\PowerShell\$installDir\pwsh.exe" -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') } else { - $installDir = "$majorVersion" - } - - $pwshPath = "$env:ProgramFiles\PowerShell\$installDir\pwsh.exe" - Write-Host "Expected pwsh location: $pwshPath" - - # Verify the file exists - if (-not (Test-Path $pwshPath)) { - Write-Host "ERROR: PowerShell executable not found at expected path: $pwshPath" - Write-Host "`nSearching for all pwsh.exe installations..." - Get-ChildItem "$env:ProgramFiles\PowerShell" -Recurse -Filter "pwsh.exe" -ErrorAction SilentlyContinue | - ForEach-Object { Write-Host " Found: $($_.FullName)" } - throw "PowerShell executable not found at: $pwshPath" + $installed = (pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') } - # Get the version from the installed executable - $installed = (& $pwshPath -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') Write-Host "Installed PowerShell version: $installed" Write-Host "Expected PowerShell version: $requested" From 11284b1dd46aee3d03a848477737681603631d30 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 10 Feb 2026 07:24:54 +0530 Subject: [PATCH 10/10] Add docs --- README.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2447d9a..f3b3d73 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ # Install-PowerShell -A cross‑platform GitHub Action that installs a specific **PowerShell Core** version—or the latest stable release—on any GitHub‑hosted runner +A cross‑platform GitHub Action that installs a specific **PowerShell Core** version—or the latest stable or preview release—on any GitHub‑hosted runner (Linux, macOS, or Windows). The action automatically skips installation when the requested version is already present. ## Usage Add the action to a job in your workflow file: - ```yaml jobs: build: @@ -25,11 +24,27 @@ jobs: Write-Host "Using PowerShell $($PSVersionTable.PSVersion)" ``` +### Installing preview builds + +```yaml + - name: Install PowerShell Preview + uses: PSModule/install-powershell@v1 + with: + Version: latest + Preview: true + + - name: Run a PowerShell script + shell: pwsh + run: | + Write-Host "Using PowerShell $($PSVersionTable.PSVersion)" +``` + ## 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.1`). Use `latest` to install the newest stable release, or the newest preview release when `Preview` is `true`. | +| `Preview` | `false` | `false` | Install PowerShell preview build instead of stable. When `true` and `Version` is `latest`, installs the latest preview release. | ## Secrets @@ -43,7 +58,7 @@ 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 `Preview` is `true`, it queries for the latest preview release instead. * **Skip logic** Before installing, the action checks the current runner to see whether the requested version is already available