Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
081084a
feat: scaffold windows WSL installer flow
vavo Mar 27, 2026
06a821c
fix: harden windows launcher build inputs
vavo Mar 27, 2026
2ef0185
fix: publish preview windows installer assets
vavo Mar 27, 2026
c22192e
fix: decouple branch installer checks from release assets
vavo Mar 27, 2026
0d90829
fix: harden runtime bootstrap downloads
vavo Mar 27, 2026
ea8d4c8
docs: mark windows installer as preview
vavo Mar 27, 2026
a3f2931
fix: harden windows preview installer flow
vavo Apr 1, 2026
3951926
chore: upgrade GitHub actions runtime versions
vavo Apr 1, 2026
aba0390
chore: publish preview tags as prereleases
vavo Apr 1, 2026
4703bf3
docs: add windows preview release template
vavo Apr 1, 2026
a226ab6
fix: sequence tagged installer builds after runtime publish
vavo Apr 1, 2026
c6c4896
feat: add windows code signing support
vavo Apr 1, 2026
f5acbc9
feat: publish windows runtime bundles to R2
vavo Apr 2, 2026
92de491
feat: improve windows web installer flow
vavo Apr 2, 2026
2bce93e
fix: split windows runtime release publish from build
vavo Apr 4, 2026
9d94f5c
fix: harden windows installer release validation
vavo Apr 4, 2026
0217850
fix: use curl for installer asset probes
vavo Apr 4, 2026
8e01689
fix: stop probing external installer assets in CI
vavo Apr 4, 2026
f7a4a15
fix: simplify installer auto-install guard
vavo Apr 5, 2026
a4788d8
fix: make runtime CDN validation non-blocking
vavo Apr 6, 2026
8e7315c
fix: send browser-like headers for runtime downloads
vavo Apr 6, 2026
0112ab5
fix: use curl for windows runtime downloads
vavo Apr 6, 2026
eba2992
fix: clear stale WSL import paths before install
vavo Apr 6, 2026
07f2579
docs: improve windows preview release guide
vavo Apr 6, 2026
8933c9c
installer setup now gets a real staged progress UI , launcher now reu…
vavo Apr 7, 2026
03f8898
fix: keep installer website link buildable
vavo Apr 7, 2026
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
58 changes: 58 additions & 0 deletions .github/workflows/windows-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Windows Installer E2E

on:
workflow_dispatch:
inputs:
manifest_url:
description: Runtime manifest URL to test against
required: true
type: string

permissions:
contents: read

jobs:
e2e:
runs-on:
- self-hosted
- windows
- x64
- lora-pilot-e2e
steps:
- name: Check out source
uses: actions/checkout@v5

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: "1.22"

- name: Install Inno Setup
shell: powershell
run: choco install innosetup --no-progress -y

- name: Build installer from source
shell: powershell
run: .\packaging\windows\build-installer.ps1 -AppVersion "e2e-$($env:GITHUB_SHA.Substring(0, 12))" -ManifestUrl "${{ inputs.manifest_url }}"

- name: Run silent installer
shell: powershell
run: Start-Process -FilePath .\dist\windows-installer\LoRAPilotSetup.exe -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES" -Wait -NoNewWindow

- name: Verify launcher status
shell: powershell
run: |
& "$env:LOCALAPPDATA\Programs\LoRAPilot\LoRAPilotLauncher.exe" status --json

- name: Start runtime and verify health
shell: powershell
run: |
& "$env:LOCALAPPDATA\Programs\LoRAPilot\LoRAPilotLauncher.exe" start
Invoke-RestMethod -Uri http://127.0.0.1:7878/healthz | ConvertTo-Json

- name: Stop runtime and purge test install
if: always()
shell: powershell
run: |
& "$env:LOCALAPPDATA\Programs\LoRAPilot\LoRAPilotLauncher.exe" stop
& "$env:LOCALAPPDATA\Programs\LoRAPilot\LoRAPilotLauncher.exe" uninstall --purge
400 changes: 400 additions & 0 deletions .github/workflows/windows-installer.yml

Large diffs are not rendered by default.

201 changes: 201 additions & 0 deletions .github/workflows/wsl-runtime-artifacts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
name: Build WSL Runtime Artifacts

on:
push:
branches:
- feat/windows-wsl-installer
tags:
- "v*"
workflow_dispatch:

permissions:
contents: write

