Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
481ffd5
test: cover render-mode docker option bypass
u1f992 May 5, 2026
c01ea34
test: cover render-on-docker example end-to-end
u1f992 May 5, 2026
18a5d62
feat: support --render-mode docker on raw Linux dockerd and Win+WSL h…
u1f992 May 9, 2026
11bbd9c
chore: add changeset
u1f992 May 9, 2026
f918099
docs: describe renderMode docker object fields
u1f992 May 9, 2026
f79efc8
Update src/config/resolve.ts
u1f992 May 13, 2026
25acbac
Update src/config/schema.ts
u1f992 May 13, 2026
e978f4a
refactor: expose WSL renderMode helpers as create* factories with aut…
u1f992 May 13, 2026
0317cf9
test(container): inline expected constants instead of importing from src
u1f992 May 13, 2026
a51c48a
fix: accept readonly string[] for renderMode.extraRunArgs to support …
u1f992 May 13, 2026
ffd6f38
ci: run render-on-docker tests on Linux and Win+WSL NAT hybrid
u1f992 May 13, 2026
2811d33
ci: declare minimum permissions for test workflow
u1f992 May 13, 2026
1df80ef
wip: capture dockerd startup diagnostics in WSL job
u1f992 May 13, 2026
d947ef9
ci: upgrade Vampire/setup-wsl@v3 to @v7 so distros install as WSL2
u1f992 May 13, 2026
6a2312d
ci: pass GITHUB_WORKSPACE into wsl-bash so image build can find the c…
u1f992 May 13, 2026
5061432
fix: preserve error.cause in runContainer so callers see the underlyi…
u1f992 May 13, 2026
69d49f6
ci: inline workspace path via YAML expansion since env: does not reac…
u1f992 May 13, 2026
ca2ddbf
fix: include container output tail in runContainer error message
u1f992 May 13, 2026
c422e40
ci: chmod fixture dir so container (uid 1000) can write its output
u1f992 May 13, 2026
f323830
ci: pre-create .vs-pdf output dir so teardown can remove container-ow…
u1f992 May 13, 2026
ff15d84
docs: Update docs
u1f992 May 14, 2026
d7309be
Merge branch 'main' into test/render-mode-docker-coverage
u1f992 May 14, 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
5 changes: 5 additions & 0 deletions .changeset/render-mode-docker-engine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vivliostyle/cli': minor
---

Support `renderMode: docker` without Docker Desktop
179 changes: 179 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ on:
- synchronize
merge_group:

permissions:
contents: read

jobs:
build-and-test:
runs-on: ${{ matrix.os }}
Expand All @@ -33,6 +36,182 @@ jobs:
- run: pnpm install
- run: pnpm build:cli
- run: pnpm test
# Runs render-on-docker.test.ts against a locally-built CLI image on Linux,
# where the docker daemon is native (no Docker Desktop, no WSL).
render-on-docker-linux:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- run: pnpm install
- run: pnpm build:cli
- name: Output package version
id: package
run: echo "version=$(jq -r '.version' package.json)" >> "$GITHUB_OUTPUT"
- name: Output browser version
id: browser
run: |
BROWSER_VERSION=$(sed -n '/START DEFAULT_BROWSER_VERSIONS/,/END DEFAULT_BROWSER_VERSIONS/p' src/constants.ts | grep -oP 'chrome:\s*\K\{[^}]+\}' | jq -r '.linux')
echo "browser=chrome@$BROWSER_VERSION" >> "$GITHUB_OUTPUT"
- name: Build vivliostyle/cli image
run: |
docker build -t vivliostyle/cli:ci \
--build-arg VS_CLI_VERSION=${{ steps.package.outputs.version }} \
--build-arg BROWSER=${{ steps.browser.outputs.browser }} \
.
- name: Run render-on-docker tests
env:
VIVLIOSTYLE_TEST_IMAGE: vivliostyle/cli:ci
run: |
# The container runs as the Dockerfile's `USER vivliostyle` (uid
# 1000); the runner's checkout dir is owned by a different uid.
# Pre-create the output dir owned by the runner with permissive
# perms so (a) the container can write inside it and (b) vitest's
# global teardown (running as the runner user) can rm
# container-created files afterwards.
mkdir -p tests/fixtures/render-on-docker/.vs-pdf
chmod -R a+rwX tests/fixtures/render-on-docker
npx vitest run tests/render-on-docker.test.ts

# Runs render-on-docker.test.ts in the Win+WSL hybrid NAT configuration:
# Node runs on Windows; dockerd runs inside a WSL Ubuntu distro; docker.exe
# on Windows is pointed at the WSL daemon via DOCKER_HOST. This is the
# configuration that `createDefaultWslNatRenderMode()` is designed for.
#
# The mirrored networking mode (`createDefaultWslMirroredRenderMode()`) is
# NOT covered here — see u1f992-temp/comment.md for why.
render-on-docker-wsl-nat:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
runs-on: windows-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- run: pnpm install
- run: pnpm build:cli

