Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Xvfb + noVNC so you can see/steer the real Electron app
# from your browser.

FROM node:20-bookworm
FROM node:24.22.1-bookworm

# System deps for Electron / Chromium + virtual display + utils
RUN apt-get update && apt-get install -y --no-install-recommends \
Expand Down
28 changes: 26 additions & 2 deletions .devcontainer/Dockerfile.daytona-server
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,46 @@ RUN apt-get update \
git \
procps \
sudo \
&& /usr/local/share/nvm/current/bin/npm install -g pnpm@10.27.0 bun@1.3.14 \
xz-utils \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /root/.cache /root/.npm /tmp/* \
&& printf 'daytona ALL=(ALL) NOPASSWD:ALL\n' >/etc/sudoers.d/daytona-openwork \
&& chmod 0440 /etc/sudoers.d/daytona-openwork \
&& install -d -o daytona -g daytona /workspace

WORKDIR /workspace
# Replace the inherited Node default, preserving Daytona's NVM current/bin launcher path.
# Official checksums: https://nodejs.org/dist/v24.22.1/SHASUMS256.txt
RUN set -eu; \
case "$(dpkg --print-architecture)" in \
amd64) node_arch=x64; node_sha256=6c172a9ab6718f7b801fb5a7bd486af2ee5e32758086a04b84fcce2aa77095e6 ;; \
arm64) node_arch=arm64; node_sha256=dbabf7a1cbf947e6059ffad2c27b80041db97dea1e553b62afdee7f13fca336e ;; \
*) echo "Unsupported Node architecture" >&2; exit 1 ;; \
esac; \
node_tmp=$(mktemp -d); \
curl -fsSL -o "$node_tmp/node.tar.xz" "https://nodejs.org/dist/v24.22.1/node-v24.22.1-linux-$node_arch.tar.xz"; \
echo "$node_sha256 $node_tmp/node.tar.xz" | sha256sum -c -; \
node_prefix=/usr/local/share/nvm/versions/node/v24.22.1; \
mkdir -p "$node_prefix" /usr/local/share/nvm/alias; \
tar -xJf "$node_tmp/node.tar.xz" -C "$node_prefix" --strip-components=1 --no-same-owner; \
rm -rf "$node_tmp" /usr/local/share/nvm/current; \
ln -s "$node_prefix" /usr/local/share/nvm/current; \
echo v24.22.1 > /usr/local/share/nvm/alias/default; \
chown -R daytona:daytona "$node_prefix"; \
test "$(/usr/local/share/nvm/current/bin/node --version)" = v24.22.1

ENV PATH="/usr/local/share/nvm/current/bin:$PATH"
RUN test "$(node --version)" = v24.22.1 \
&& /usr/local/share/nvm/current/bin/npm install -g pnpm@10.27.0 bun@1.3.14 \
&& /usr/local/share/nvm/current/bin/npm cache clean --force

WORKDIR /workspace

# Everything under /workspace is created as the daytona user so no later
# chown layer is needed: a recursive chown in its own layer copy-on-write
# duplicates the entire baked workspace and pushed the image past the 20 GB
# snapshot limit.
USER daytona
RUN test "$(node --version)" = v24.22.1

RUN git clone --depth 1 --branch dev https://github.com/different-ai/openwork.git . \
&& mkdir -p /workspace/.openwork-daytona \
Expand Down
27 changes: 25 additions & 2 deletions .devcontainer/Dockerfile.daytona-vnc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,32 @@ FROM daytonaio/sandbox:0.6.0
USER root

RUN apt-get update \
&& apt-get install -y --no-install-recommends ffmpeg \
&& apt-get install -y --no-install-recommends ca-certificates curl ffmpeg xz-utils \
&& rm -rf /var/lib/apt/lists/*

RUN /usr/local/share/nvm/current/bin/npm install -g pnpm@10.27.0 bun
# Replace the inherited Node default, preserving Daytona's NVM current/bin launcher path.
# Official checksums: https://nodejs.org/dist/v24.22.1/SHASUMS256.txt
RUN set -eu; \
case "$(dpkg --print-architecture)" in \
amd64) node_arch=x64; node_sha256=6c172a9ab6718f7b801fb5a7bd486af2ee5e32758086a04b84fcce2aa77095e6 ;; \
arm64) node_arch=arm64; node_sha256=dbabf7a1cbf947e6059ffad2c27b80041db97dea1e553b62afdee7f13fca336e ;; \
*) echo "Unsupported Node architecture" >&2; exit 1 ;; \
esac; \
node_tmp=$(mktemp -d); \
curl -fsSL -o "$node_tmp/node.tar.xz" "https://nodejs.org/dist/v24.22.1/node-v24.22.1-linux-$node_arch.tar.xz"; \
echo "$node_sha256 $node_tmp/node.tar.xz" | sha256sum -c -; \
node_prefix=/usr/local/share/nvm/versions/node/v24.22.1; \
mkdir -p "$node_prefix" /usr/local/share/nvm/alias; \
tar -xJf "$node_tmp/node.tar.xz" -C "$node_prefix" --strip-components=1 --no-same-owner; \
rm -rf "$node_tmp" /usr/local/share/nvm/current; \
ln -s "$node_prefix" /usr/local/share/nvm/current; \
echo v24.22.1 > /usr/local/share/nvm/alias/default; \
chown -R daytona:daytona "$node_prefix"; \
test "$(/usr/local/share/nvm/current/bin/node --version)" = v24.22.1

ENV PATH="/usr/local/share/nvm/current/bin:$PATH"
RUN test "$(node --version)" = v24.22.1 \
&& /usr/local/share/nvm/current/bin/npm install -g pnpm@10.27.0 bun

WORKDIR /workspace

Expand All @@ -27,3 +49,4 @@ RUN git clone --depth 1 --branch dev https://github.com/different-ai/openwork.gi
RUN chown -R daytona:daytona /workspace

USER daytona
RUN test "$(node --version)" = v24.22.1
2 changes: 1 addition & 1 deletion .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Services:
# - MySQL 8.4 for the Den database
# - Workspace container with Node 20, Electron deps, Xvfb, noVNC
# - Workspace container with Node 24.22.1, Electron deps, Xvfb, noVNC
#
# Ports:
# - 5173 App Vite dev server (HMR)
Expand Down
89 changes: 89 additions & 0 deletions .devcontainer/node-runtime.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import assert from "node:assert/strict"
import { spawnSync } from "node:child_process"
import { mkdtempSync, mkdirSync, readFileSync, readlinkSync, rmSync, writeFileSync, existsSync } from "node:fs"
import { tmpdir } from "node:os"
import { join } from "node:path"
import { test } from "node:test"

const checksums = {
amd64: "6c172a9ab6718f7b801fb5a7bd486af2ee5e32758086a04b84fcce2aa77095e6",
arm64: "dbabf7a1cbf947e6059ffad2c27b80041db97dea1e553b62afdee7f13fca336e",
}

for (const file of ["Dockerfile.daytona-server", "Dockerfile.daytona-vnc"]) {
const source = readFileSync(new URL(file, import.meta.url), "utf8")
const block = source.match(/^RUN set -eu;[\s\S]*?(?=\n\n)/m)?.[0]
assert.ok(block, `${file} must explicitly install Node rather than inherit it`)
const script = block.slice("RUN ".length).replaceAll("\\\n", "\n")

test(`${file} pins official artifacts and preserves Daytona's launcher path`, () => {
assert.equal(spawnSync("sh", ["-n"], { input: script }).status, 0)
assert.match(script, /https:\/\/nodejs\.org\/dist\/v24\.22\.1\/node-v24\.22\.1-linux-\$node_arch\.tar\.xz/)
for (const [arch, checksum] of Object.entries(checksums)) {
assert.ok(script.includes(`${arch}) node_arch=${arch === "amd64" ? "x64" : "arm64"}; node_sha256=${checksum}`))
}
assert.ok(script.indexOf("sha256sum -c -") < script.indexOf("tar -xJf"))
assert.match(source, /ENV PATH="\/usr\/local\/share\/nvm\/current\/bin:\$PATH"/)
assert.ok(source.indexOf(block) < source.indexOf("/usr/local/share/nvm/current/bin/npm install"))
assert.match(source, /USER daytona\nRUN test "\$\(node --version\)" = v24\.22\.1/)
assert.match(source, /\bxz-utils\b/)
})

function runInstaller(arch, checksumFailure = false) {
const root = mkdtempSync(join(tmpdir(), "openwork-node-image-"))
const bin = join(root, "bin")
const nvm = join(root, "nvm")
const log = join(root, "events")
mkdirSync(bin)
const stub = (name, body) => writeFileSync(join(bin, name), `#!/bin/sh\nset -eu\n${body}\n`, { mode: 0o755 })
stub("dpkg", 'echo "$TEST_ARCH"')
stub("curl", 'test "$1" = -fsSL; test "$2" = -o; echo "$4" >> "$TEST_LOG"; echo archive > "$3"')
stub("sha256sum", `read -r checksum archive
test "$checksum" = "$TEST_CHECKSUM"
test -f "$archive"
echo verified >> "$TEST_LOG"
test "$TEST_CHECKSUM_FAILURE" = 0`)
stub("tar", `test "$1" = -xJf; test "$3" = -C
echo extracted >> "$TEST_LOG"
mkdir -p "$4/bin"
printf '#!/bin/sh\\necho v24.22.1\\n' > "$4/bin/node"
chmod +x "$4/bin/node"`)
stub("chown", ":")
const result = spawnSync("sh", ["-c", script.replaceAll("/usr/local/share/nvm", nvm)], {
encoding: "utf8",
env: { ...process.env, PATH: `${bin}:${process.env.PATH}`, TEST_ARCH: arch, TEST_LOG: log,
TEST_CHECKSUM: checksums[arch] ?? "", TEST_CHECKSUM_FAILURE: checksumFailure ? "1" : "0" },
})
return { root, nvm, result, events: existsSync(log) ? readFileSync(log, "utf8") : "" }
}

for (const arch of Object.keys(checksums)) {
test(`${file} installs ${arch} and updates both NVM current and default`, () => {
const run = runInstaller(arch)
try {
assert.equal(run.result.status, 0, run.result.stderr)
assert.equal(readlinkSync(join(run.nvm, "current")), join(run.nvm, "versions/node/v24.22.1"))
assert.equal(readFileSync(join(run.nvm, "alias/default"), "utf8"), "v24.22.1\n")
assert.match(run.events, new RegExp(`node-v24\\.22\\.1-linux-${arch === "amd64" ? "x64" : "arm64"}\\.tar\\.xz`))
assert.match(run.events, /verified\nextracted\n/)
} finally { rmSync(run.root, { recursive: true, force: true }) }
})
}

for (const [label, arch, failChecksum] of [["checksum mismatch", "amd64", true], ["unsupported architecture", "riscv64", false]]) {
test(`${file} fails closed on ${label} before extraction or activation`, () => {
const run = runInstaller(arch, failChecksum)
try {
assert.notEqual(run.result.status, 0)
assert.doesNotMatch(run.events, /extracted/)
assert.equal(existsSync(join(run.nvm, "current")), false)
} finally { rmSync(run.root, { recursive: true, force: true }) }
})
}
}

test("workspace devcontainer documentation matches the pinned runtime", () => {
const source = readFileSync(new URL("docker-compose.yml", import.meta.url), "utf8")
assert.match(source, /Workspace container with Node 24\.22\.1/)
assert.doesNotMatch(source, /Workspace container with Node 20/)
})
2 changes: 1 addition & 1 deletion .github/actions/setup-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ runs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/alpha-macos-aarch64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
Expand Down Expand Up @@ -318,7 +318,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/api-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-electron-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup Bun
uses: oven-sh/setup-bun@v2
Expand Down Expand Up @@ -94,7 +94,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup Bun
uses: oven-sh/setup-bun@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/celld-runner-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
if: steps.guard.outputs.stable == 'true'
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Gather release facts
if: steps.guard.outputs.stable == 'true' && steps.dedupe.outputs.documented == 'false'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-enterprise-mcp-mock.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-i18n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Run i18n audit
run: node scripts/i18n-audit.mjs --ci
2 changes: 1 addition & 1 deletion .github/workflows/ci-opencode-openwork.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
node-version: 24.22.1
registry-url: https://registry.npmjs.org

- name: Setup Bun for desktop channel tests
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci-openwork-ui-mcp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
node-version: 24.22.1
registry-url: https://registry.npmjs.org

- name: Setup pnpm
Expand Down Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
node-version: 24.22.1
registry-url: https://registry.npmjs.org

- name: Setup pnpm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
node-version: 24.22.1
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.4.0
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1

- name: Validate models snapshot
run: |
Expand Down Expand Up @@ -520,7 +520,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 24.22.1
- name: Validate the docs build
run: npx -y mint@4.2.868 validate
- name: Check for broken links and images
Expand Down Expand Up @@ -560,7 +560,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
node-version: 24.22.1
- name: Setup pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql-result-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
persist-credentials: false
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
node-version: 24.22.1
- name: Verify uploaded results for open pull requests
env:
GH_TOKEN: ${{ github.token }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/contributor-pr-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
sparse-checkout: .github/scripts
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 24
node-version: 24.22.1
- name: Check the commenter and bind the reviewed commit
id: authorize
env:
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
sparse-checkout: .github/scripts
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 24
node-version: 24.22.1
- name: Approve the fork's waiting test runs
env:
GH_TOKEN: ${{ github.token }}
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
sparse-checkout: .github/scripts
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 24
node-version: 24.22.1
- name: Mint the check token
id: app
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/contributor-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
sparse-checkout: .github/scripts
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 24
node-version: 24.22.1
- name: List open forks to screen
id: backfill
env:
Expand Down
Loading
Loading