Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 51 additions & 11 deletions .github/workflows/ci_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,49 @@ jobs:
build_and_test:
runs-on: windows-latest
timeout-minutes: 20
env:
BAZELISK_HOME: ${{ github.workspace }}\.bazel-cache\bazelisk
BAZEL_DISK_CACHE: ${{ github.workspace }}\.bazel-cache\disk
BAZEL_PROFILE_JSON: ${{ github.workspace }}\windows-fastbuild-profile.json.gz
WINDOWS_FASTBUILD_TARGETS: >-
//library/... //examples/... //python/... //jni/...
WINDOWS_OPT_TARGETS: >-
//library/src:dds //examples:analyse_play_pbn
steps:
# Checkout the repository
- name: Checkout repository
uses: actions/checkout@v6

# Reuse downloaded Bazel binaries across workflow runs
- name: Restore Bazelisk cache
uses: actions/cache@v4
with:
path: ${{ env.BAZELISK_HOME }}
key: windows-bazelisk-cache-${{ runner.os }}-${{ hashFiles('.bazelversion') }}
restore-keys: |
windows-bazelisk-cache-${{ runner.os }}-

# Install Bazelisk (recommended Bazel launcher)
- name: Setup Bazelisk
uses: ./.github/actions/setup-bazelisk

# Warm external deps (emsdk, LLVM, …); retry transient network fetch failures
# Reuse compiled/action cache artifacts across workflow runs
- name: Restore Bazel disk cache
uses: actions/cache@v4
with:
path: ${{ github.workspace }}\.bazel-cache\disk
key: windows-bazel-disk-cache-${{ runner.os }}-${{ hashFiles('.bazelversion', '.bazelrc', 'MODULE.bazel', 'MODULE.bazel.lock', 'BUILD.bazel', 'CPPVARIABLES.bzl') }}
restore-keys: |
windows-bazel-disk-cache-${{ runner.os }}-

# Warm external deps for the same scope tested on Windows
- name: Prefetch external repos
shell: pwsh
run: |
[string[]]$fastbuild_targets = $env:WINDOWS_FASTBUILD_TARGETS -split '\s+' | Where-Object { $_ -ne '' }
$max = 3
for ($i = 1; $i -le $max; $i++) {
bazelisk fetch //...
bazelisk fetch --disk_cache="$env:BAZEL_DISK_CACHE" --verbose_failures @fastbuild_targets
if ($LASTEXITCODE -eq 0) { exit 0 }
if ($i -lt $max) {
Write-Host "Fetch failed (attempt $i/$max). Retrying in 20s..."
Expand All @@ -33,15 +60,21 @@ jobs:
}
exit 1

# Build all targets (retry: fetch flakes can still surface on first analysis).
# --config=opt: DDS_CPPOPTS no longer forces /O2 (that fought Bazel's /Od and
# triggered MSVC D9025); opt mode is how Windows keeps release-level codegen.
- name: Bazel build (retry on transient fetch failure)
# Run Windows-native coverage in fastbuild (test-centric flow)
- name: Run Windows test targets
shell: pwsh
run: |
[string[]]$fastbuild_targets = $env:WINDOWS_FASTBUILD_TARGETS -split '\s+' | Where-Object { $_ -ne '' }
bazelisk test --disk_cache="$env:BAZEL_DISK_CACHE" --profile="$env:BAZEL_PROFILE_JSON" --verbose_failures @fastbuild_targets

# Keep a narrow release-level check on Windows with --config=opt
- name: Build Windows opt smoke targets (retry on transient fetch failure)
shell: pwsh
run: |
[string[]]$opt_targets = $env:WINDOWS_OPT_TARGETS -split '\s+' | Where-Object { $_ -ne '' }
$max = 3
for ($i = 1; $i -le $max; $i++) {
bazelisk build --config=opt --verbose_failures //...
bazelisk build --config=opt --disk_cache="$env:BAZEL_DISK_CACHE" --verbose_failures @opt_targets
if ($LASTEXITCODE -eq 0) { exit 0 }
if ($i -lt $max) {
Write-Host "Build failed (attempt $i/$max). Retrying in 20s..."
Expand All @@ -52,10 +85,6 @@ jobs:
}
exit 1

# Run all tests (including Python) — no retry so real test failures surface quickly
- name: Run all tests
run: bazelisk test --config=opt --verbose_failures //...

# Upload test logs
- name: Upload test logs - Windows
if: always()
Expand All @@ -65,3 +94,14 @@ jobs:
path: bazel-testlogs/
if-no-files-found: ignore
retention-days: 30

# Upload profile artifacts
- name: Upload Bazel profile - Windows
if: always()
uses: actions/upload-artifact@v6
with:
name: bazel-profile-windows
path: |
${{ github.workspace }}\windows-fastbuild-profile.json.gz
if-no-files-found: ignore
retention-days: 30
31 changes: 27 additions & 4 deletions python/tests/ci_windows_cppopts_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ def _bazelisk_invocation_has_config_opt(text: str, subcommand: str) -> bool:
return False


def _workflow_lines_with(text: str, needle: str) -> list[str]:
return [line for line in text.splitlines() if needle in line]


class TestWindowsMsvcCppoptsAvoidD9025(unittest.TestCase):
def test_windows_cppopts_do_not_override_bazel_optimization(self) -> None:
"""Bazel already sets /Od (fastbuild/dbg) or /O2 (opt); re-stating any
Expand Down Expand Up @@ -360,17 +364,36 @@ def test_matches_when_config_opt_precedes_trailing_comment(self) -> None:

class TestWindowsCiUsesOpt(unittest.TestCase):
def test_windows_ci_passes_config_opt(self) -> None:
"""Without /O2 in DDS_CPPOPTS, CI must opt in via --config=opt."""
"""Windows CI keeps opt only for a focused release validation step."""
text = (
_repo_root() / ".github" / "workflows" / "ci_windows.yml"
).read_text(encoding="utf-8")
self.assertFalse(
_bazelisk_invocation_has_config_opt(text, "test"),
"expected broad Windows test coverage to run in fastbuild",
)
self.assertTrue(
_bazelisk_invocation_has_config_opt(text, "build"),
"expected Windows CI build to use --config=opt",
"expected a focused Windows build step to keep --config=opt",
)

def test_windows_ci_limits_scope_and_collects_profile(self) -> None:
text = (
_repo_root() / ".github" / "workflows" / "ci_windows.yml"
).read_text(encoding="utf-8")
self.assertIn("WINDOWS_FASTBUILD_TARGETS", text)
self.assertNotIn("bazelisk fetch //...", text)
self.assertNotIn("bazelisk test --verbose_failures //...", text)
self.assertNotIn("bazelisk build --config=opt --verbose_failures //...", text)
self.assertRegex(
text,
r"actions/cache@v4",
"expected Windows workflow to enable cross-run Bazel caching",
)
test_lines = _workflow_lines_with(text, "bazelisk test")
self.assertTrue(
_bazelisk_invocation_has_config_opt(text, "test"),
"expected Windows CI test to use --config=opt",
any("--profile=" in line for line in test_lines),
"expected Windows test command to emit a Bazel profile",
)


Expand Down
Loading