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 : ' no'
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 : Install System Dependencies
53+ run : |
54+ [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
55+ Set-ExecutionPolicy Bypass -Scope Process -Force
56+ Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
57+
58+ # Temporarily add choco to this step's path so the installer below functions
59+ $env:Path += ";$env:ALLUSERSPROFILE\chocolatey\bin"
60+
61+ $env:JAVA_HOME = [System.Environment]::GetEnvironmentVariable("JAVA_HOME", "Machine")
62+
63+ choco install git make pkgconfiglite openjdk17 ccache bazelisk -y
64+
65+ python -m pip install --break-system-packages numpy
66+
67+ - name : Configure System Paths
68+ run : |
69+ Add-Content -Path $env:GITHUB_PATH -Value "C:\Program Files\Git\cmd"
70+ Add-Content -Path $env:GITHUB_PATH -Value "$env:ALLUSERSPROFILE\chocolatey\bin"
71+ Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.cargo\bin"
72+
73+ - name : Setup VCPKG
74+ run : |
75+ git clone https://github.com/microsoft/vcpkg.git $env:USERPROFILE\vcpkg
76+ cd $env:USERPROFILE\vcpkg
77+ .\bootstrap-vcpkg.bat -disableMetrics
78+ .\vcpkg integrate install
79+ .\vcpkg install zlib openssl libpng curl fftw3 --triplet x64-windows
80+
81+ - name : Install Rust
82+ run : |
83+ Invoke-WebRequest -Uri "https://win.rustup.rs" -OutFile "rustup-init.exe"
84+ .\rustup-init.exe -y --default-host x86_64-pc-windows-msvc
85+
86+ - name : Checkout code
87+ uses : actions/checkout@v4
88+ with :
89+ lfs : true
90+
91+ - name : Set up cache keys and bazel output base
92+ id : cache-keys
93+ run : |
94+ $BAZEL_OUTPUT_BASE = "C:/w"
95+ if ($env:GITHUB_WORKSPACE -match "^[Dd]:") {
96+ $BAZEL_OUTPUT_BASE = "D:/w"
97+ }
98+ $CACHE_RESTORE_KEY_2="${{ github.workflow }}"
99+ $CACHE_RESTORE_KEY_1="$CACHE_RESTORE_KEY_2-${{ hashFiles('**/WORKSPACE', '**/.bazelrc') }}"
100+ $CACHE_RESTORE_KEY_0="$CACHE_RESTORE_KEY_1-${{ hashFiles('**/BUILD*') }}"
101+ # If it's not a pull request, then it will be the same as $CACHE_RESTORE_KEY_1-.
102+ $CACHE_RESTORE_KEY_HEAD="$CACHE_RESTORE_KEY_0-${{ github.event.pull_request.base.sha }}"
103+ $CACHE_KEY="$CACHE_RESTORE_KEY_0-${{ github.sha }}"
104+
105+ echo "CACHE_RESTORE_KEY_2=$CACHE_RESTORE_KEY_2" >> "$env:GITHUB_OUTPUT"
106+ echo "CACHE_RESTORE_KEY_1=$CACHE_RESTORE_KEY_1" >> "$env:GITHUB_OUTPUT"
107+ echo "CACHE_RESTORE_KEY_0=$CACHE_RESTORE_KEY_0" >> "$env:GITHUB_OUTPUT"
108+ echo "CACHE_RESTORE_KEY_HEAD=$CACHE_RESTORE_KEY_HEAD" >> "$env:GITHUB_OUTPUT"
109+ echo "CACHE_KEY=$CACHE_KEY" >> "$env:GITHUB_OUTPUT"
110+
111+ # D: is faster than C: for I/O.
112+ $SHORT_SHA=$("${{ github.sha }}".SubString(0, 8))
113+ echo "BAZEL_OUTPUT_BASE=${BAZEL_OUTPUT_BASE}-$SHORT_SHA" >> "$env:GITHUB_ENV"
114+
115+ - name : Clean build outputs if cache is being refreshed
116+ if : env.REFRESH_CACHE == 'true'
117+ run : bazel --output_base="$env:BAZEL_OUTPUT_BASE" clean --expunge
118+
119+ - name : Restore bazel cache if cache is not being refreshed
120+ id : bazel-cache
121+ if : env.REFRESH_CACHE != 'true'
122+ uses : actions/cache/restore@v4
123+ with :
124+ path : |
125+ ~/.cache/bazel-windows
126+ ~/.cache/bazel-windows-dll
127+ key : ${{ steps.cache-keys.outputs.CACHE_KEY }}
128+ restore-keys : |
129+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_HEAD }}
130+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_0 }}-
131+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_1 }}-
132+ ${{ steps.cache-keys.outputs.CACHE_RESTORE_KEY_2 }}-
133+
134+ - name : Check cache hit
135+ run : |
136+ echo "Cache Hit: ${{ steps.bazel-cache.outputs.cache-hit }}"
137+ echo "Cache Primary Key: ${{ steps.bazel-cache.outputs.cache-primary-key }}"
138+ echo "Cache Matched Key: ${{ steps.bazel-cache.outputs.cache-matched-key }}"
139+
140+ - name : Download Model
141+ env :
142+ HF_TOKEN : ${{ secrets.HF_TOKEN }}
143+ run : |
144+ if (-not (Test-Path "./models")) {
145+ New-Item -ItemType Directory -Path "./models" -Force
146+ }
147+
148+ $headers = @{
149+ "Authorization" = "Bearer $($env:HF_TOKEN)"
150+ }
151+
152+ Write-Host "Downloading model from Hugging Face: ${{ env.MODEL_URL }}"
153+
154+ Invoke-WebRequest -Uri "${{ env.MODEL_URL }}" `
155+ -Headers $headers `
156+ -OutFile "${{ env.MODEL_PATH }}"
157+
158+ $file = Get-Item "${{ env.MODEL_PATH }}"
159+ $sizeMB = [math]::Round($file.Length / 1MB, 2)
160+ Write-Host "Verification Success: $($file.Name) ($sizeMB MB) is ready."
161+ Get-ChildItem "${{ env.MODEL_PATH }}" | Select-Object Name, @{Name="Size(MB)";Expression={$_.Length / 1MB}}
162+
163+ - name : Wait For Connection
164+ uses : google-ml-infra/actions/ci_connection@7f5ca0c263a81ed09ea276524c1b9192f1304e3c
165+ with :
166+ halt-dispatch-input : ${{ inputs.halt-for-connection }}
167+
168+ - name : Run bazel build on Windows
169+ run : |
170+ bazel --output_base="$env:BAZEL_OUTPUT_BASE" `
171+ build --disk_cache=~/.cache/bazel-windows `
172+ --build_tag_filters='-nowindows' `
173+ -- `
174+ //... `
175+ //runtime/engine:litert_lm_main `
176+ -//kotlin/...
177+
178+ - name : Update litert_lm_main prebuilt for Windows if new version tag is pushed
179+ if : github.ref_type == 'tag'
180+ run : |
181+ cp bazel-bin/runtime/engine/litert_lm_main.exe litert_lm_main.windows_x86_64.exe
182+ gh release upload ${{ github.ref_name }} litert_lm_main.windows_x86_64.exe --clobber
183+
184+ - name : Run bazel test on Windows
185+ run : |
186+ bazel --output_base="$env:BAZEL_OUTPUT_BASE" `
187+ test --disk_cache=~/.cache/bazel-windows --test_output=errors `
188+ --test_tag_filters='-requires-mac-inputs:hard,-nowindows' `
189+ -- `
190+ //... `
191+ -//kotlin/...
192+
193+ - name : Install pytest
194+ run : python -m pip install --break-system-packages pytest==8.3.4
195+
196+ - name : Run pytest
197+ # Execute pytest via the python module (-m) to bypass missing pytest.exe PATH issues
198+ run : python -m pytest tools/test/ --model-path=${{ env.MODEL_PATH }} --build-system=bazel
199+
200+ - name : Run bazel build on Windows with dynamic linking
201+ run : |
202+ bazel --output_base="$env:BAZEL_OUTPUT_BASE" `
203+ build --disk_cache=~/.cache/bazel-windows-dll `
204+ --define=litert_link_capi_so=true `
205+ --define=resolve_symbols_in_exec=false `
206+ //runtime/engine:litert_lm_main
207+
208+ - name : Remove cache if cache is being refreshed
209+ if : env.REFRESH_CACHE == 'true'
210+ continue-on-error : true # Ignore errors when cache is not found.
211+ run : gh cache delete ${{ steps.cache-keys.outputs.CACHE_KEY }}
212+
213+ - name : Save bazel cache if it's new or being refreshed
214+ uses : actions/cache/save@v4
215+ if : env.REFRESH_CACHE == 'true' || steps.bazel-cache.outputs.cache-hit != 'true'
216+ with :
217+ path : |
218+ ~/.cache/bazel-windows
219+ ~/.cache/bazel-windows-dll
220+ key : ${{ steps.cache-keys.outputs.CACHE_KEY }}
0 commit comments