-
Notifications
You must be signed in to change notification settings - Fork 730
[bazel] Sandbox bash and git on Windows with tools/bazel.bat #9341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
PeterJohnson
merged 16 commits into
wpilibsuite:main
from
AustinSchuh:bazel-windows-bash-sandbox
Sep 7, 2026
+208
−0
Merged
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
0bafb24
[bazel] Sandbox bash and git on Windows with tools/bazel.bat
AustinSchuh fe8186e
[bazel] Address review feedback on the Windows wrapper
AustinSchuh de5a088
[bazel] Harden the Windows wrapper's git bootstrap
AustinSchuh 3419056
[bazel] Stop using delayed expansion in the Windows wrapper
AustinSchuh 4ee4c11
[bazel] Only shorten the profile path when it has a space
AustinSchuh 67cb172
[bazel] Let Bazel isolate repository rules instead of the wrapper
AustinSchuh 1241b54
[bazel] Scope the git config isolation to repository rules
AustinSchuh 4dff70d
[bazel] Pass the classifier filter through strict repo env
AustinSchuh 2a42b43
[bazel] Drop BAZEL_GIT and GIT_BIN_PATH, trim the comments
AustinSchuh 15adcc6
Apply suggestion from @auscompgeek
AustinSchuh d7ec673
Apply suggestion from @auscompgeek
AustinSchuh 43674b5
[bazel] Drop the git http.ssl repo_env settings
AustinSchuh 3b97eb0
Merge remote-tracking branch 'github/bazel-windows-bash-sandbox' into…
AustinSchuh 81ed09d
[bazel] Update the pinned git, run Windows CI through Bazelisk
AustinSchuh 606f927
[bazel] Explain why Windows CI has to name Bazelisk
AustinSchuh 7639182
Merge remote-tracking branch 'origin/main' into bazel-windows-bash-sa…
AustinSchuh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| @echo off | ||
| setlocal enabledelayedexpansion | ||
|
|
||
| :: Bazelisk runs this wrapper instead of Bazel itself on Windows. It bootstraps | ||
| :: a private copy of PortableGit, which supplies both git and bash/sh, and then | ||
| :: scrubs the environment before handing off to Bazel. That keeps the build from | ||
| :: depending on whatever happens to be installed and on PATH on the machine. | ||
|
|
||
| :: Use the short (8.3) form of the profile directory so that a user name with a | ||
| :: space in it doesn't break paths downstream. | ||
| for %%I in ("%USERPROFILE%") do set "USERPROFILE=%%~sI" | ||
|
|
||
| set "BAZEL_CACHE_DIR=%USERPROFILE%\.cache\bazel" | ||
|
|
||
| :: 1. Figure out which bazel we are supposed to hand off to. | ||
| if defined BAZEL_OVERRIDE ( | ||
| echo Actually calling "%BAZEL_OVERRIDE%" | ||
| set "_SAVE_TARGET=%BAZEL_OVERRIDE%" | ||
| ) else ( | ||
| :: 2. Ensure Bazelisk integration. | ||
| if not defined BAZEL_REAL ( | ||
| echo Error: This script must be run via Bazelisk on Windows. >&2 | ||
| exit /b 1 | ||
|
AustinSchuh marked this conversation as resolved.
|
||
| ) | ||
| set "_SAVE_TARGET=%BAZEL_REAL%" | ||
| ) | ||
|
|
||
| :: 3. Automated hermetic git bootstrapping with SHA256 validation. | ||
| set "GIT_CACHE_DIR=%BAZEL_CACHE_DIR%\portable_git" | ||
| set "GIT_EXE_PATH=%GIT_CACHE_DIR%\cmd\git.exe" | ||
|
|
||
| if not exist "%GIT_EXE_PATH%" ( | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
|
||
| echo [Wrapper] Git not detected in runtime cache. Fetching isolated PortableGit... >&2 | ||
|
|
||
| set "GIT_VERSION=v2.44.0.windows.1" | ||
| set "GIT_ZIP_NAME=PortableGit-2.44.0-64-bit.7z.exe" | ||
| set "GIT_URL=https://github.com/git-for-windows/git/releases/download/!GIT_VERSION!/!GIT_ZIP_NAME!" | ||
| set "EXPECTED_SHA256=1fc64ca91b9b475ab0ada72c9f7b3addbe69a6c8f520be31425cf21841cca369" | ||
|
|
||
| set "TEMP_DOWNLOAD_DIR=%BAZEL_CACHE_DIR%\git_tmp" | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
|
||
| if exist "!TEMP_DOWNLOAD_DIR!" rmdir /s /q "!TEMP_DOWNLOAD_DIR!" | ||
| mkdir "!TEMP_DOWNLOAD_DIR!" | ||
|
|
||
| echo [Wrapper] Downloading from !GIT_URL! ... >&2 | ||
|
|
||
| curl -fL --silent --show-error --output "!TEMP_DOWNLOAD_DIR!\git.7z.exe" "!GIT_URL!" | ||
| if errorlevel 1 ( | ||
| echo Error: Failed to download hermetic Git toolchain >&2 | ||
| exit /b 1 | ||
| ) | ||
|
|
||
| echo [Wrapper] Validating cryptographic payload checksum... >&2 | ||
| set "COMPUTED_SHA256=" | ||
| for /f "skip=1 delims=" %%A in ('certutil -hashfile "!TEMP_DOWNLOAD_DIR!\git.7z.exe" SHA256 ^| findstr /v "CertUtil"') do ( | ||
| set "LINE=%%A" | ||
| set "LINE=!LINE: =!" | ||
| set "COMPUTED_SHA256=!LINE!" | ||
| ) | ||
|
|
||
| if /i not "!COMPUTED_SHA256!"=="!EXPECTED_SHA256!" ( | ||
| echo. >&2 | ||
| echo =============================================================== >&2 | ||
| echo SECURITY ERROR: Cryptographic checksum mismatch detected. >&2 | ||
| echo Expected: !EXPECTED_SHA256! >&2 | ||
| echo Received: !COMPUTED_SHA256! >&2 | ||
| echo =============================================================== >&2 | ||
| rmdir /s /q "!TEMP_DOWNLOAD_DIR!" | ||
| exit /b 1 | ||
| ) | ||
| echo [Wrapper] Integrity verification successful. SHA256 matches. >&2 | ||
|
|
||
| echo [Wrapper] Extracting archive package... >&2 | ||
| mkdir "%GIT_CACHE_DIR%" 2>nul | ||
| "!TEMP_DOWNLOAD_DIR!\git.7z.exe" -y -o"%GIT_CACHE_DIR%" >nul | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
|
||
|
|
||
| rmdir /s /q "!TEMP_DOWNLOAD_DIR!" | ||
|
|
||
| echo [Wrapper] Isolated Git runtime setup completed successfully. >&2 | ||
| ) | ||
|
|
||
| :: 4. Environment sandboxing (the Windows equivalent of "env -i"). | ||
| set "_SAVE_SYSTEMROOT=%SystemRoot%" | ||
| set "_SAVE_SYSTEMDRIVE=%SystemDrive%" | ||
| set "_SAVE_COMSPEC=%ComSpec%" | ||
| set "_SAVE_PATH=%PATH%" | ||
| set "_SAVE_PATHEXT=%PATHEXT%" | ||
| set "_SAVE_TEMP=%TEMP%" | ||
| set "_SAVE_TMP=%TMP%" | ||
| set "_SAVE_USERPROFILE=%USERPROFILE%" | ||
| set "_SAVE_USERNAME=%USERNAME%" | ||
| set "_SAVE_COMPUTERNAME=%COMPUTERNAME%" | ||
| set "_SAVE_PROCESSOR_ARCHITECTURE=%PROCESSOR_ARCHITECTURE%" | ||
| :: Explicit MSVC overrides are an escape hatch for machines where Visual Studio | ||
| :: isn't in the default location, so let them survive the purge. | ||
| set "_SAVE_BAZEL_VC=%BAZEL_VC%" | ||
| set "_SAVE_BAZEL_VS=%BAZEL_VS%" | ||
| set "_SAVE_BAZEL_VC_FULL_VERSION=%BAZEL_VC_FULL_VERSION%" | ||
| set "_SAVE_BAZEL_WINSDK_FULL_VERSION=%BAZEL_WINSDK_FULL_VERSION%" | ||
| :: Critical cradle: back up our bootstrapped Git path and git configuration so | ||
| :: the environment purge loop below ignores them. Configure git through | ||
| :: GIT_CONFIG_PARAMETERS rather than "git config --global" so that we don't | ||
| :: scribble on the developer's own ~/.gitconfig. The value has to be a list of | ||
| :: single quoted key=value pairs or git rejects it outright. | ||
| set "_SAVE_GIT_CACHE_DIR=%GIT_CACHE_DIR%" | ||
| set "_SAVE_GIT_CONFIG_PARAMETERS='http.sslBackend=openssl' 'http.sslVerify=true'" | ||
|
|
||
| for /f "tokens=1 delims==" %%a in ('set') do ( | ||
| set "VAR_NAME=%%a" | ||
| if not "!VAR_NAME:~0,6!"=="_SAVE_" ( | ||
| set "%%a=" | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
AustinSchuh marked this conversation as resolved.
Outdated
|
||
| ) | ||
| ) | ||
|
|
||
| set "SystemRoot=%_SAVE_SYSTEMROOT%" | ||
| set "SystemDrive=%_SAVE_SYSTEMDRIVE%" | ||
| set "ComSpec=%_SAVE_COMSPEC%" | ||
| set "PATHEXT=%_SAVE_PATHEXT%" | ||
| set "TEMP=%_SAVE_TEMP%" | ||
| set "TMP=%_SAVE_TMP%" | ||
| set "USERPROFILE=%_SAVE_USERPROFILE%" | ||
| set "HOME=%_SAVE_USERPROFILE%" | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
|
||
| set "USERNAME=%_SAVE_USERNAME%" | ||
| set "USER=%_SAVE_USERNAME%" | ||
| set "COMPUTERNAME=%_SAVE_COMPUTERNAME%" | ||
| set "HOSTNAME=%_SAVE_COMPUTERNAME%" | ||
| set "PROCESSOR_ARCHITECTURE=%_SAVE_PROCESSOR_ARCHITECTURE%" | ||
| set "GIT_CONFIG_PARAMETERS=%_SAVE_GIT_CONFIG_PARAMETERS%" | ||
|
|
||
| if defined _SAVE_BAZEL_VC set "BAZEL_VC=%_SAVE_BAZEL_VC%" | ||
| if defined _SAVE_BAZEL_VS set "BAZEL_VS=%_SAVE_BAZEL_VS%" | ||
| if defined _SAVE_BAZEL_VC_FULL_VERSION set "BAZEL_VC_FULL_VERSION=%_SAVE_BAZEL_VC_FULL_VERSION%" | ||
| if defined _SAVE_BAZEL_WINSDK_FULL_VERSION set "BAZEL_WINSDK_FULL_VERSION=%_SAVE_BAZEL_WINSDK_FULL_VERSION%" | ||
|
|
||
| set "PATH=%_SAVE_SYSTEMROOT%\system32;%_SAVE_SYSTEMROOT%;%_SAVE_SYSTEMROOT%\System32\Wbem;%_SAVE_GIT_CACHE_DIR%\cmd;%_SAVE_GIT_CACHE_DIR%\bin;%_SAVE_GIT_CACHE_DIR%\usr\bin;%_SAVE_PATH%" | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
|
||
|
|
||
| :: Critical explicit binding: force Bazel's repository rules to bypass PATH | ||
| :: lookups entirely and use the copies we just bootstrapped. | ||
| set "BAZEL_GIT=%_SAVE_GIT_CACHE_DIR%\cmd\git.exe" | ||
| set "GIT_BIN_PATH=%_SAVE_GIT_CACHE_DIR%\cmd\git.exe" | ||
| set "BAZEL_SH=%_SAVE_GIT_CACHE_DIR%\bin\bash.exe" | ||
|
|
||
| set "TERM=dumb" | ||
| set "LANG=C" | ||
| set "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=0" | ||
|
|
||
| :: 5. Drop the scratch copies so that they do not leak into the environment | ||
| :: that Bazel and its repository rules end up seeing. | ||
| set "VAR_NAME=" | ||
| for /f "tokens=1 delims==" %%a in ('set _SAVE_') do ( | ||
| if not "%%a"=="_SAVE_TARGET" set "%%a=" | ||
| ) | ||
|
|
||
| :: 6. Execute the isolated Bazel process. | ||
| "%_SAVE_TARGET%" %* | ||
|
AustinSchuh marked this conversation as resolved.
Outdated
|
||
| endlocal | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.