@@ -196,3 +196,152 @@ jobs:
196196 files : ./release-packages/*
197197 tag_name : v${{ env.VERSION }}
198198 name : v${{ env.VERSION }}
199+
200+ package-windows :
201+ name : win32-x64
202+ runs-on : windows-2022
203+ if : >-
204+ (github.event_name == 'workflow_dispatch') ||
205+ (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
206+
207+ defaults :
208+ run :
209+ shell : bash
210+
211+ env :
212+ VSCODE_TARGET : win32-x64
213+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
214+ TAG : ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
215+ # Ensure native modules are built from source to avoid prebuilds.
216+ npm_config_build_from_source : true
217+ OS : windows
218+
219+ steps :
220+ # Git rewrites line endings on windows by default, which turns every
221+ # shell script the build is made of into one bash cannot read, and
222+ # every name in patches/series into one with a stray return.
223+ - name : Keep line endings as they are in the repository
224+ run : git config --global core.autocrlf false
225+
226+ - name : Strip update/ and v from tag and set major version
227+ run : |
228+ version=${TAG#update/}
229+ version=${version#v}
230+ version=4${version:1}
231+ echo "VERSION=$version" >> $GITHUB_ENV
232+
233+ - uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
234+ with :
235+ submodules : true
236+
237+ # quilt has no windows build. The patches are ordinary -p1 diffs
238+ # against the repository root, so git applies them in series order.
239+ - name : Apply patches
240+ run : |
241+ while read -r patch; do
242+ case "$patch" in '' | '#'*) continue ;; esac
243+ echo "applying $patch"
244+ git apply --whitespace=nowarn "patches/$patch"
245+ done < patches/series
246+
247+ - uses : actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
248+ with :
249+ node-version-file : .node-version
250+ cache : npm
251+ cache-dependency-path : |
252+ package-lock.json
253+ test/package-lock.json
254+
255+ # npm hands every script it runs to cmd, which cannot run the shell
256+ # scripts this repository is built out of. Point it at the same bash
257+ # the steps here use rather than at a path, which moves between
258+ # images.
259+ - name : Let npm run shell scripts
260+ run : echo "npm_config_script_shell=$(cygpath -w "$(command -v bash)")" >> $GITHUB_ENV
261+
262+ # The build merges json by handing jq a process substitution, which
263+ # bash presents as a file under /dev/fd. The jq on this image is a
264+ # windows program and cannot open those, so it reads the second input
265+ # as nothing and the merge fails. Both the product and the package
266+ # merge go through here.
267+ - name : Let jq read what bash hands it
268+ run : |
269+ mkdir -p "$RUNNER_TEMP/shim"
270+ cat > "$RUNNER_TEMP/shim/jq" <<'SHIM'
271+ #!/usr/bin/env bash
272+ set -euo pipefail
273+ args=()
274+ for arg in "$@"; do
275+ case $arg in
276+ /dev/fd/* | /proc/*/fd/*)
277+ copy=$(mktemp)
278+ cat "$arg" > "$copy"
279+ args+=("$copy")
280+ ;;
281+ *) args+=("$arg") ;;
282+ esac
283+ done
284+ exec jq.exe "${args[@]}"
285+ SHIM
286+ chmod +x "$RUNNER_TEMP/shim/jq"
287+ echo "$RUNNER_TEMP/shim" >> $GITHUB_PATH
288+
289+ # Stamping version details into the native binaries clears any
290+ # signature they arrived with and asks signtool whether there is one.
291+ # That only reads and removes, so it wants no certificate and signs
292+ # nothing. It just has to be findable, and the sdk carrying it is not
293+ # on the path.
294+ - name : Put signtool on the path
295+ run : |
296+ sdk=$(ls -d "/c/Program Files (x86)/Windows Kits/10/bin"/*/x64 | sort -V | tail -1)
297+ test -x "$sdk/signtool.exe"
298+ cygpath -w "$sdk" >> $GITHUB_PATH
299+
300+ # build-release.sh copies the tree with rsync, which neither windows
301+ # nor the git bash on this image has. MSYS2 is already here, just not
302+ # on the path.
303+ - name : Install rsync
304+ shell : cmd
305+ run : C:\msys64\usr\bin\pacman -Sy --noconfirm --needed rsync
306+
307+ # Only rsync crosses over. Putting msys2's /usr/bin in front instead
308+ # breaks the release step: npm on the path is a shell script whose
309+ # shebang reads /usr/bin/env bash, so with msys2 first it is msys2's
310+ # bash that runs it, and crossing into a second msys runtime does not
311+ # carry the environment. npm then sees no script-shell and falls back
312+ # to cmd, which cannot run ./ci/build/build-release.sh, and
313+ # KEEP_MODULES is dropped on the way. A forwarder avoids the whole
314+ # class: rsync is a native exe that loads its runtime from beside
315+ # itself, and nothing else on the path moves.
316+ - name : Reach rsync without moving the path
317+ run : |
318+ cat > "$RUNNER_TEMP/shim/rsync" <<'SHIM'
319+ #!/usr/bin/env bash
320+ exec /c/msys64/usr/bin/rsync.exe "$@"
321+ SHIM
322+ chmod +x "$RUNNER_TEMP/shim/rsync"
323+
324+ - run : npm ci
325+ - run : npm run build
326+ - run : npm run build:vscode
327+ - run : KEEP_MODULES=1 npm run release
328+
329+ # Of the two tars on this image it is git bash's GNU one that can
330+ # rename the tree's top directory as it archives; the windows bsdtar
331+ # is built without substitution support. Asserted rather than
332+ # assumed, since the two are interchangeable everywhere except here.
333+ - name : Package
334+ run : |
335+ case "$(tar --version | head -1)" in
336+ *GNU*) ;;
337+ *) echo "expected GNU tar for --transform, got $(tar --version | head -1)" >&2; exit 1 ;;
338+ esac
339+ npm run package
340+
341+ - uses : softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
342+ with :
343+ draft : true
344+ discussion_category_name : " 📣 Announcements"
345+ files : ./release-packages/*
346+ tag_name : v${{ env.VERSION }}
347+ name : v${{ env.VERSION }}
0 commit comments