-
Notifications
You must be signed in to change notification settings - Fork 2
164 lines (141 loc) · 6.76 KB
/
Copy pathbuild.yml
File metadata and controls
164 lines (141 loc) · 6.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
name: Build Windows Installer
on:
push:
tags: ['v*']
workflow_dispatch: # 允许手动触发
permissions:
contents: write
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Setup Python (for the sidecar syntax gate)
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
shell: pwsh
run: |
npm cache clean --force
if (Test-Path release) { Remove-Item -Recurse -Force release }
if (Test-Path node_modules/.cache) { Remove-Item -Recurse -Force node_modules/.cache }
# electron-builder caches app metadata (incl. version) across runs in
# ~/.cache/electron-builder — if a previous run baked version=0.2.10,
# the next installer gets named "0.2.10" even after we bump package.json.
# Wipe it explicitly so appInfo.version is recomputed from package.json.
if (Test-Path "$env:LOCALAPPDATA\electron-builder\Cache") { Remove-Item -Recurse -Force "$env:LOCALAPPDATA\electron-builder\Cache" }
if (Test-Path "$env:USERPROFILE\.cache\electron-builder") { Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\electron-builder" }
npm install
# ===== P63: real quality gates =====
# A tag push does NOT trigger ci.yml (see the note there), and lint/test here were
# continue-on-error — so releases went out entirely unguarded. These now FAIL the
# build: a broken release costs the user an install/uninstall cycle to discover.
# Python syntax first — the sidecar ships as extraResources, so nothing else in the
# toolchain reads it. One bad indent silently degrades the installed app to the VBS
# fallback engine, which is exactly how P36 reached a released installer.
- name: Sidecar syntax check
run: python -m compileall -q sidecar/sw_agent
- name: Sidecar lint + tests
run: |
pip install --quiet ruff pytest
ruff check sidecar/
pytest sidecar/tests -q
- name: Typecheck
run: npm run typecheck
- name: Lint
run: npm run lint
- name: Test
run: npm test
# P12: download the bundled Python embeddable + install pywin32/pillow into
# vendor/python/ before electron-builder runs. Idempotent — safe to re-run.
# This is a build-time network op; end users have no network requirement.
- name: Prepare bundled Python runtime
if: startsWith(github.ref, 'refs/tags/')
shell: pwsh
run: ./scripts/prepare-python.ps1
- name: Build
run: npm run build
# P110: NSIS setup retired (2026-08-04) — users found the installer repeatedly
# unusable, so tag builds now ship ONLY the portable single-file exe.
# npm run dist = prepare-python + build + electron-builder (target: portable
# from electron-builder.yml) → release/Millwright-Portable-<ver>-x64.exe
- name: Package (portable / 免安装版)
if: startsWith(github.ref, 'refs/tags/')
run: npm run dist
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# P63: verify what actually landed in the package. We have shipped an installer
# whose bundled sidecar was stale, and another with no Python runtime at all —
# both only surfaced after a user installed it. This check takes seconds and makes
# that class of accident impossible. It also confirms the installer filename carries
# the version from package.json (the old electron-builder cache bug).
- name: Verify packaged payload
if: startsWith(github.ref, 'refs/tags/')
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$res = 'release/win-unpacked/resources'
$version = (Get-Content package.json -Raw | ConvertFrom-Json).version
Write-Host "package.json version: ${version}"
$required = @(
"$res/sidecar/sw_agent/server.py",
"$res/sidecar/sw_agent/bridge.py",
"$res/sidecar/sw_agent/registry.py",
"$res/sidecar/sw_agent/tools/feature.py",
"$res/sidecar/sw_agent/tools/sketch.py",
"$res/sidecar/sw_agent/tools/batch.py",
"$res/sidecar/sw_agent/tools/drawing.py",
"$res/sidecar/sw_agent/tools/machine.py",
"$res/python/python.exe",
"$res/python/Lib/site-packages/win32com",
"$res/python/Lib/site-packages/PIL"
)
$missing = @($required | Where-Object { -not (Test-Path $_) })
if ($missing.Count -gt 0) {
Write-Host "::error::Packaged payload is incomplete:"
$missing | ForEach-Object { Write-Host "::error:: missing $_" }
exit 1
}
Write-Host "sidecar + bundled Python runtime: OK"
# the sidecar inside the package must match the sidecar in the repo
$repoPy = Get-ChildItem sidecar/sw_agent -Recurse -Filter *.py | ForEach-Object { $_.Name } | Sort-Object
$pkgPy = Get-ChildItem "$res/sidecar/sw_agent" -Recurse -Filter *.py | ForEach-Object { $_.Name } | Sort-Object
$diff = Compare-Object $repoPy $pkgPy
if ($diff) {
Write-Host "::error::Packaged sidecar differs from the repo:"
$diff | ForEach-Object { Write-Host "::error:: $($_.SideIndicator) $($_.InputObject)" }
exit 1
}
Write-Host "packaged sidecar matches the repo ($($repoPy.Count) modules): OK"
# the archive must be named for the version we just built
$zip = Get-ChildItem release/*.zip | Select-Object -First 1
Write-Host "archive: $($zip.Name)"
if ($zip.Name -notmatch [regex]::Escape($version)) {
Write-Host "::error::Archive name lacks version ${version} — stale electron-builder cache?"
exit 1
}
Write-Host "archive name carries ${version}: OK"
# P110 v3: extract-and-run zip (nsis + portable exe both retired).
# npm run dist with the zip target produces release/*.zip containing the
# full win-unpacked tree — download, extract, run Millwright.exe.
- name: Upload artifact (portable directory)
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v7
with:
name: Millwright
path: release/win-unpacked/**
retention-days: 30
- name: Create Release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v3
with:
files: release/*.zip
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}