Skip to content

ci: run the CI on Windows in parallel with Linux - #906

Draft
Upd4ting wants to merge 13 commits into
mainfrom
ci/windows
Draft

Upd4ting wants to merge 13 commits into
mainfrom
ci/windows

Conversation

@Upd4ting

@Upd4ting Upd4ting commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Why

dms's CI runs only on Linux, so Windows-only breaks reach developers first. This PR runs the CI on Windows in parallel with Linux and fixes what breaks there (ANT-2185).

Status: blocked. The run was frozen before the dms-control tests were fixed. The Windows Test job still fails and then hangs on them (see Open).

What

  • CI. ci-node.yml@v1 now runs with windows: true. backend, frontend-test, frontend-verify and verify-map gain a windows-latest matrix leg and use Git Bash as the package-script shell.
    • The Windows backend suites get a 35-minute budget. Linux keeps 20. That number is measured: Windows builder:2 took 17 min against 9 on Linux.
    • docs-playground stays Linux-only because it builds Linux Docker images. formal stays Linux-only because model checking does not depend on the OS.
  • .gitattributes. * text=auto eol=lf, and symlink=dir for the .claude/skills/* directory links. The index was already LF everywhere, so nothing is renormalised.
  • Production Windows bugs fixed.
    • Builder engine. Paths it stores or compares are now POSIX, and fs calls use native paths (engine/file-paths.ts). On Windows, moduleOfFile matched no module, and the project config recorded modules\erp-tables.
    • npm and pnpm calls. npm view, npm pack and pnpm exec tsc failed with ENOENT on Windows, because npm is a .cmd shim. This hit the module store, update notifications and the MCP typecheck tool.
      • utils/package-manager.ts now runs them through cmd.exe on Windows, with every argument double-quoted.
      • Arguments containing ", %, ! or a control character are refused.
      • Trailing backslashes are doubled.
      • Linux and macOS still use execFile with no shell.
      • Please review this helper carefully: it builds a shell command line from a package spec.
  • Test and check fixes.
    • Separator, 8.3 short name and escaped-path mismatches in interface tests, backend-checks.cjs, the auto-import and playground import checkers, and test-files.mjs. That script now lists / paths, so the shards match across OSes.
    • The replica test spawns ajs through Node.
    • Three builder reads get the OP_TIMEOUT their siblings use.

Windows-only skip

The MCP credential test asserts mode 0o600 only where the OS has POSIX modes (it.skip on win32). Measured: Node on Windows reports 0o666 (438) after chmod(0o600), because it only toggles the read-only flag. Restricting the file to its user on Windows needs an ACL change. That is a follow-up.

Proof

  • Before, the first run with windows: true: https://github.com/AntelopeJS/dms/actions/runs/43492195752. 9 Windows jobs failed: Node, Test, backend unit, integration and builder:2, builder:1 (cancelled at 20 min with 36 failing), frontend-test shard 2, frontend-verify, and the gate.
  • After, at 050d1cf: https://github.com/AntelopeJS/dms/actions/runs/43504376080.
    • Green on Windows: Node, backend unit, integration, builder:1 (338 passing in 17 min), both frontend-test shards, frontend-verify, verify-map. Every Linux job is green too.
    • Windows builder:2: 3 failing out of 332, down from 18.
    • Windows Test: hangs on dms-control (see Open).

Open

  • dms-control on Windows. In packages/dms/bin/control, 30 tests fail: backend-records, backend, backend-mode, build-cache, build-key, journey (a stand-in mongod gives ENOENT) and mongo. The suite then hangs after mongo.test.mjs, even with --test-timeout=90000. This was seen on a probe run of those tests alone.
  • Builder:2 on Windows, 3 failures. Each one compares a ts-morph / path with a native path:
    • writes a resource into the module named
    • writes a category and a page into the module named
    • mounts the summary route on a controller whose route map names its routes without it

Temporary dependencies

@antelopejs/dms-frontend is pinned to a tarball of main 8e5ca35 (dms-frontend #336 and #337, unreleased) in .tgz-deps/. That makes ajs dms verify-source build its workspace on the project's drive. Swap it for the release that carries 8e5ca35, and note that this commit range also includes dms-frontend #335, fix(auth)!.

ts-morph names a file with `/` on every platform, while node:path builds a
module root with the platform's separator. On Windows the builder's
containment checks compared the two as text, so no file belonged to any
module: mapped modules were never detected, GetMapping and remaps saw no
mapped records, pages and resources lost their source module, and a page
or resource placed by folder was refused as escaping src. The scaffolded
local module's path was also written into antelope.config.ts with `\`.

isInsideFolder compares through path.relative, which normalizes separators
and drive-letter case, and replaces the startsWith checks in modules.ts,
placement.ts and project-config-ops.ts. posixRelative writes the module
path with `/`. Both take the path functions as a parameter so a spec runs
the Windows branch through path.win32.

Tests that compared paths as text now compare them the way Windows reports
them, and three reads that rebuild the index run under the file's
OP_TIMEOUT instead of mocha's 2 s default, which a Windows runner exceeds.
On Windows npm and pnpm are .cmd shims. execFile without a shell cannot
run them, so `npm view`, `npm pack` and `pnpm exec tsc` failed with ENOENT
and the store, the update notifications and the MCP typecheck tool
swallowed the error.

runPackageManager runs a package-manager command with no shell outside
Windows. On Windows it passes cmd.exe a command line in which every
argument is double-quoted, so cmd.exe and the shim read & | < > ^ ( ) as
text, with trailing backslashes doubled. It refuses an argument holding
", %, ! or a control character, which cmd.exe reads even inside quotes.
The four call sites move onto it, and the process pins follow.

The tests now run on Windows: package-contents packs through the helper,
the registry stand-in gets an npm.cmd beside it, and the manifest fixtures
no longer name a folder with a double quote.
@Upd4ting Upd4ting added the tgz-pending Waits for a release; holds a .tgz-deps tarball label Nov 13, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tgz-pending Waits for a release; holds a .tgz-deps tarball

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant