Skip to content

Commit 37d2064

Browse files
ai-edge-botcopybara-github
authored andcommitted
Update CI-Win build environment and runner.
LiteRT-LM-PiperOrigin-RevId: 907807277
1 parent 4541df0 commit 37d2064

1 file changed

Lines changed: 221 additions & 0 deletions

File tree

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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

Comments
 (0)