# Vampire/setup-wsl handles `wsl --install`, distro download, and
# default-user provisioning (which `wsl --install -d` would otherwise
# prompt for interactively).
- name: Set up WSL with Ubuntu
uses: Vampire/setup-wsl@v7
with:
distribution: Ubuntu-24.04
set-as-default: 'true'

- name: Install Docker Engine inside WSL
shell: wsl-bash {0}
run: |
set -eux
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
sudo sh /tmp/get-docker.sh
# Make dockerd listen on TCP so Windows-side docker.exe can reach
# it. 0.0.0.0:2375 is unauthenticated; acceptable for a one-shot
# CI VM but never for a real host.
sudo mkdir -p /etc/docker
echo '{"hosts":["unix:///var/run/docker.sock","tcp://0.0.0.0:2375"]}' | sudo tee /etc/docker/daemon.json
# WSL doesn't run systemd by default; start dockerd directly. The
# `-H` flags on the command line conflict with daemon.json hosts,
# so override via the systemd-style override-less direct invocation.
sudo nohup dockerd > /tmp/dockerd.log 2>&1 &
# Wait for the socket to come up
for i in $(seq 1 30); do
if sudo docker info > /dev/null 2>&1; then break; fi
sleep 1
done
if ! sudo docker info > /dev/null 2>&1; then
echo "::group::dockerd log (/tmp/dockerd.log)"
sudo cat /tmp/dockerd.log || true
echo "::endgroup::"
echo "::group::process tree"
ps auxf 2>&1 | grep -E 'docker|containerd' || true
echo "::endgroup::"
echo "::group::docker socket presence"
sudo ls -la /var/run/docker.sock /run/docker.sock 2>&1 || true
echo "::endgroup::"
echo "::group::iptables alternatives state"
update-alternatives --display iptables 2>&1 || true
update-alternatives --display ip6tables 2>&1 || true
echo "::endgroup::"
echo "::group::kernel info"
uname -a
cat /proc/version
echo "::endgroup::"
exit 1
fi
sudo docker info

- name: Output package version
id: package
shell: bash
run: echo "version=$(jq -r '.version' package.json)" >> "$GITHUB_OUTPUT"
- name: Output browser version
id: browser
shell: bash
run: |
BROWSER_VERSION=$(sed -n '/START DEFAULT_BROWSER_VERSIONS/,/END DEFAULT_BROWSER_VERSIONS/p' src/constants.ts | grep -oP 'chrome:\s*\K\{[^}]+\}' | jq -r '.linux')
echo "browser=chrome@$BROWSER_VERSION" >> "$GITHUB_OUTPUT"

- name: Build vivliostyle/cli image inside WSL
shell: wsl-bash {0}
# GitHub Actions `env:` values are set on the Windows-side shell only;
# they do NOT propagate into Vampire/setup-wsl's wsl-bash wrapper.
# Substitute the values directly via YAML expression expansion so the
# script body contains the literals. Single quotes preserve the
# Windows-style backslashes in the workspace path so bash does not
# interpret them as escape sequences.
run: |
set -eux
# The runner workspace is at /mnt/d/...; building from drvfs is
# very slow (small-file I/O over 9P). Copy to the WSL ext4 fs.
WORKSPACE=$(wslpath -u '${{ github.workspace }}')
cp -r "$WORKSPACE" /tmp/repo
cd /tmp/repo
sudo docker build -t vivliostyle/cli:ci \
--build-arg VS_CLI_VERSION='${{ steps.package.outputs.version }}' \
--build-arg BROWSER='${{ steps.browser.outputs.browser }}' \
.

- name: Allow inbound on vEthernet (WSL) interface
shell: pwsh
run: |
# The WSL VM eth0 default gateway points at this Windows interface;
# Defender Firewall blocks inbound by default, which prevents the
# container from reaching the host Vite. Loosen for this run only.
$iface = Get-NetIPAddress -AddressFamily IPv4 |
Where-Object { $_.InterfaceAlias -like 'vEthernet (WSL*' } |
Select-Object -First 1
if (-not $iface) { throw 'No vEthernet (WSL*) interface found.' }
New-NetFirewallRule -DisplayName 'Vivliostyle CI: WSL inbound' `
-Direction Inbound `
-InterfaceAlias $iface.InterfaceAlias `
-Protocol TCP -Action Allow

- name: Run render-on-docker WSL hybrid NAT test
shell: pwsh
env:
VIVLIOSTYLE_TEST_IMAGE: vivliostyle/cli:ci
VIVLIOSTYLE_TEST_WSL_HYBRID_NAT: '1'
run: |
# Resolve WSL VM IP and point Windows-side docker.exe (pre-installed
# via Docker Desktop) at the in-WSL dockerd's TCP listener.
$wslIp = (wsl -- hostname -I).Trim().Split(' ')[0]
$env:DOCKER_HOST = "tcp://${wslIp}:2375"
docker version
npx vitest run tests/render-on-docker.test.ts

build-and-push-image:
runs-on: ubuntu-latest
services:
Expand Down
Loading
Loading