jobs:
build-runtime:
runs-on: ubuntu-latest
env:
WINDOWS_RUNTIME_PUBLIC_BASE_URL: ${{ vars.WINDOWS_RUNTIME_PUBLIC_BASE_URL }}
WINDOWS_RUNTIME_R2_BUCKET: ${{ vars.WINDOWS_RUNTIME_R2_BUCKET }}
WINDOWS_RUNTIME_R2_ENDPOINT: ${{ vars.WINDOWS_RUNTIME_R2_ENDPOINT }}
WINDOWS_RUNTIME_R2_PREFIX: ${{ vars.WINDOWS_RUNTIME_R2_PREFIX }}
WINDOWS_RUNTIME_R2_ACCESS_KEY_ID: ${{ secrets.WINDOWS_RUNTIME_R2_ACCESS_KEY_ID }}
WINDOWS_RUNTIME_R2_SECRET_ACCESS_KEY: ${{ secrets.WINDOWS_RUNTIME_R2_SECRET_ACCESS_KEY }}
steps:
- name: Check out source
uses: actions/checkout@v5

- name: Set release metadata
shell: bash
run: |
tag_build="false"
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
app_version="${GITHUB_REF_NAME}"
tag_build="true"
else
app_version="sha-${GITHUB_SHA::12}"
fi
echo "APP_VERSION=${app_version}" >> "${GITHUB_ENV}"
echo "RUNTIME_VERSION=${app_version}" >> "${GITHUB_ENV}"
echo "TAG_BUILD=${tag_build}" >> "${GITHUB_ENV}"
if [[ "${tag_build}" == "true" ]]; then
if [[ -z "${WINDOWS_RUNTIME_R2_PREFIX}" ]]; then
runtime_prefix="windows-runtime"
else
runtime_prefix="${WINDOWS_RUNTIME_R2_PREFIX%/}"
fi
echo "RUNTIME_R2_PREFIX=${runtime_prefix}" >> "${GITHUB_ENV}"
runtime_base_url="${WINDOWS_RUNTIME_PUBLIC_BASE_URL%/}/${runtime_prefix}/${app_version}"
echo "RUNTIME_BASE_URL=${runtime_base_url}" >> "${GITHUB_ENV}"
else
echo "RUNTIME_BASE_URL=https://github.com/${GITHUB_REPOSITORY}/releases/download/${app_version}" >> "${GITHUB_ENV}"
fi
prerelease="false"
if [[ "${app_version}" == *preview* || "${app_version}" == *alpha* || "${app_version}" == *beta* || "${app_version}" == *rc* ]]; then
prerelease="true"
fi
echo "RELEASE_IS_PRERELEASE=${prerelease}" >> "${GITHUB_ENV}"

