Repository navigation
fix: run Bazel Maven scans on Windows #1658
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
+2,272
−845
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
5ce4b1e
fix: run Bazel Maven scans on Windows
mtorp a63a4ba
fix: keep native Windows executable paths
mtorp 0c7235d
test: handle Windows executable path casing
mtorp d4378dc
fix: only stop Bazel servers this scan started
mtorp aa20faf
fix: stop servers the scan started, keep inputs
mtorp 33305d7
fix: stop launcher trees and verify server exit
mtorp 35b6556
Merge remote-tracking branch 'origin/v1.x' into martin/windows-bazel-…
mtorp 5478276
fix: keep scans passing when pid files can't be read
mtorp 0d97adc
fix: report cancelled Bazel runs as aborted on Windows
mtorp 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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| name: Bazel on Windows | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main, v1.x] | ||
| paths: | ||
| - .github/workflows/bazel-windows.yml | ||
| - package.json | ||
| - pnpm-lock.yaml | ||
| - src/commands/manifest/bazel/** | ||
| - test/fixtures/manifest-bazel/** | ||
| push: | ||
| branches: [main, v1.x] | ||
| paths: | ||
| - .github/workflows/bazel-windows.yml | ||
| - package.json | ||
| - pnpm-lock.yaml | ||
| - src/commands/manifest/bazel/** | ||
| - test/fixtures/manifest-bazel/** | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: bazel-windows-${{ github.ref }} | ||
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | ||
|
|
||
| jobs: | ||
| maven: | ||
| name: Maven on Windows x64 | ||
| runs-on: windows-2022 | ||
| timeout-minutes: 45 | ||
| defaults: | ||
| run: | ||
| shell: pwsh | ||
| steps: | ||
| - name: Checkout source | ||
| env: | ||
| CHECKOUT_REF: ${{ github.sha }} | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
| SERVER_URL: ${{ github.server_url }} | ||
| REPOSITORY: ${{ github.repository }} | ||
| run: | | ||
| $PSNativeCommandUseErrorActionPreference = $true | ||
| git init -q | ||
| git config --local advice.detachedHead false | ||
| git remote add origin "$env:SERVER_URL/$env:REPOSITORY" | ||
| $auth = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("x-access-token:$env:GITHUB_TOKEN")) | ||
| $env:GIT_CONFIG_COUNT = '1' | ||
| $env:GIT_CONFIG_KEY_0 = "http.$env:SERVER_URL/.extraheader" | ||
| $env:GIT_CONFIG_VALUE_0 = "AUTHORIZATION: basic $auth" | ||
| git fetch --no-tags --depth=1 origin $env:CHECKOUT_REF | ||
| git checkout -q --detach FETCH_HEAD | ||
|
|
||
| - name: Install pinned toolchains | ||
| run: | | ||
| $tools = Join-Path $env:RUNNER_TEMP 'bazel-tools' | ||
| New-Item -ItemType Directory -Force "$tools/bin" | Out-Null | ||
| function Get-VerifiedTool($url, $file, $sha256) { | ||
| Invoke-WebRequest -Uri $url -OutFile $file | ||
| if ((Get-FileHash $file -Algorithm SHA256).Hash.ToLowerInvariant() -ne $sha256) { | ||
| throw "Checksum mismatch for $file" | ||
| } | ||
| } | ||
| Get-VerifiedTool 'https://nodejs.org/dist/v24.14.1/node-v24.14.1-win-x64.zip' "$tools/node.zip" '6e50ce5498c0cebc20fd39ab3ff5df836ed2f8a31aa093cecad8497cff126d70' | ||
| Get-VerifiedTool 'https://api.nuget.org/v3-flatcontainer/python/3.12.10/python.3.12.10.nupkg' "$tools/python.zip" '0eb85c2dfccccf1b17352de4c397f69194035b7d37149eacc16f1147d93de3b8' | ||
| Get-VerifiedTool 'https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_x64_windows_hotspot_21.0.6_7.zip' "$tools/java.zip" '897c8eebb0f85a99ccecbd482ebae9a45d88c19d6077054f6529ebab49b6d259' | ||
| Get-VerifiedTool 'https://github.com/bazelbuild/bazelisk/releases/download/v1.26.0/bazelisk-windows-amd64.exe' "$tools/bin/bazelisk.exe" '023734f33ed6b9c6d65468fe20bb2c5fb32473ccb8aca2fc5bf1521e61ce1622' | ||
| Get-VerifiedTool 'https://github.com/pnpm/pnpm/releases/download/v10.33.0/pnpm-win-x64.exe' "$tools/bin/pnpm.exe" 'afc96009dc39fe23a835d65192049e6a995f342496b175585dc2beda7d42d33f' | ||
| Expand-Archive "$tools/node.zip" "$tools/node" | ||
| Expand-Archive "$tools/python.zip" "$tools/python" | ||
| Expand-Archive "$tools/java.zip" "$tools/java" | ||
| "$tools/node/node-v24.14.1-win-x64" | Add-Content $env:GITHUB_PATH | ||
| "$tools/python/tools" | Add-Content $env:GITHUB_PATH | ||
| "$tools/java/jdk-21.0.6+7/bin" | Add-Content $env:GITHUB_PATH | ||
| "$tools/bin" | Add-Content $env:GITHUB_PATH | ||
| "JAVA_HOME=$tools/java/jdk-21.0.6+7" | Add-Content $env:GITHUB_ENV | ||
| 'USE_BAZEL_VERSION=7.4.1' | Add-Content $env:GITHUB_ENV | ||
| 'SOCKET_BAZEL_OUTPUT_ROOT=C:/sb' | Add-Content $env:GITHUB_ENV | ||
| New-Item -ItemType Directory -Force 'C:/sb' | Out-Null | ||
|
|
||
| - name: Record versions and verify prerequisites | ||
| run: | | ||
| $PSNativeCommandUseErrorActionPreference = $true | ||
| git rev-parse HEAD | ||
| node --version | ||
| pnpm --version | ||
| bazelisk --version | ||
| python --version | ||
| java -version | ||
| Write-Output "PowerShell $($PSVersionTable.PSVersion)" | ||
| Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, OSArchitecture | ||
| Get-Command node, bazelisk, python, java | Select-Object Name, Source | ||
|
|
||
| - name: Install dependencies and build | ||
| run: | | ||
| $PSNativeCommandUseErrorActionPreference = $true | ||
| pnpm install --frozen-lockfile | ||
| pnpm build | ||
|
|
||
| - name: Test executable handling and prerequisites | ||
| run: | | ||
| $PSNativeCommandUseErrorActionPreference = $true | ||
| pnpm test:unit src/commands/manifest/bazel/bazel-bin-detect.test.mts src/commands/manifest/bazel/bazel-process.test.mts src/commands/manifest/bazel/bazel-java-shim.test.mts src/commands/manifest/bazel/bazel-python-shim.test.mts src/commands/manifest/bazel/bazel-query-runner.test.mts src/commands/manifest/bazel/bazel-cquery.test.mts | ||
|
|
||
| - name: Install the packaged CLI | ||
| run: | | ||
| $PSNativeCommandUseErrorActionPreference = $true | ||
| $packages = Join-Path $env:RUNNER_TEMP 'bazel-packages' | ||
| $installation = Join-Path $env:RUNNER_TEMP 'bazel-installation' | ||
| pnpm pack --pack-destination $packages | ||
| $tarball = Get-ChildItem "$packages/*.tgz" | Select-Object -First 1 | ||
| npm install --ignore-scripts --no-audit --no-fund --prefix $installation $tarball.FullName | ||
| "SOCKET_BAZEL_TEST_CLI=$installation/node_modules/socket/bin/cli.js" | Add-Content $env:GITHUB_ENV | ||
|
|
||
| - name: Verify Maven manifests and cleanup | ||
| env: | ||
| SOCKET_BAZEL_INTEGRATION: '1' | ||
| run: | | ||
| $PSNativeCommandUseErrorActionPreference = $true | ||
| pnpm exec vitest run --config vitest.e2e.config.mts src/commands/manifest/bazel/bazel-native.e2e.test.mts | ||
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
|---|---|---|
| @@ -1,53 +1,95 @@ | ||
| import { beforeEach, describe, expect, it, vi } from 'vitest' | ||
| import { | ||
| copyFileSync, | ||
| mkdtempSync, | ||
| realpathSync, | ||
| rmSync, | ||
| statSync, | ||
| } from 'node:fs' | ||
| import os from 'node:os' | ||
| import path from 'node:path' | ||
|
|
||
| // Mock whichBin so tests run with no bazel on PATH. | ||
| vi.mock('@socketsecurity/registry/lib/bin', () => ({ | ||
| whichBin: vi.fn(), | ||
| })) | ||
|
|
||
| import { whichBin } from '@socketsecurity/registry/lib/bin' | ||
| import { afterEach, beforeEach, describe, expect, it } from 'vitest' | ||
|
|
||
| import { resolveBazelBinary } from './bazel-bin-detect.mts' | ||
| import { getBazelEnvironment } from './bazel-process.mts' | ||
|
|
||
| describe('resolveBazelBinary', () => { | ||
| const mocked = vi.mocked(whichBin) | ||
| let cwd: string | ||
|
|
||
| beforeEach(() => { | ||
| mocked.mockReset() | ||
| cwd = realpathSync(mkdtempSync(path.join(os.tmpdir(), 'bazel binaries '))) | ||
| }) | ||
|
|
||
| it('returns explicit path when it exists', async () => { | ||
| // Use a path that definitely exists on every dev machine. | ||
| const existing = process.execPath | ||
| await expect(resolveBazelBinary(existing)).resolves.toBe(existing) | ||
| afterEach(() => { | ||
| rmSync(cwd, { recursive: true, force: true, maxRetries: 5 }) | ||
| }) | ||
|
|
||
| it('throws InputError when explicit path does not exist', async () => { | ||
| await expect( | ||
| resolveBazelBinary('/no/such/bazel/binary/xyz'), | ||
| ).rejects.toThrow(/--bazel path does not exist/) | ||
| function install(name: string): string { | ||
| const bin = path.join( | ||
| cwd, | ||
| `${name}${process.platform === 'win32' ? '.exe' : ''}`, | ||
| ) | ||
| copyFileSync(process.execPath, bin) | ||
| return bin | ||
| } | ||
|
|
||
| it('resolves an explicit path relative to the scan directory', async () => { | ||
| const bin = install('bazel') | ||
| const resolved = await resolveBazelBinary( | ||
| path.basename(bin), | ||
| getBazelEnvironment(), | ||
| cwd, | ||
| ) | ||
| expect(statSync(resolved).ino).toBe(statSync(bin).ino) | ||
| }) | ||
|
|
||
| it('preserves an explicit executable outside PATH', async () => { | ||
| const bin = install('selected') | ||
| const resolved = await resolveBazelBinary( | ||
| bin, | ||
| getBazelEnvironment({ PATH: '' }), | ||
| cwd, | ||
| ) | ||
| expect(statSync(resolved).ino).toBe(statSync(bin).ino) | ||
| }) | ||
|
|
||
| it('returns bazelisk when on PATH', async () => { | ||
| mocked.mockResolvedValueOnce('/usr/local/bin/bazelisk') | ||
| await expect(resolveBazelBinary(undefined)).resolves.toBe( | ||
| '/usr/local/bin/bazelisk', | ||
| it('prefers Bazelisk over Bazel', async () => { | ||
| const bazelisk = install('bazelisk') | ||
| install('bazel') | ||
| const resolved = await resolveBazelBinary( | ||
| undefined, | ||
| getBazelEnvironment({ PATH: cwd }), | ||
| cwd, | ||
| ) | ||
| expect(statSync(resolved).ino).toBe(statSync(bazelisk).ino) | ||
| }) | ||
|
|
||
| it('falls back to bazel when bazelisk is missing', async () => { | ||
| mocked | ||
| .mockResolvedValueOnce(null) | ||
| .mockResolvedValueOnce('/usr/local/bin/bazel') | ||
| await expect(resolveBazelBinary(undefined)).resolves.toBe( | ||
| '/usr/local/bin/bazel', | ||
| it('falls back to Bazel when Bazelisk is absent', async () => { | ||
| const bazel = install('bazel') | ||
| const resolved = await resolveBazelBinary( | ||
| undefined, | ||
| getBazelEnvironment({ PATH: cwd }), | ||
| cwd, | ||
| ) | ||
| expect(statSync(resolved).ino).toBe(statSync(bazel).ino) | ||
| }) | ||
|
|
||
| it('throws InputError when neither is on PATH', async () => { | ||
| mocked.mockResolvedValue(null) | ||
| await expect(resolveBazelBinary(undefined)).rejects.toThrow( | ||
| /Could not find bazelisk or bazel/, | ||
| it('finds tools in a quoted PATH entry', async () => { | ||
| const bazel = install('bazel') | ||
| const resolved = await resolveBazelBinary( | ||
| undefined, | ||
| getBazelEnvironment({ PATH: `"${cwd}"` }), | ||
| os.tmpdir(), | ||
| ) | ||
| expect(statSync(resolved).ino).toBe(statSync(bazel).ino) | ||
| }) | ||
|
|
||
| it('reports missing tools', async () => { | ||
| await expect( | ||
| resolveBazelBinary(undefined, getBazelEnvironment({ PATH: cwd }), cwd), | ||
| ).rejects.toThrow(/Could not find bazelisk or bazel/) | ||
| await expect( | ||
| resolveBazelBinary(path.join(cwd, 'missing'), getBazelEnvironment(), cwd), | ||
| ).rejects.toThrow(/--bazel path does not exist/) | ||
| }) | ||
| }) |
Oops, something went wrong.
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.