Skip to content

Commit e5b7fdd

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

1 file changed

Lines changed: 220 additions & 0 deletions

File tree

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

Comments
 (0)