Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
e4f5191
docs(nbd-poc): design for NBD-over-inherited-fd transport PoC
xdqi May 31, 2026
f07cf26
docs(nbd-poc): add production async-server section (§9)
xdqi May 31, 2026
7d83c91
docs(nbd-poc): clarify keep-alive vs multiplexing in §9
xdqi May 31, 2026
251f86b
docs(nbd-poc): implementation plan for NBD-over-inherited-fd PoC
xdqi May 31, 2026
352a087
feat(qemu_backend): add nbd-fd / nbd-port image-path branch for PoC
xdqi May 31, 2026
76660b7
feat(lspart): accept --nbd-fd N / --nbd-port P flags
xdqi May 31, 2026
c14c165
feat(poc-nbd): native-transport addon exposing socketpair()
xdqi May 31, 2026
57e18e2
feat(poc-nbd): hand-written read-only NBD newstyle server
xdqi May 31, 2026
06d7a2d
docs(nbd-poc): adapt plan to synthetic test image + correct binary paths
xdqi May 31, 2026
9af49c3
feat(poc-nbd): deterministic qcow2 test-image generator
xdqi May 31, 2026
47d02c9
fix(poc-nbd): correct NBD option-reply magic to 0x0003e889045565a9
xdqi May 31, 2026
25bc814
feat(poc-nbd): launcher (fd-pair + unix-socket modes) + qemu-img cros…
xdqi May 31, 2026
bca5dd2
docs(nbd-poc): fix NBD reply magic + Stage-2 async qemu-io
xdqi May 31, 2026
e183b91
test(poc-nbd): Stage 1 — inherited-fd NBD open, zero QEMU source changes
xdqi May 31, 2026
17f6e5f
docs(nbd-poc): record Stage-1 PASS + MODULE_INIT_QOM requirement
xdqi May 31, 2026
4947017
test(poc-nbd): Stage 2 — full Linux chain parity + through-chain byte…
xdqi May 31, 2026
e8e882f
docs(poc-nbd): Stage-3 wine/loopback findings + PoC results summary
xdqi May 31, 2026
38c48a6
fix(poc-nbd): clear CLOEXEC only on child fd; close imageFd in stage2
xdqi May 31, 2026
0709bfc
docs(poc-nbd): Stage 3 PASS — wine 127.0.0.1 loopback validated
xdqi Jun 1, 2026
5adabdd
docs(nbd-proxy): production NBD proxy design
xdqi Jun 1, 2026
74dac95
docs(nbd-proxy): implementation plan for @anyfs/nbd-proxy
xdqi Jun 1, 2026
d6dccee
feat(nbd-proxy): scaffold @anyfs/nbd-proxy package
xdqi Jun 1, 2026
0cc964f
feat(nbd-proxy): DataSource interface + FileSource
xdqi Jun 1, 2026
8816561
feat(nbd-proxy): async multi-in-flight NbdServer
xdqi Jun 1, 2026
7cba496
feat(nbd-proxy): endpoint (fd + loopback) + qemu-img integration test
xdqi Jun 1, 2026
7be1f88
fix(nbd-proxy): serveOnLoopback rejects on listen error instead of ha…
xdqi Jun 1, 2026
c00b5ea
feat(nbd-proxy): HttpSource (global fetch + connection reuse)
xdqi Jun 1, 2026
62ccd7f
feat(nbd-proxy): BlockDeviceSource (Linux v1)
xdqi Jun 1, 2026
905fdf3
feat(nbd-proxy): real CLI + spawned-proxy integration test
xdqi Jun 1, 2026
f8fb1ae
test(nbd-proxy): run unit+integration in pnpm test; web paths intact
xdqi Jun 1, 2026
09687a9
fix(nbd-proxy): harden NbdServer error paths + clear unknown-kind error
xdqi Jun 1, 2026
0164d67
docs: build & test hardening implementation plan
xdqi Jun 10, 2026
cceea69
feat(build): add wasm_sysroot config key + materialize wasm_ld default
xdqi Jun 10, 2026
b2406c0
refactor(build): wire gen_lkl_config_wasm + build_lkl_wasm to build.c…
xdqi Jun 10, 2026
9669cb2
refactor(build): wire build_boot_wasm + build_libblkid_wasm to build.…
xdqi Jun 10, 2026
0ed37a6
refactor(build): wire build_libblkid_mingw to build.config.toml
xdqi Jun 10, 2026
a59d587
refactor(build): wire build_qemu to build.config.toml
xdqi Jun 10, 2026
58f91d9
fix(build): align wasm_sysroot key + drop unreachable doctor wasm-ld …
xdqi Jun 10, 2026
5d4abfd
refactor(build): wire build_anyfs to build.config.toml; lint covers a…
xdqi Jun 10, 2026
baa0e78
feat(build): generate wasm export list from anyfs_ts.c + drift gate
xdqi Jun 10, 2026
e05d2d5
ci(lint): shellcheck gate for build scripts
xdqi Jun 10, 2026
9354834
refactor(build): build_anyfs_wasm uses config.sh + generated exports;…
xdqi Jun 10, 2026
1790b92
fix(test): wasm export gate matches all TS symbol references, not jus…
xdqi Jun 10, 2026
9e56e73
feat(server): add server_common daemon skeleton (signals/boot/shares/…
xdqi Jun 10, 2026
e3f40ae
feat(doctor): wasm-sysroot manifest check
xdqi Jun 10, 2026
335bef7
refactor(ksmbd): use server_common skeleton
xdqi Jun 10, 2026
31d6b5b
refactor(nfsd): use server_common skeleton
xdqi Jun 10, 2026
73bb803
test(core): meson unit suite + path DSL parser tests
xdqi Jun 10, 2026
d0820b6
test(core): share helper unit tests
xdqi Jun 10, 2026
3855eb2
ci(linux): run C unit suite + wasm export gate; shellcheck via base a…
xdqi Jun 10, 2026
866ec9c
fix(build): vendor LKL-wasm bracket fixer tools; fail loudly when mis…
xdqi Jun 10, 2026
c9dff2d
test(core): node:test unit suite — format, session-base, dispatch matrix
xdqi Jun 10, 2026
8bc79a2
test(core): port node wasm smoke to async _p call pattern; realpath s…
xdqi Jun 10, 2026
e53a65e
feat(build): --cc compiler override for LKL and QEMU builds
xdqi Jun 10, 2026
d8e1828
test(react): vitest provider + hooks unit suite
xdqi Jun 10, 2026
8f846a1
ci: ts unit-test workflow
xdqi Jun 10, 2026
62d1ff8
test: CDP suite demoted to diagnostics after Playwright parity audit
xdqi Jun 10, 2026
5625d8b
fix(build): preflight LKL-wasm tool check before compile; unclip buil…
xdqi Jun 10, 2026
af7e393
test: relocate test-core to ts integration; corral debug scripts unde…
xdqi Jun 10, 2026
58b1357
ci(linux): sccache-dist compile farm (2 workers, best-effort)
xdqi Jun 10, 2026
305db9b
test(integration): port test-core to the session API (async _p wasm p…
xdqi Jun 10, 2026
b4bcfff
ci(mingw64): experimental sccache-dist farm for the LKL cross build
xdqi Jun 10, 2026
5660da7
test(native): await async addon calls in stale smoke tests
xdqi Jun 10, 2026
41d2e9c
feat(build): reproducible wasm-sysroot recipe (manifest-parity with t…
xdqi Jun 10, 2026
b25cfc2
ci: fix ts install for bare runners; skip farm cleanly when secret ab…
xdqi Jun 10, 2026
a033e9e
fix(build): delegate blkid wasm helper to the sysroot recipe; guard t…
xdqi Jun 10, 2026
2797b52
feat(build): wasm-sysroot CI tarball release + fetch (mingw-style pro…
xdqi Jun 10, 2026
817a1be
ci: skip sccache farm cleanly when TS_OAUTH_SECRET is absent
xdqi Jun 10, 2026
bd2b066
ci(wasm-sysroot): release workflow for the wasm sysroot tarball
xdqi Jun 10, 2026
0e5d5e1
ci(ts): generate the nbd-proxy qcow2 fixture before tests
xdqi Jun 10, 2026
dfb16a5
docs: sccache-dist CI farm setup, fallback contract, first-run results
xdqi Jun 10, 2026
a4c293c
ci: sccache-dist-action v0.0.5 + tailnet tag:ci on both farm legs
xdqi Jun 10, 2026
6086876
feat(build): fetch patched wasm-ld from llvm-wasm fork releases
xdqi Jun 10, 2026
5b26d20
ci(mingw64): msys-cross-pkgconfig renamed to msys-cross-mingw64-pkgconf
xdqi Jun 10, 2026
f2da756
chore: gitignore __pycache__; shellcheck-gate doctor.sh; document .to…
xdqi Jun 10, 2026
f34876c
docs(ci): final sccache-dist farm results (v0.0.5, tag:ci)
xdqi Jun 11, 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
90 changes: 87 additions & 3 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,44 @@ on:
workflow_dispatch:

jobs:
# Ephemeral sccache-dist compile farm. Workers serve the coordinator
# (the build job) and exit when it goes offline. Skipped on PRs —
# fork PRs have no TS_OAUTH_SECRET and same-repo PRs don't need the
# farm for cache-warm builds. Also skipped when TS_OAUTH_SECRET is not
# configured, so missing-secret runs stay green instead of failing the
# worker jobs. (The secrets context is not allowed in `if` expressions,
# so its presence is laundered through job-level env.)
sccache-workers:
name: sccache worker ${{ matrix.idx }}
if: ${{ github.event_name != 'pull_request' }}
runs-on: ubuntu-24.04
timeout-minutes: 75
strategy:
matrix:
idx: [1, 2]
env:
FARM_SECRET_SET: ${{ secrets.TS_OAUTH_SECRET != '' }}
steps:
- name: Farm disabled — TS_OAUTH_SECRET not configured
if: ${{ env.FARM_SECRET_SET == 'false' }}
run: echo "TS_OAUTH_SECRET is not set; skipping farm worker (build compiles locally)."
- uses: xdqi/sccache-dist-action@v0.0.5
if: ${{ env.FARM_SECRET_SET == 'true' }}
with:
mode: worker
worker-index: '${{ matrix.idx }}'
oauth-secret: '${{ secrets.TS_OAUTH_SECRET }}'
# The OAuth client owns tag:ci (not the action default tag:ci-sccache).
tags: 'tag:ci'

build:
name: linux-amd64
runs-on: ubuntu-24.04
timeout-minutes: 75

env:
FARM_SECRET_SET: ${{ secrets.TS_OAUTH_SECRET != '' }}

steps:
- name: Checkout anyfs-reader
uses: actions/checkout@v4
Expand All @@ -40,7 +73,8 @@ jobs:
libfuse3-dev libnl-3-dev libnl-genl-3-dev \
libcurl4-openssl-dev \
patchelf ca-certificates \
smbclient nfs-common curl
smbclient nfs-common curl \
shellcheck

# ── Caches ──────────────────────────────────────────────────────────────
# All source deps (linux, qemu, ksmbd-tools) are now managed by peru and
Expand Down Expand Up @@ -114,6 +148,35 @@ jobs:
- name: Lint — no hardcoded paths in migrated build scripts
run: ./scripts/lint-no-hardcoded-paths.sh

- name: Lint — shellcheck
run: ./scripts/lint-shellcheck.sh

# ── sccache-dist farm (best-effort; build proceeds locally if absent) ──
# Gated on TS_OAUTH_SECRET: without it the farm cannot come up, so skip
# the whole block (sccache never lands on PATH and the build uses plain
# gcc, exactly like the PR path).
- name: Cache sccache objects
if: ${{ github.event_name != 'pull_request' && env.FARM_SECRET_SET == 'true' }}
uses: actions/cache@v4
with:
path: ~/.cache/sccache
key: sccache-linux-amd64-${{ github.sha }}
restore-keys: |
sccache-linux-amd64-

- name: Bring up sccache-dist farm
if: ${{ github.event_name != 'pull_request' && env.FARM_SECRET_SET == 'true' }}
continue-on-error: true
uses: xdqi/sccache-dist-action@v0.0.5
with:
mode: coordinator
expected-workers: 2
min-workers: 1
wait-timeout: 180s
oauth-secret: '${{ secrets.TS_OAUTH_SECRET }}'
# The OAuth client owns tag:ci (not the action default tag:ci-sccache).
tags: 'tag:ci'

# ── Build ksmbd-tools (linux-amd64) ────────────────────────────────────
- name: Build ksmbd-tools
if: steps.cache-ksmbd-build.outputs.cache-hit != 'true'
Expand Down Expand Up @@ -141,11 +204,16 @@ jobs:

- name: Build LKL kernel
run: |
CC_ARGS=()
if command -v sccache >/dev/null 2>&1; then
CC_ARGS=(--cc="sccache gcc")
fi
./scripts/build_lkl.sh \
--linux=deps/linux \
--out="$GITHUB_WORKSPACE" \
--targets=linux-amd64 \
-j"$(nproc)"
"${CC_ARGS[@]}" \
-j"${SCCACHE_J:-$(nproc)}"
# package_linux.sh falls back to $HOME/linux/tools/lkl/lib/liblkl.so —
# link the per-target build there so packaging finds it.
mkdir -p deps/linux/tools/lkl/lib
Expand All @@ -154,10 +222,15 @@ jobs:

- name: Build QEMU block layer
run: |
CC_ARGS=()
if command -v sccache >/dev/null 2>&1; then
CC_ARGS=(--cc="sccache gcc")
fi
./scripts/build_qemu.sh \
--qemu-src=deps/qemu \
--targets=linux-amd64 \
-j"$(nproc)"
"${CC_ARGS[@]}" \
-j"${SCCACHE_J:-$(nproc)}"

- name: Build anyfs-reader (core + server + fuse)
run: |
Expand All @@ -169,6 +242,17 @@ jobs:
--ksmbd-root=deps/ksmbd-tools \
-j"$(nproc)"

- name: sccache stats
if: ${{ github.event_name != 'pull_request' && env.FARM_SECRET_SET == 'true' }}
continue-on-error: true
run: sccache --show-stats || true

- name: Run C unit tests
run: meson test -C build-anyfs-linux-amd64 --suite unit --print-errorlogs

- name: Wasm export drift gate
run: ./tests/test_wasm_exports.sh

# ── Integration smoke test ──────────────────────────────────────────────
# Boots each anyfs binary against a Debian 13 generic-cloud qcow2 and
# asserts lspart/smbclient/nfs see a real Debian rootfs. This catches
Expand Down
79 changes: 77 additions & 2 deletions .github/workflows/mingw64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,36 @@ on:
workflow_dispatch:

jobs:
# Ephemeral sccache-dist compile farm. Workers serve the coordinator
# (the build job) and exit when it goes offline. Skipped on PRs —
# fork PRs have no TS_OAUTH_SECRET and same-repo PRs don't need the
# farm for cache-warm builds. Also skipped when TS_OAUTH_SECRET is not
# configured, so missing-secret runs stay green instead of failing the
# worker jobs. (The secrets context is not allowed in `if` expressions,
# so its presence is laundered through job-level env.)
sccache-workers:
name: sccache worker ${{ matrix.idx }}
if: ${{ github.event_name != 'pull_request' }}
runs-on: ubuntu-24.04
timeout-minutes: 90
strategy:
matrix:
idx: [1, 2]
env:
FARM_SECRET_SET: ${{ secrets.TS_OAUTH_SECRET != '' }}
steps:
- name: Farm disabled — TS_OAUTH_SECRET not configured
if: ${{ env.FARM_SECRET_SET == 'false' }}
run: echo "TS_OAUTH_SECRET is not set; skipping farm worker (build compiles locally)."
- uses: xdqi/sccache-dist-action@v0.0.5
if: ${{ env.FARM_SECRET_SET == 'true' }}
with:
mode: worker
worker-index: '${{ matrix.idx }}'
oauth-secret: '${{ secrets.TS_OAUTH_SECRET }}'
# The OAuth client owns tag:ci (not the action default tag:ci-sccache).
tags: 'tag:ci'

build:
name: mingw64
runs-on: ubuntu-24.04
Expand All @@ -40,6 +70,7 @@ jobs:
env:
MSYS_CROSS_REPO: https://msys.kosaka.moe/repo
MSYS_CROSS_PREFIX: /opt/msys2-cross
FARM_SECRET_SET: ${{ secrets.TS_OAUTH_SECRET != '' }}

steps:
- name: Checkout anyfs-reader
Expand Down Expand Up @@ -90,7 +121,7 @@ jobs:
msys-cross-mingw64-gcc \
msys-cross-cygwin-binutils \
msys-cross-cygwin-gcc \
msys-cross-pkgconfig
msys-cross-mingw64-pkgconf

# MSYS2 upstream sysroot libs under /opt/msys2-cross/mingw64.
# QEMU block layer + DLL closure deps that package_mingw64.sh
Expand All @@ -111,6 +142,37 @@ jobs:
"${MSYS_CROSS_PREFIX}/bin/x86_64-w64-mingw32-pkg-config" \
--modversion glib-2.0

# ── sccache-dist farm (best-effort; build proceeds locally if absent) ──
# EXPERIMENTAL on this leg: sccache-dist must package the msys2-cross
# x86_64-w64-mingw32-gcc toolchain (under /opt/msys2-cross) and ship it
# to the workers. The engine supports arbitrary-toolchain packaging, but
# a plain cross-gcc + sysroot is unproven here. On any farm failure the
# build falls back to local compilation exactly as before.
# Gated on TS_OAUTH_SECRET: without it the farm cannot come up, so skip
# the whole block (sccache never lands on PATH and the build uses the
# plain cross-gcc, exactly like the PR path).
- name: Cache sccache objects
if: ${{ github.event_name != 'pull_request' && env.FARM_SECRET_SET == 'true' }}
uses: actions/cache@v4
with:
path: ~/.cache/sccache
key: sccache-mingw64-${{ github.sha }}
restore-keys: |
sccache-mingw64-

- name: Bring up sccache-dist farm
if: ${{ github.event_name != 'pull_request' && env.FARM_SECRET_SET == 'true' }}
continue-on-error: true
uses: xdqi/sccache-dist-action@v0.0.5
with:
mode: coordinator
expected-workers: 2
min-workers: 1
wait-timeout: 180s
oauth-secret: '${{ secrets.TS_OAUTH_SECRET }}'
# The OAuth client owns tag:ci (not the action default tag:ci-sccache).
tags: 'tag:ci'

# ── Caches ──────────────────────────────────────────────────────────────
# All source deps (linux, qemu, ksmbd-tools, util-linux) are now managed
# by peru and cached together under ./deps/. Key on peru.yaml (SHA-pinned
Expand Down Expand Up @@ -202,11 +264,19 @@ jobs:

- name: Build LKL kernel (mingw64)
run: |
# Absolute compiler path so sccache-dist hashes and ships the
# msys2-cross toolchain (not whatever "x86_64-w64-mingw32-gcc"
# resolves to on a worker).
CC_ARGS=()
if command -v sccache >/dev/null 2>&1; then
CC_ARGS=(--cc="sccache /opt/msys2-cross/bin/x86_64-w64-mingw32-gcc")
fi
./scripts/build_lkl.sh \
--linux=deps/linux \
--out="$GITHUB_WORKSPACE" \
--targets=mingw64 \
-j"$(nproc)"
"${CC_ARGS[@]}" \
-j"${SCCACHE_J:-$(nproc)}"
test -f "$GITHUB_WORKSPACE/lkl-mingw64/tools/lkl/lib/liblkl.dll" \
|| { echo "::error::liblkl.dll missing"; exit 1; }

Expand All @@ -233,6 +303,11 @@ jobs:
--ksmbd-root=deps/ksmbd-tools \
-j"$(nproc)"

- name: sccache stats
if: ${{ github.event_name != 'pull_request' && env.FARM_SECRET_SET == 'true' }}
continue-on-error: true
run: sccache --show-stats || true

- name: Package Win64 distribution tarball
run: |
./scripts/package_mingw64.sh
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/ts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: ts

# Pure TS unit tests (no wasm bundle, no LKL): @anyfs/core node:test suite +
# @anyfs/react vitest suite + @anyfs/nbd-proxy. The wasm smoke tests
# (test/smoke.node.mjs) need a built bundle and stay local-only.

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
unit:
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11
package_json_file: ts/package.json
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
cache-dependency-path: ts/pnpm-lock.yaml
- name: Install qemu-utils (qemu-img + qemu-io for nbd-proxy integration)
run: sudo apt-get install -y --no-install-recommends qemu-utils
- name: Install
working-directory: ts
# electron-demo depends on a sibling checkout (drivelist via
# file:../../../../drivelist-anyfs) and @anyfs/native's node-gyp
# install script compiles against the LKL tree — neither exists on a
# bare CI runner. Exclude both; electron-demo is the only dependent of
# @anyfs/native, and none of the CI-tested packages need either.
run: pnpm install --frozen-lockfile --filter '!electron-demo' --filter '!@anyfs/native'
- name: Build packages
working-directory: ts
run: pnpm -r --filter './packages/*' --filter '!@anyfs/native' build
- name: Core unit tests
working-directory: ts
run: pnpm --filter @anyfs/core run test:unit
- name: React unit tests
working-directory: ts
run: pnpm --filter @anyfs/react test
# The nbd-proxy integration test opens the PoC fixture qcow2 through the
# proxy with real qemu-img; the fixture is deterministic and generated
# on the fly (8 MiB pattern image + qemu-img convert).
- name: Generate nbd-proxy test fixture
run: node scripts/poc-nbd/make-test-image.mjs
- name: nbd-proxy tests
working-directory: ts
run: pnpm --filter @anyfs/nbd-proxy test
Loading
Loading