Created
April 2, 2026 01:08
-
-
Save AmosLewis/070d3c14f525a717d2c6da7394bea79c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 | |
| } |
Author
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
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.