1+ name : " ML-CI-Win"
2+ on :
3+ push :
4+ tags :
5+ - v*.*.*
6+ pull_request :
7+ branches :
8+ - main
9+ schedule :
10+ - cron : " 0 10 * * *" # Run at 2am PST (10am UTC) every day to refresh the cache.
11+ workflow_dispatch : # Manual trigger
12+ inputs :
13+ REFRESH_CACHE :
14+ description : ' Refresh cache to remove unused files'
15+ type : boolean
16+ default : true
17+ halt-for-connection :
18+ description : ' Should this workflow run wait for a remote connection?'
19+ type : choice
20+ required : true
21+ default : ' yes'
22+ options :
23+ - ' yes'
24+ - ' no'
25+
26+ concurrency :
27+ group : ${{ github.workflow }}-${{ github.head_ref || github.ref }}
28+ cancel-in-progress : true
29+
30+ jobs :
31+ presubmit :
32+ name : " Presubmit-Win"
33+ runs-on : windows-x86-n2-16
34+ defaults :
35+ run :
36+ shell : powershell
37+ permissions :
38+ actions : write # For gh cache delete.
39+ contents : write # For gh release upload.
40+ env :
41+ MODEL_KEY : gemma-3-1b-it-v1
42+ MODEL_PATH : .\models\gemma3-1b-it-int4.litertlm
43+ MODEL_URL : https://huggingface.co/litert-community/Gemma3-1B-IT/resolve/main/gemma3-1b-it-int4.litertlm
44+
45+ # Clear ANDROID_NDK_HOME as Windows_x64 has NDK where jobs don't have permission for
46+ # androidndk rules to create symlinks.
47+ ANDROID_NDK_HOME :
48+ GH_TOKEN : ${{ github.token }} # For gh release upload.
49+ REFRESH_CACHE : ${{ github.event_name == 'schedule' ||
50+ (github.event_name == 'workflow_dispatch' && inputs.REFRESH_CACHE) }}
51+ steps :
52+ - name : Wait For Connection
53+ uses : google-ml-infra/actions/ci_connection@7f5ca0c263a81ed09ea276524c1b9192f1304e3c
54+ with :
55+ halt-dispatch-input : ${{ inputs.halt-for-connection }}
56+
57+ - name : Install System Dependencies
58+ run : |
59+ [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
60+ Set-ExecutionPolicy Bypass -Scope Process -Force
61+ Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
62+
63+ # Temporarily add choco to this step's path so the installer below functions
64+ $env:Path += ";$env:ALLUSERSPROFILE\chocolatey\bin"
65+
66+ $env:JAVA_HOME = [System.Environment]::GetEnvironmentVariable("JAVA_HOME", "Machine")
67+
68+ choco install git make pkgconfiglite openjdk17 ccache bazelisk -y
69+
70+ python -m pip install --break-system-packages numpy
71+
72+ - name : Configure System Paths
73+ run : |
74+ Add-Content -Path $env:GITHUB_PATH -Value "C:\Program Files\Git\cmd"
75+ Add-Content -Path $env:GITHUB_PATH -Value "$env:ALLUSERSPROFILE\chocolatey\bin"
76+ Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.cargo\bin"
77+
78+ - name : Setup VCPKG
79+ run : |
80+ git clone https://github.com/microsoft/vcpkg.git $env:USERPROFILE\vcpkg
81+ cd $env:USERPROFILE\vcpkg
82+ .\bootstrap-vcpkg.bat -disableMetrics
83+ .\vcpkg integrate install
84+ .\vcpkg install zlib openssl libpng curl fftw3 --triplet x64-windows
85+
86+ - name : Install Rust
87+ run : |
88+ Invoke-WebRequest -Uri "https://win.rustup.rs" -OutFile "rustup-init.exe"
89+ .\rustup-init.exe -y --default-host x86_64-pc-windows-msvc
90+
91+ - name : Checkout code
92+ uses : actions/checkout@v4
93+ with :
94+ lfs : true
95+
96+ - name : Set up cache keys and bazel output base
97+ id : cache-keys
98+ run : |
99+ $BAZEL_OUTPUT_BASE = "C:/w"
100+ if ($env:GITHUB_WORKSPACE -match "^[Dd]:") {
101+ $BAZEL_OUTPUT_BASE = "D:/w"
102+ }
103+ $CACHE_RESTORE_KEY_2="${{ github.workflow }}"
104+ $CACHE_RESTORE_KEY_1="$CACHE_RESTORE_KEY_2-${{ hashFiles('**/WORKSPACE', '**/.bazelrc') }}"
105+ $CACHE_RESTORE_KEY_0="$CACHE_RESTORE_KEY_1-${{ hashFiles('**/BUILD*') }}"
106+ # If it's not a pull request, then it will be the same as $CACHE_RESTORE_KEY_1-.
107+ $CACHE_RESTORE_KEY_HEAD="$CACHE_RESTORE_KEY_0-${{ github.event.pull_request.base.sha }}"
108+ $CACHE_KEY="$CACHE_RESTORE_KEY_0-${{ github.sha }}"
109+
110+ echo "CACHE_RESTORE_KEY_2=$CACHE_RESTORE_KEY_2" >> "$env:GITHUB_OUTPUT"
111+ echo "CACHE_RESTORE_KEY_1=$CACHE_RESTORE_KEY_1" >> "$env:GITHUB_OUTPUT"
112+ echo "CACHE_RESTORE_KEY_0=$CACHE_RESTORE_KEY_0" >> "$env:GITHUB_OUTPUT"
113+ echo "CACHE_RESTORE_KEY_HEAD=$CACHE_RESTORE_KEY_HEAD" >> "$env:GITHUB_OUTPUT"
114+ echo "CACHE_KEY=$CACHE_KEY" >> "$env:GITHUB_OUTPUT"
115+
116+ # D: is faster than C: for I/O.
117+ $SHORT_SHA=$("${{ github.sha }}".SubString(0, 8))
118+ echo "BAZEL_OUTPUT_BASE=${BAZEL_OUTPUT_BASE}-$SHORT_SHA" >> "$env:GITHUB_ENV"
119+
120+ - name : Clean build outputs if cache is being refreshed
121+ if : env.REFRESH_CACHE == 'true'
122+ run : bazel --output_base="$env:BAZEL_OUTPUT_BASE" clean --expunge
123+
124+ - name : Restore bazel cache if cache is not being refreshed
125+ id : bazel-cache
126+ if : env.REFRESH_CACHE != 'true'
127+ uses : actions/cache/restore@v4
128+ with :
129+ path : |
130+ ~/.cache/bazel-windows
131+ ~/.cache/bazel-windows-dll
132+ key : ${{ steps.cache-keys.outputs.CACHE_KEY }}
133+ restore-keys : |
134+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_HEAD }}
135+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_0 }}-
136+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_1 }}-
137+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_2 }}-
138+
139+ - name : Check cache hit
140+ run : |
141+ echo "Cache Hit: ${{ steps.bazel-cache.outputs.cache-hit }}"
142+ echo "Cache Primary Key: ${{ steps.bazel-cache.outputs.cache-primary-key }}"
143+ echo "Cache Matched Key: ${{ steps.bazel-cache.outputs.cache-matched-key }}"
144+
145+ - name : Download Model
146+ env :
147+ HF_TOKEN : ${{ secrets.HF_TOKEN }}
148+ run : |
149+ if (-not (Test-Path "./models")) {
150+ New-Item -ItemType Directory -Path "./models" -Force
151+ }
152+
153+ $headers = @{
154+ "Authorization" = "Bearer $($env:HF_TOKEN)"
155+ }
156+
157+ Write-Host "Downloading model from Hugging Face: ${{ env.MODEL_URL }}"
158+
159+ Invoke-WebRequest -Uri "${{ env.MODEL_URL }}" `
160+ -Headers $headers `
161+ -OutFile "${{ env.MODEL_PATH }}"
162+
163+ $file = Get-Item "${{ env.MODEL_PATH }}"
164+ $sizeMB = [math]::Round($file.Length / 1MB, 2)
165+ Write-Host "Verification Success: $($file.Name) ($sizeMB MB) is ready."
166+ Get-ChildItem "${{ env.MODEL_PATH }}" | Select-Object Name, @{Name="Size(MB)";Expression={$_.Length / 1MB}}
167+
168+
169+ - name : Run bazel build on Windows
170+ run : |
171+ bazel --output_base="$env:BAZEL_OUTPUT_BASE" `
172+ build --disk_cache=~/.cache/bazel-windows `
173+ --build_tag_filters='-nowindows' `
174+ -- `
175+ //... `
176+ //runtime/engine:litert_lm_main `
177+ -//kotlin/...
178+
179+ - name : Update litert_lm_main prebuilt for Windows if new version tag is pushed
180+ if : github.ref_type == 'tag'
181+ run : |
182+ cp bazel-bin/runtime/engine/litert_lm_main.exe litert_lm_main.windows_x86_64.exe
183+ gh release upload ${{ github.ref_name }} litert_lm_main.windows_x86_64.exe --clobber
184+
185+ - name : Run bazel test on Windows
186+ run : |
187+ bazel --output_base="$env:BAZEL_OUTPUT_BASE" `
188+ test --disk_cache=~/.cache/bazel-windows --test_output=errors `
189+ --test_tag_filters='-requires-mac-inputs:hard,-nowindows' `
190+ -- `
191+ //... `
192+ -//kotlin/...
193+
194+ - name : Install pytest
195+ run : python -m pip install --break-system-packages pytest==8.3.4
196+
197+ - name : Run pytest
198+ # Execute pytest via the python module (-m) to bypass missing pytest.exe PATH issues
199+ run : python -m pytest tools/test/ --model-path=${{ env.MODEL_PATH }} --build-system=bazel
200+
201+ - name : Run bazel build on Windows with dynamic linking
202+ run : |
203+ bazel --output_base="$env:BAZEL_OUTPUT_BASE" `
204+ build --disk_cache=~/.cache/bazel-windows-dll `
205+ --define=litert_link_capi_so=true `
206+ --define=resolve_symbols_in_exec=false `
207+ //runtime/engine:litert_lm_main
208+
209+ - name : Remove cache if cache is being refreshed
210+ if : env.REFRESH_CACHE == 'true'
211+ continue-on-error : true # Ignore errors when cache is not found.
212+ run : gh cache delete ${{ steps.cache-keys.outputs.CACHE_KEY }}
213+
214+ - name : Save bazel cache if it's new or being refreshed
215+ uses : actions/cache/save@v4
216+ if : env.REFRESH_CACHE == 'true' || steps.bazel-cache.outputs.cache-hit != 'true'
217+ with :
218+ path : |
219+ ~/.cache/bazel-windows
220+ ~/.cache/bazel-windows-dll
221+ key : ${{ steps.cache-keys.outputs.CACHE_KEY }}
0 commit comments