Skip to content

Instantly share code, notes, and snippets.

@AmosLewis
Created April 2, 2026 01:08
Show Gist options
  • Select an option

  • Save AmosLewis/070d3c14f525a717d2c6da7394bea79c to your computer and use it in GitHub Desktop.

Select an option

Save AmosLewis/070d3c14f525a717d2c6da7394bea79c to your computer and use it in GitHub Desktop.
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Install Git for Windows so `bash` is available on PATH for GitHub Actions jobs.
.DESCRIPTION
ROCm/TheRock CI uses `shell: bash` in composite actions and job defaults (e.g.
`.github/actions/setup_test_environment`). The runner process must resolve `bash`
from PATH — same pattern as GitHub-hosted windows-latest (Git Bash included).
OrchestrAI bare-metal Windows images may only have Docker + PowerShell; they still
need Git's bash.exe for those workflows.
.PARAMETER SkipRestartRunnerService
If set, do not attempt to restart GitHub Actions runner services after install.
.NOTES
Run elevated on each Windows self-hosted runner. If jobs still fail, reboot once
so the runner service picks up Machine PATH.
.EXAMPLE
PS> .\install_git_bash_for_gha_runner.ps1
#>
[CmdletBinding()]
param(
[switch] $SkipRestartRunnerService
)
$ErrorActionPreference = 'Stop'
function Add-MachinePathEntry {
param(
[Parameter(Mandatory)]
[string] $Directory
)
$Directory = $Directory.TrimEnd('\')
if (-not (Test-Path -LiteralPath $Directory)) {
return
}
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
$parts = @(
$machinePath -split ';' |
ForEach-Object { $_.Trim() } |
Where-Object { $_ }
)
if ($parts -contains $Directory) {
Write-Host "PATH already contains: $Directory" -ForegroundColor DarkGray
return
}
$newPath = ($parts + $Directory) -join ';'
[Environment]::SetEnvironmentVariable('Path', $newPath, 'Machine')
$env:Path = "$newPath;$env:Path"
Write-Host "Appended to Machine PATH: $Directory" -ForegroundColor Green
}
function Install-GitViaWinget {
if (-not (Get-Command winget.exe -ErrorAction SilentlyContinue)) {
return $false
}
Write-Host "`n=== Installing Git.Git via winget (machine scope) ===" -ForegroundColor Cyan
& winget.exe install --id Git.Git -e --scope machine `
--accept-package-agreements --accept-source-agreements
return $true
}
function Install-GitViaChoco {
if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) {
return $false
}
Write-Host "`n=== Installing git via Chocolatey ===" -ForegroundColor Cyan
choco install git -y --no-progress
return $true
}
function Restart-GithubRunnerServices {
Write-Host "`n=== Restarting GitHub Actions runner services ===" -ForegroundColor Cyan
$services = Get-Service -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'actions.runner.*' }
if (-not $services) {
Write-Host "No services matching actions.runner.* (runner may use a different host model)." -ForegroundColor Yellow
return
}
foreach ($svc in $services) {
try {
Restart-Service -Name $svc.Name -Force
Write-Host "Restarted: $($svc.Name)" -ForegroundColor Green
}
catch {
Write-Warning "Could not restart $($svc.Name): $_"
}
}
}
# ── Main ──────────────────────────────────────────────────────────────────────
$gitBin = Join-Path ${env:ProgramFiles} 'Git\bin'
$gitCmd = Join-Path ${env:ProgramFiles} 'Git\cmd'
$bashExe = Join-Path $gitBin 'bash.exe'
$existing = Get-Command bash.exe -ErrorAction SilentlyContinue
if ($existing) {
Write-Host "bash already on PATH: $($existing.Source)" -ForegroundColor Green
exit 0
}
if (Test-Path -LiteralPath $bashExe) {
Write-Host "Git bash found at $bashExe but not on PATH; updating Machine PATH only." -ForegroundColor Yellow
}
else {
$installed = $false
if (Install-GitViaWinget) {
$installed = $true
}
elseif (Install-GitViaChoco) {
$installed = $true
}
if (-not $installed) {
Write-Host @"
No winget and no choco found. Install Git for Windows manually, then re-run this script
to ensure Machine PATH includes Git\bin:
https://git-scm.com/download/win
Silent install: download the latest Git-64-bit.exe from
https://github.com/git-for-windows/git/releases
then: Start-Process -FilePath `$path\to\Git-64-bit.exe -ArgumentList '/VERYSILENT','/NORESTART' -Wait
"@ -ForegroundColor Red
exit 1
}
if (-not (Test-Path -LiteralPath $bashExe)) {
Write-Error "Git install finished but bash not found at $bashExe. Check install log or non-default install path."
}
}
Add-MachinePathEntry -Directory $gitBin
Add-MachinePathEntry -Directory $gitCmd
$env:Path = "$gitBin;$gitCmd;$env:Path"
$verify = Get-Command bash.exe -ErrorAction SilentlyContinue
if (-not $verify) {
Write-Error "bash.exe still not resolvable. Reboot the host, or add Git\bin to Machine PATH manually."
}
Write-Host "`nOK: $($verify.Source)" -ForegroundColor Green
if (-not $SkipRestartRunnerService) {
Restart-GithubRunnerServices
Write-Host "`nIf the next job still reports 'bash: command not found', reboot once." -ForegroundColor Yellow
}
@AmosLewis

Copy link
Copy Markdown
Author

To solve https://github.com/ROCm/TheRock/actions/runs/23870669925/job/69624712807

Git for Windows was already installed on the runner, but C:\Program Files\Git\bin was not on the machine-wide (system) PATH, so GitHub Actions steps that use shell: bash could not resolve bash and failed with “bash: command not found.” We ran the UCICD helper script, which added C:\Program Files\Git\bin to the system PATH. After that, bash resolves correctly (e.g. Get-Command bash → C:\Program Files\Git\bin\bash.exe). Please re-run the failing workflow; if jobs still don’t see the updated PATH, restart the runner process or reboot the host so the GitHub Actions worker picks up the new environment.

@AmosLewis

Copy link
Copy Markdown
Author
PS C:\Users\defaultuser\src> Invoke-WebRequest -Uri 'https://gist.githubusercontent.com/AmosLewis/070d3c14f525a717d2c6da7394bea79c/raw/f8e0868733994f38ec83700e986c7267f2f9c0ed/install_git_bash_for_ucicd_runner.ps1' -OutFile .\install_git_bash_for_ucicd_runner.ps1 -UseBasicParsing
PS C:\Users\defaultuser\src> ls


    Directory: C:\Users\defaultuser\src


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          4/1/2026   9:16 PM           5163 install_git_bash_for_ucicd_runner.ps1


PS C:\Users\defaultuser\src> Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
PS C:\Users\defaultuser\src> .\install_git_bash_for_ucicd_runner.ps1
Git bash found at C:\Program Files\Git\bin\bash.exe but not on PATH; updating Machine PATH only.
Appended to Machine PATH: C:\Program Files\Git\bin
PATH already contains: C:\Program Files\Git\cmd

OK: C:\Program Files\Git\bin\bash.exe

=== Restarting GitHub Actions runner services ===
No services matching actions.runner.* (runner may use a different host model).

If the next job still reports 'bash: command not found', reboot once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment