Skip to content
Closed

Wine #3602

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
4e86a32
docs: add Windows port design docs and M0 baseline
Sep 10, 2026
56783d1
Fix log dir creation on Windows; add windows_amd64 arch config
Sep 10, 2026
788c4d1
Add Windows implementations of the process, locking and clean layers
Sep 10, 2026
d4c132d
docs: record M1 progress and the Wine cache trap
Sep 10, 2026
75fad1a
Replace the remaining Unix-only runtime calls for Windows
Sep 10, 2026
c3b6bff
docs: mark M1 complete
Sep 10, 2026
06bd904
Fix BUILD wiring for the Windows sources
Sep 10, 2026
15e06fd
docs: record what verifying through plz changed
Sep 10, 2026
30cca3a
Make path list handling and config locations platform-aware
Sep 10, 2026
f42897c
docs: record M2 progress and a hash-comparison pitfall
Sep 10, 2026
ee77512
Use forward slashes in the environment Please generates
Sep 10, 2026
b13dc79
docs: record the measured backslash hazard
Sep 10, 2026
1ff0359
Fix globbing on Windows, and degrade gracefully without symlink privi…
Sep 10, 2026
b952a22
docs: mark M2 complete
Sep 10, 2026
4888dbc
docs: M5 vertical slice works; record the cc-rules changes
Sep 10, 2026
4c2bd5e
docs: arcat is the real Windows gate, and it ports almost for free
Sep 10, 2026
638858a
Fix package lookup and tool paths on Windows
Sep 10, 2026
dfc819a
docs: M6 headline end-to-end test passes
Sep 10, 2026
bafddbc
Make the build shell configurable, and bundle one for Windows
Sep 10, 2026
906b29e
docs: M3 complete; the bundled shell works with no configuration
Sep 10, 2026
1f1f3f0
Build, package and release Windows artifacts
Sep 10, 2026
c5cee6d
docs: M4 is done bar the arcat release
Sep 10, 2026
1124c94
Keep build labels and plz-out paths slash-separated on Windows
Sep 10, 2026
9421f5f
Run the Windows build under Wine, in CI
Sep 10, 2026
25ab97b
docs: M6 complete, and it overturned an M2 decision
Sep 10, 2026
8979c1e
Say plainly that there is no sandbox on Windows
Sep 10, 2026
ac30c91
Fix plz watch never firing on Windows
Sep 10, 2026
d217b65
docs: M7 and M8 started; two items turned out to be bugs
Sep 10, 2026
808edb1
Fix output dirs, coverage paths and file:// URLs on Windows
Sep 10, 2026
142804d
Point the Wine job at four more packages
Sep 10, 2026
5268f43
docs: record what the wider Wine job found
Sep 10, 2026
1683506
Make the BUILD language and label queries platform-independent
Sep 10, 2026
fb1319a
Run every package that can run under Wine
Sep 10, 2026
a6f4a3a
docs: three more bugs, and a warning about running these by hand
Sep 10, 2026
e83faa2
Resolve the build shell once, for everything that runs one
Sep 10, 2026
1e75ece
Add the last four packages to the Wine job
Sep 10, 2026
8782968
docs: the last packages found a gap in M3's own work
Sep 10, 2026
ff53c8b
Test killing a process tree, and put src/process under Wine
Sep 10, 2026
e702172
docs: what the job objects from M1 actually do
Sep 10, 2026
c2c0b66
Put the last package under Wine
Sep 10, 2026
6cec27a
Say what to do about the two errors a Windows user hits first
Sep 10, 2026
a1d723c
Print forward slashes in the paths Please reports
Sep 10, 2026
9e40292
Don't let a missing arcat stop everything on Windows
Sep 10, 2026
0082601
Explain a binary Windows won't run rather than saying it's missing
Sep 10, 2026
61c292d
Allow a plugin to be built from a local checkout
Sep 10, 2026
02ac6db
docs: a handoff note for picking this up cold
Sep 10, 2026
22a3a3f
Give back the parse claim on a package that turned out not to exist
Sep 10, 2026
b2cd14f
Look for please.exe when the test is running on Windows
Sep 10, 2026
b0d4a0b
Run a Python test on Windows, under Wine
Sep 10, 2026
d0eb04a
docs: python works on Windows, and three things that will bite the ne…
Sep 10, 2026
94108ed
Link a Windows binary against a DLL, and run it under Wine
Sep 10, 2026
c4abe73
docs: a DLL can be linked against, and the fourth empty-repeatable-ke…
Sep 10, 2026
3c69048
Run an sh_binary under Wine, as a .cmd
Sep 11, 2026
c6d33d2
docs: sh_binary works on Windows, and three more standing traps
Sep 11, 2026
28f0789
Build arcat from source, and fix two Windows bugs in it
Sep 11, 2026
2c4bc6b
Vendor the plugin sources and their tools for a Windows release
Sep 11, 2026
b600f9f
Find bundled plugins and arcat beside please.exe
Sep 11, 2026
6060faf
Put the plugins and the tools in the Windows release zip
Sep 11, 2026
d8b48e8
Run the release zip under Wine with the network taken away
Sep 11, 2026
167ceb3
docs: the offline release, and two more standing traps
Sep 11, 2026
adfb8e5
Ship installation instructions in the Windows zip
Sep 11, 2026
9f5d519
Package the Windows test binaries for a real Windows machine
Sep 11, 2026
f835b2c
Drive the Windows tests and probe what Wine cannot show
Sep 11, 2026
7aa45c7
Run Please on Windows in GitHub Actions
Sep 11, 2026
cf02f57
Stop the repo root walk spinning for ever on Windows
Sep 11, 2026
29e8df6
Let go of the log file before cleaning
Sep 11, 2026
f6f973c
Compare paths against the repo root in one place, and correctly
Sep 11, 2026
51aeec2
Match environment variable names the way the OS does
Sep 11, 2026
b6d83f7
Give the test bundle a repo root, and make the Windows job blocking
Sep 11, 2026
814a751
Keep the bundle's repo root in the artifact
Sep 11, 2026
2cef107
docs: what a real Windows machine said
Sep 12, 2026
096eae9
Run a cc_test on Windows, under Wine
Sep 12, 2026
3543e67
docs: correct two things a real Windows machine disproved
Sep 12, 2026
df011dd
Copy where Windows will not make a symlink, and stop skipping the tests
Sep 12, 2026
e84759a
Give plz run fixtures Windows can execute
Sep 12, 2026
90cb09d
Hand cmd.exe a path it can parse when running a target
Sep 12, 2026
80e94d0
docs: no Windows-specific skips left, and what deleting them found
Sep 12, 2026
4f1c731
Download the plugins from forks, and delete the workaround
Sep 12, 2026
bb96046
Publish the plugin tools for Windows, and download them
Sep 12, 2026
7a68ed7
Ship Windows support in 17.34.0
Sep 12, 2026
58f5d43
Stop working around the pex tool, and delete the last override
Sep 12, 2026
5375d89
Release 18.0.0 from this fork, since upstream cannot
Sep 12, 2026
40783c1
Replay the codelabs on Windows, and record what they cannot do
Sep 13, 2026
ccd993d
Merge codelab config fragments key by key, and record the first run
Sep 13, 2026
0179b2c
Record the second native run of the codelabs
Sep 13, 2026
35eaffe
Merge pull request #3 from PeterNeiss/codelabs
PeterNeiss Sep 13, 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
60 changes: 60 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,58 @@ jobs:
- save_cache:
key: go-freebsd-v1-{{ checksum "third_party/go/BUILD" }}
paths: [ ".plz-cache/third_party/go" ]

build-windows:
working_directory: ~/please
docker:
- image: ghcr.io/thought-machine/please_windows_builder:20260910
resource_class: large
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- restore_cache:
key: go-windows-v1-{{ checksum "third_party/go/BUILD" }}
- run:
name: Extract plz
command: tar -xzf /tmp/workspace/linux_amd64/please_*.tar.gz
- run:
name: Cross-compile
command: ./please/please build -p -v2 --profile ci --arch windows_amd64 //package:release_files
- persist_to_workspace:
root: plz-out/pkg
paths:
- windows_amd64/*
- store_artifacts:
path: plz-out/log
- save_cache:
key: go-windows-v1-{{ checksum "third_party/go/BUILD" }}
paths: [ ".plz-cache/third_party/go" ]

# Runs the Windows binaries we just cross-built, under Wine, on Linux. This is the only
# thing in CI that checks the port's runtime behaviour rather than that it compiles; see
# docs/design/windows/05-testing-strategy.md for what it does and does not cover.
test-windows-wine:
working_directory: ~/please
docker:
- image: ghcr.io/thought-machine/please_windows_builder:20260910
resource_class: large
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- restore_cache:
key: go-windows-v1-{{ checksum "third_party/go/BUILD" }}
- run:
name: Extract plz
command: tar -xzf /tmp/workspace/linux_amd64/please_*.tar.gz
- run:
name: Test under Wine
command: ./please/please test -p -v2 --profile ci --include=wine
- store_test_results:
path: plz-out/log/test_results.xml
- store_artifacts:
path: plz-out/log
build-linux-arm64:
working_directory: ~/please
docker:
Expand Down Expand Up @@ -515,6 +567,12 @@ workflows:
- build-freebsd:
requires:
- build-alpine
- build-windows:
requires:
- build-alpine
- test-windows-wine:
requires:
- build-alpine
- test-rex:
requires:
- build-alpine
Expand All @@ -531,6 +589,8 @@ workflows:
requires:
- build-alpine
- build-freebsd
- build-windows
- test-windows-wine
- build-darwin-amd64
- build-linux-arm64
- build-linux
Expand Down
9 changes: 9 additions & 0 deletions .circleci/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ release_folder /tmp/workspace/darwin_arm64 darwin_arm64/$VERSION
release_folder /tmp/workspace/linux_amd64 linux_amd64/$VERSION
release_folder /tmp/workspace/linux_arm64 linux_arm64/$VERSION
release_folder /tmp/workspace/freebsd_amd64 freebsd_amd64/$VERSION
release_folder /tmp/workspace/windows_amd64 windows_amd64/$VERSION

# Sign the download script with our release key
/tmp/workspace/release_signer pgp -o get_plz.sh.asc -i tools/misc/get_plz.sh
Expand All @@ -58,6 +59,14 @@ release_file tools/misc/get_plz.sh get_plz.sh text/x-shellscript
release_file get_plz.sh.asc get_plz.sh.asc text/plain
release_file get_plz.sh.sig get_plz.sh.sig application/octet-stream

# The Windows installer, served the same way and signed the same way. Windows has no shell to
# curl | sh with; this is run with irm ... | iex instead.
/tmp/workspace/release_signer pgp -o get_plz.ps1.asc -i tools/misc/get_plz.ps1
/tmp/workspace/release_signer kms -o get_plz.ps1.sig -i tools/misc/get_plz.ps1
release_file tools/misc/get_plz.ps1 get_plz.ps1 text/plain
release_file get_plz.ps1.asc get_plz.ps1.asc text/plain
release_file get_plz.ps1.sig get_plz.ps1.sig application/octet-stream

if [[ "$VERSION" == *"beta"* ]] || [[ "$VERSION" == *"alpha"* ]] || [[ "$VERSION" == *"prerelease"* ]]; then
echo "$VERSION is a prerelease, only setting latest_prerelease_version"
else
Expand Down
12 changes: 7 additions & 5 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
*.build_defs linguist-language=Starlark diff=python
BUILD.plz linguist-language=Starlark diff=python
docs/* linguist-documentation
*_bindata.go linguist-generated
third_party/go/zip/* linguist-vendored
# Batch files are read by cmd.exe, which is not reliable on LF-only input, and the fixtures
# under test/windows are compared byte for byte against output the bundled busybox produced.
# Neither should be translated on checkout.
*.cmd -text
src/run/test_data/** -text
test/windows/smoke_repo/** -text
test/windows/offline_repo/** -text
85 changes: 85 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Builds and publishes a release from this fork.
#
# Upstream publishes to a GCS bucket from CircleCI, which only runs on thought-machine/please.
# A fork cannot drive that, so nothing this branch produces was downloadable by pleasew.ps1,
# get_plz.ps1 or plz update - the Windows support was real and unreachable at the same time.
#
# This publishes the same artifacts as a GitHub Release instead. The asset names carry the
# platform, which is what gen_release.py does for the GitHub half of an upstream release, so the
# two layouts agree on names even though they disagree on paths.
#
# Delete this whole workflow if upstream ever starts publishing Windows builds.
name: Release

on:
push:
tags:
- "v*"
# So a release can be cut without tagging, while this is still being worked out.
workflow_dispatch:
inputs:
tag:
description: "Tag to release, e.g. v17.34.0"
required: true

permissions:
contents: write

jobs:
release:
name: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Please
run: |
./pleasew --version
echo "$HOME/.please" >> "$GITHUB_PATH"
- name: Build this repo's Please
# The released Please is not this one, and it hangs parsing //test/windows. Everything
# below uses the one we just built, the same two-step test.sh insists on.
run: ./pleasew build -p -v2 --profile ci //src:please
- name: Work out what we are releasing
id: version
run: |
tag="${{ github.event.inputs.tag }}"
[ -n "$tag" ] || tag="${GITHUB_REF#refs/tags/}"
version="$(cat VERSION)"
# A tag that disagrees with VERSION would publish assets nobody can find, since every
# consumer builds the filename out of the version rather than out of the tag.
[ "$tag" = "v$version" ] || { echo "tag $tag does not match VERSION $version" >&2; exit 1; }
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Build the releases
run: |
plz-out/bin/src/please build -p -v2 --profile ci --arch windows_amd64 //package:release_files
plz-out/bin/src/please build -p -v2 --profile ci //package:release_files
- name: Name the assets by platform
id: assets
run: |
version="${{ steps.version.outputs.version }}"
mkdir -p assets
for arch in windows_amd64 linux_amd64; do
for f in plz-out/pkg/$arch/*; do
[ -f "$f" ] || continue
# The same rename gen_release.py does: please_1.2.3.zip -> please_1.2.3_arch.zip.
base="$(basename "$f")"
cp "$f" "assets/${base/$version/${version}_$arch}"
done
done
ls -l assets
- name: Publish
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${{ steps.version.outputs.tag }}" \
--repo "${{ github.repository }}" \
--title "Please ${{ steps.version.outputs.version }}" \
--notes "Built from this fork, which carries Windows support that is not upstream yet.

Install on Windows:

irm https://raw.githubusercontent.com/${{ github.repository }}/${{ steps.version.outputs.tag }}/tools/misc/get_plz.ps1 | iex

See docs/design/windows/07-state-of-play.md for what works and what does not." \
assets/*
183 changes: 183 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# The only thing anywhere that runs Please on a real Windows machine.
#
# Everything else the port claims rests on Wine, and docs/design/windows/05-testing-strategy.md
# is explicit that Wine passing is evidence rather than proof. The classes it cannot show are
# the ones Please works hardest in: sharing violations on teardown, path length, case-insensitive
# collisions, symlink privileges.
#
# CircleCI cross-builds the same artifacts, but its workspaces are scoped to one CircleCI run
# and cannot be read from here, so this cross-builds its own on a Linux runner and hands them
# over. That duplication is the price of there being no Windows runner in CircleCI's config.
name: Windows

on:
push:
branches:
- master
- wine
pull_request:

concurrency:
group: windows-${{ github.ref }}
cancel-in-progress: true

jobs:
cross-build:
name: cross-build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Please
run: |
./pleasew --version
echo "$HOME/.please" >> "$GITHUB_PATH"
- name: Build this repo's Please
# The released Please is not this one, and the difference is not cosmetic: it predates
# the parse-deadlock fix and hangs parsing //test/windows, silently and for ever.
# Everything below uses the one we just built, the same two-step test.sh insists on.
run: ./pleasew build -p -v2 --profile ci //src:please
- name: Cross-build the test bundle
run: plz-out/bin/src/please build -p -v2 --profile ci //test/windows:native_test_bundle
- name: Cross-build the release
# The same command CircleCI's build-windows job runs, so what the Windows job gets here
# is what a user would get.
run: plz-out/bin/src/please build -p -v2 --profile ci --arch windows_amd64 //package:release_files
- name: Extract the codelab plan
# Built here, on Linux, so the Windows job replays a plan that
# //test/windows/codelab_script/script:script_test has already checked against the same
# codelabs and the same sidecar. See test/windows/run_codelabs.ps1.
run: plz-out/bin/src/please build -p -v2 --profile ci //test/windows:codelab_plan
- name: Upload the codelab plan
uses: actions/upload-artifact@v4
with:
name: windows-codelab-plan
path: plz-out/gen/test/windows/codelab_plan.json
retention-days: 7
- name: Upload the test bundle
uses: actions/upload-artifact@v4
with:
name: windows-test-bundle
path: plz-out/gen/test/windows/native_test_bundle
# The bundle's repo-root marker is a .plzconfig, and this action drops hidden files
# unless told not to. Without it the tests that look for a repo root find none and
# die, which nothing on the Linux side can catch - the Wine test runs the bundle
# directly, never through an artifact.
include-hidden-files: true
retention-days: 7
- name: Upload the release
uses: actions/upload-artifact@v4
with:
name: windows-release
path: plz-out/pkg/windows_amd64/please_*.zip
retention-days: 7
- name: Upload the logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: cross-build-logs
path: plz-out/log
retention-days: 7

test:
name: test
needs: cross-build
runs-on: windows-latest
# Blocking. It was advisory for exactly one run, to produce a failure list without a red
# check nobody had read yet; everything that run found is fixed. Anything genuinely left
# over belongs in test/windows/known_failures.txt with a reason, not behind a flag that
# makes the whole job ignorable.
steps:
- name: Keep Unix line endings
# The fixtures are compared byte for byte against output the bundled busybox produced,
# and busybox does not translate line endings. Has to precede the checkout.
run: git config --global core.autocrlf input
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: windows-test-bundle
path: ${{ runner.temp }}\bundle
- uses: actions/download-artifact@v4
with:
name: windows-release
path: ${{ runner.temp }}\release
- name: Report the machine
# Both of these change what is reachable, both differ between runner images, and
# guessing either has already cost time. Print them rather than assuming.
run: |
(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -EA SilentlyContinue) |
Select-Object -ExpandProperty LongPathsEnabled -EA SilentlyContinue |
ForEach-Object { "LongPathsEnabled=$_" } | Tee-Object -Append $env:GITHUB_STEP_SUMMARY
whoami /priv | Select-String SeCreateSymbolicLinkPrivilege |
Tee-Object -Append $env:GITHUB_STEP_SUMMARY
- name: Run the cross-built unit tests
run: |
./test/windows/run_native_tests.ps1 `
-Bundle "$env:RUNNER_TEMP\bundle" `
-Logs "$env:RUNNER_TEMP\logs" `
-KnownFailures test/windows/known_failures.txt
- name: Build a repo with the release
if: ${{ !cancelled() }}
run: |
./test/windows/run_native_probes.ps1 `
-Release "$env:RUNNER_TEMP\release" `
-Logs "$env:RUNNER_TEMP\logs"
- name: Upload the logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: windows-test-logs
path: ${{ runner.temp }}\logs
retention-days: 7

codelabs:
name: codelabs
needs: cross-build
runs-on: windows-latest
# A job of its own rather than a step in test. It needs the release but not the bundle, it
# runs for far longer - eight codelabs, plugin downloads, a Go toolchain - and a hung codelab
# should not eat the unit tests' time or delay the signal people actually read.
timeout-minutes: 90
# Blocking from its first run, for the reason the test job gives. What the codelabs cannot do
# on Windows is expected, and the mechanism for expected already exists: every such step is
# in test/windows/codelab_known_failures.txt with a reason. There is no advisory mode to
# forget to take out.
steps:
- name: Keep Unix line endings
# The runner script and the failures list come from the checkout. Has to precede it.
run: git config --global core.autocrlf input
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: windows-release
path: ${{ runner.temp }}\release
- uses: actions/download-artifact@v4
with:
name: windows-codelab-plan
path: ${{ runner.temp }}\plan
- name: Report the toolchains
# The codelabs assume Go, Python, git, Docker and kubectl, and which of those exist - and
# for Docker, which kind of containers it runs - decides what is skipped. Print it rather
# than inferring it from the results.
run: |
"pwsh = $($PSVersionTable.PSVersion)" | Tee-Object -Append $env:GITHUB_STEP_SUMMARY
foreach ($t in 'go', 'python', 'git', 'docker', 'kubectl') {
$c = Get-Command $t -EA SilentlyContinue
"$t = $(if ($c) { $c.Source } else { 'not installed' })" | Tee-Object -Append $env:GITHUB_STEP_SUMMARY
}
if (Get-Command docker -EA SilentlyContinue) {
"docker OSType = $(docker info --format '{{.OSType}}' 2>$null)" | Tee-Object -Append $env:GITHUB_STEP_SUMMARY
}
- name: Run the codelabs
run: |
./test/windows/run_codelabs.ps1 `
-Plan "$env:RUNNER_TEMP\plan\codelab_plan.json" `
-Release "$env:RUNNER_TEMP\release" `
-Logs "$env:RUNNER_TEMP\logs" `
-KnownFailures test/windows/codelab_known_failures.txt
- name: Upload the logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: windows-codelab-logs
path: ${{ runner.temp }}\logs
retention-days: 7
Loading