Skip to content

Commit 159c292

Browse files
🚀 [Feature]: Token-controlled GitHub release lookup now supports authenticated or anonymous mode (#26)
Install-PowerShell now lets workflows control how release metadata is fetched from GitHub, including default GitHub token usage, custom token usage, and fully anonymous lookup when no token is provided. This keeps existing workflows working while making rate-limit and restricted-permission scenarios easier to handle. - Fixes #23 ## New: Configurable authentication for release metadata lookup The action now supports a `Token` input that controls authentication for GitHub API requests used during version resolution. By default, it behaves exactly as before by using `${{ github.token }}`, and workflows can now explicitly provide a custom token or set `Token: ''` for anonymous API calls. ```yaml - uses: PSModule/install-powershell@v1 with: Version: latest Token: '' ``` An optional `Host` input is also available for environments that need a non-default GitHub host. ## Changed: Linux and macOS API queries now use GitHub CLI API path when available GitHub API calls that resolve release information on Linux and macOS now use the GitHub CLI API path, with a compatible REST fallback when the CLI is not available. Package download behavior remains unchanged. ## Fixed: Empty token no longer sends an Authorization header When token input is empty, all platform-specific API calls now omit the `Authorization` header so anonymous release lookups work as expected. ## Technical Details - Updated action inputs and platform env wiring in `action.yml` to flow `Token` into `GITHUB_TOKEN` and into `GH_TOKEN`/`GH_HOST` for CLI-driven API calls. - Replaced Linux/macOS release metadata curl API calls with a `github_api_get` helper that prefers `gh api` and falls back to `curl`. - Updated Windows latest-version resolution headers to conditionally include `Authorization` only when `GITHUB_TOKEN` is present. - Updated `README.md` inputs and secrets documentation for token/host behavior. - Implementation plan progress: all core change tasks completed; documentation task for adding explicit usage examples remains open and can be added in a follow-up update. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent e2f7da1 commit 159c292

7 files changed

Lines changed: 759 additions & 512 deletions

File tree

Lines changed: 78 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Action-Test
22

3-
run-name: "Action-Test - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}"
3+
run-name: 'Action-Test - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}'
44

55
on:
66
workflow_dispatch:
@@ -25,6 +25,8 @@ jobs:
2525
version: ['latest', 'prerelease', '7.4.7', '7.5.0', '7.4.0-preview.5']
2626
runs-on: ${{ matrix.os }}
2727
name: '${{ matrix.os }} - [${{ matrix.version }}]'
28+
env:
29+
TestGitHubToken: ${{ github.token }}
2830
steps:
2931
- name: Checkout repo
3032
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -40,72 +42,79 @@ jobs:
4042
- name: Verify installed version
4143
shell: pwsh
4244
env:
43-
GITHUB_TOKEN: ${{ github.token }}
45+
RequestedVersion: ${{ matrix.version }}
4446
run: |
45-
# Requested version that came from the matrix
46-
$requested = '${{ matrix.version }}'
47-
48-
# When 'prerelease' → resolve to latest prerelease
49-
if ($requested.Trim().ToLower() -eq 'prerelease') {
50-
$releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases' `
51-
-Headers @{
52-
'Accept' = 'application/vnd.github+json'
53-
'Authorization' = "Bearer $($env:GITHUB_TOKEN)"
54-
'X-GitHub-Api-Version' = '2022-11-28'
55-
}
56-
$latestPrerelease = $releases | Where-Object { $_.prerelease -eq $true } | Select-Object -First 1
57-
if (-not $latestPrerelease) {
58-
throw "No prerelease releases found for PowerShell/PowerShell."
59-
}
60-
$requested = $latestPrerelease.tag_name.TrimStart('v')
61-
Write-Host "Resolved 'prerelease' → $requested"
62-
}
63-
# When empty / 'null' / 'latest' → resolve to latest stable release
64-
elseif ([string]::IsNullOrWhiteSpace($requested) -or
65-
$requested.Trim().ToLower() -in @('latest','null')) {
66-
67-
$requested = (
68-
Invoke-RestMethod -Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest' `
69-
-Headers @{
70-
'Accept' = 'application/vnd.github+json'
71-
'Authorization' = "Bearer $($env:GITHUB_TOKEN)"
72-
'X-GitHub-Api-Version' = '2022-11-28'
73-
}
74-
).tag_name.TrimStart('v')
75-
Write-Host "Resolved 'latest' → $requested"
76-
}
77-
78-
# On Windows, always verify by launching pwsh from the known install directory.
79-
# This avoids relying on PATH resolution, which may still point to the pre-installed
80-
# version if the runner's environment hasn't refreshed after the MSI install.
81-
if ($IsWindows) {
82-
$isPrerelease = $requested -match '-'
83-
$majorVersion = ($requested -split '[\.-]')[0]
84-
$installDir = if ($isPrerelease) { "$majorVersion-preview" } else { $majorVersion }
85-
$pwshPath = "$env:ProgramFiles\PowerShell\$installDir\pwsh.exe"
86-
Write-Host "Windows: verifying via subprocess at $pwshPath"
87-
if (Test-Path $pwshPath) {
88-
$installed = (& $pwshPath -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()')
89-
} else {
90-
Write-Host "Warning: Expected pwsh not found at $pwshPath, falling back to `$PSVersionTable"
91-
$installed = ($PSVersionTable.PSVersion).ToString()
92-
}
93-
} else {
94-
$installed = ($PSVersionTable.PSVersion).ToString()
95-
}
96-
Write-Host "Installed PowerShell version: $installed"
97-
Write-Host "Expected PowerShell version: $requested"
98-
99-
if ($installed -ne $requested) {
100-
throw "Failed: expected $requested but got $installed"
101-
}
102-
103-
# For prerelease matrix entries, additionally assert the version string
104-
# contains a prerelease segment so we never silently fall back to stable.
105-
$matrixVersion = '${{ matrix.version }}'
106-
if ($matrixVersion.Trim().ToLower() -eq 'prerelease') {
107-
if ($installed -notmatch '-') {
108-
throw "Prerelease validation failed: installed version '$installed' does not contain a prerelease segment."
109-
}
110-
Write-Host "Prerelease check passed: '$installed' contains a prerelease segment."
111-
}
47+
./tests/scripts/Verify-InstalledVersion.ps1 -RequestedVersion "$env:RequestedVersion" -GitHubToken "$env:TestGitHubToken"
48+
49+
ActionTestTokenUseCaseDefault:
50+
name: 'ubuntu-latest - [Token default behavior]'
51+
runs-on: ubuntu-latest
52+
env:
53+
TestGitHubToken: ${{ github.token }}
54+
TestLatestVersion: latest
55+
steps:
56+
- name: Checkout repo
57+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
58+
with:
59+
persist-credentials: false
60+
61+
- name: Action-Test (Default token behavior)
62+
uses: ./
63+
with:
64+
Version: ${{ env.TestLatestVersion }}
65+
66+
- name: Verify default token behavior
67+
shell: pwsh
68+
env:
69+
RequestedVersion: ${{ env.TestLatestVersion }}
70+
run: |
71+
./tests/scripts/Verify-InstalledVersion.ps1 -RequestedVersion "$env:RequestedVersion" -GitHubToken "$env:TestGitHubToken"
72+
73+
ActionTestTokenUseCaseExplicit:
74+
name: 'ubuntu-latest - [Token explicit input]'
75+
runs-on: ubuntu-latest
76+
env:
77+
TestGitHubToken: ${{ github.token }}
78+
TestLatestVersion: latest
79+
steps:
80+
- name: Checkout repo
81+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
82+
with:
83+
persist-credentials: false
84+
85+
- name: Action-Test (Explicit token input)
86+
uses: ./
87+
with:
88+
Version: ${{ env.TestLatestVersion }}
89+
Token: ${{ env.TestGitHubToken }}
90+
91+
- name: Verify explicit token input behavior
92+
shell: pwsh
93+
env:
94+
RequestedVersion: ${{ env.TestLatestVersion }}
95+
run: |
96+
./tests/scripts/Verify-InstalledVersion.ps1 -RequestedVersion "$env:RequestedVersion" -GitHubToken "$env:TestGitHubToken"
97+
98+
ActionTestTokenUseCaseAnonymous:
99+
name: 'ubuntu-latest - [Token anonymous mode]'
100+
runs-on: ubuntu-latest
101+
env:
102+
TestLatestVersion: latest
103+
steps:
104+
- name: Checkout repo
105+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
106+
with:
107+
persist-credentials: false
108+
109+
- name: Action-Test (Anonymous mode)
110+
uses: ./
111+
with:
112+
Version: ${{ env.TestLatestVersion }}
113+
Token: ''
114+
115+
- name: Verify anonymous mode behavior
116+
shell: pwsh
117+
env:
118+
RequestedVersion: ${{ env.TestLatestVersion }}
119+
run: |
120+
./tests/scripts/Verify-InstalledVersion.ps1 -RequestedVersion "$env:RequestedVersion"

‎README.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,14 @@ jobs:
5050
| ----- | -------- | ------- | ----------- |
5151
| `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`). |
5252
| `Prerelease` | `false` | `false` | Install a prerelease version. When `true` and `Version` is `latest`, resolves to the latest prerelease. Similar to `-Prerelease` on `Install-PSResource`. |
53+
| `Token` | `false` | `${{ github.token }}` | Token used for GitHub API requests. Set to an empty string (`''`) for anonymous API calls. |
54+
| `Host` | `false` | `github.com` | GitHub host used by the CLI/API path. Keep `github.com` for GitHub.com, or set your GHES hostname. |
5355

5456
## Secrets
5557

56-
This action does **not** require any secrets.
58+
This action does **not** require custom secrets by default because it uses `${{ github.token }}`.
59+
60+
If needed, provide `Token` with a custom PAT. To force anonymous API access, set `Token: ''`.
5761
5862
## Outputs
5963

0 commit comments

Comments
 (0)