- name: Validate R2 release configuration
if: env.TAG_BUILD == 'true'
shell: bash
run: |
missing=()
for var_name in \
WINDOWS_RUNTIME_PUBLIC_BASE_URL \
WINDOWS_RUNTIME_R2_BUCKET \
WINDOWS_RUNTIME_R2_ENDPOINT \
WINDOWS_RUNTIME_R2_ACCESS_KEY_ID \
WINDOWS_RUNTIME_R2_SECRET_ACCESS_KEY
do
if [[ -z "${!var_name:-}" ]]; then
missing+=("${var_name}")
fi
done
if (( ${#missing[@]} > 0 )); then
printf 'Missing required R2 config for tagged release: %s\n' "${missing[*]}" >&2
exit 1
fi
if [[ "${WINDOWS_RUNTIME_PUBLIC_BASE_URL}" == *".r2.cloudflarestorage.com"* ]]; then
echo "WINDOWS_RUNTIME_PUBLIC_BASE_URL must be a public r2.dev URL or custom domain, not the S3 API endpoint." >&2
exit 1
fi

- name: Build runtime artifacts
shell: bash
run: bash packaging/windows/build-runtime-artifacts.sh

- name: Upload runtime artifacts
uses: actions/upload-artifact@v6
with:
name: windows-runtime-artifacts
path: dist/windows-runtime/*

- name: Install AWS CLI
if: env.TAG_BUILD == 'true'
shell: bash
run: |
if command -v aws >/dev/null 2>&1; then
aws --version
exit 0
fi
python3 -m pip install --user awscli
echo "${HOME}/.local/bin" >> "${GITHUB_PATH}"

- name: Publish runtime bundles to Cloudflare R2
if: env.TAG_BUILD == 'true'
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ env.WINDOWS_RUNTIME_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ env.WINDOWS_RUNTIME_R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
run: |
r2_path="s3://${WINDOWS_RUNTIME_R2_BUCKET}/${RUNTIME_R2_PREFIX}/${APP_VERSION}/"
aws --endpoint-url "${WINDOWS_RUNTIME_R2_ENDPOINT}" s3 cp dist/windows-runtime/ "${r2_path}" \
--recursive \
--exclude "*" \
--include "*.tar.zst" \
--include "*.sha256"

publish-runtime-release:
if: startsWith(github.ref, 'refs/tags/')
needs:
- build-runtime
runs-on: ubuntu-latest
steps:
- name: Set release metadata
shell: bash
run: |
prerelease="false"
if [[ "${GITHUB_REF_NAME}" == *preview* || "${GITHUB_REF_NAME}" == *alpha* || "${GITHUB_REF_NAME}" == *beta* || "${GITHUB_REF_NAME}" == *rc* ]]; then
prerelease="true"
fi
echo "RELEASE_IS_PRERELEASE=${prerelease}" >> "${GITHUB_ENV}"

- name: Download runtime artifacts
uses: actions/download-artifact@v5
with:
name: windows-runtime-artifacts
path: dist/windows-runtime

- name: Validate public runtime bundle URLs
id: validate_runtime_urls
continue-on-error: true
shell: bash
run: |
python3 - <<'PY'
import json
import os
import subprocess
import sys
import time

manifest_path = os.path.join("dist", "windows-runtime", "windows-runtime-manifest.json")
with open(manifest_path, "r", encoding="utf-8") as handle:
manifest = json.load(handle)

for url in (manifest["fresh_install"]["url"], manifest["upgrade_overlay"]["url"]):
for attempt in range(1, 13):
probe = subprocess.run(
[
"curl",
"--silent",
"--show-error",
"--fail",
"--location",
"--range",
"0-0",
"--output",
"/dev/null",
"--write-out",
"%{http_code}",
url,
],
capture_output=True,
text=True,
)
status = probe.stdout.strip()
if probe.returncode == 0 and status in {"200", "206"}:
print(f"Validated {url} with HTTP {status}")
break
detail = probe.stderr.strip() or status or f"curl exited with {probe.returncode}"
if attempt == 12:
print(f"Public runtime URL validation failed for {url}: {detail}", file=sys.stderr)
raise SystemExit(1)
time.sleep(10)
PY

- name: Warn when public runtime URL validation is flaky
if: steps.validate_runtime_urls.outcome == 'failure'
shell: bash
run: |
echo "Public runtime URL validation failed from the GitHub runner, but runtime bundles were already uploaded to R2." >&2
echo "Continuing with release publishing instead of blocking on CDN runner-specific 403 responses." >&2

- name: Publish runtime release assets
uses: softprops/action-gh-release@v2
with:
prerelease: ${{ env.RELEASE_IS_PRERELEASE == 'true' }}
files: |
dist/windows-runtime/windows-runtime-manifest.json
dist/windows-runtime/*.sha256
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04

ARG BUILDPLATFORM
ARG TARGETPLATFORM
ARG APP_VERSION=dev
ARG RUNTIME_VERSION=dev
ARG VCS_REF=unknown
ARG BUILD_DATE=unknown

ENV DEBIAN_FRONTEND=noninteractive \
TZ=Etc/UTC \
Expand All @@ -18,6 +22,10 @@ ENV DEBIAN_FRONTEND=noninteractive \
HF_HUB_ENABLE_HF_TRANSFER=1 \
HF_XET_HIGH_PERFORMANCE=1 \
UMASK=0022
ENV LORA_PILOT_APP_VERSION="${APP_VERSION}" \
LORA_PILOT_RUNTIME_VERSION="${RUNTIME_VERSION}" \
LORA_PILOT_VCS_REF="${VCS_REF}" \
LORA_PILOT_BUILD_DATE="${BUILD_DATE}"

ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
Expand Down Expand Up @@ -116,6 +124,7 @@ COPY apps /opt/pilot/apps
COPY docs /opt/pilot/docs
COPY README.md /opt/pilot/README.md
COPY CHANGELOG /opt/pilot/CHANGELOG
RUN /opt/pilot/build/write-runtime-version.sh

EXPOSE 7878 8888 8443 5555 6666 9090 4444 8675

Expand Down
Loading
Loading