Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e85e6e4
feat(sdk): Include devnet package version in the target folder
brunomenezes Jul 17, 2026
460a270
chore(sdk): cartesi-base-image debian:trixie to latest.
brunomenezes Aug 4, 2026
04c018d
feat(sdk): Bump image and linux kernel, machine-emulator. Add machine…
brunomenezes Aug 4, 2026
6dac888
refactor(sdk): Remove contract address listing from the devnet script.
brunomenezes Aug 17, 2026
2fabd46
refactor(sdk): Fetch the anvil state from the cartesi/dave release.
brunomenezes Aug 17, 2026
0a66b6f
chore(sdk): Bump anvil/foundry to 1.5.1 and prt to 3.0.0-alpha.4.
brunomenezes Aug 17, 2026
d40510e
chore(sdk): Bump prt to 3.0.0-alpha.5 and validate its tarball checksum.
brunomenezes Sep 29, 2026
6012d4f
chore(sdk): Bump rollups-node to 2.0.0-alpha.13.
brunomenezes Oct 3, 2026
19673ca
refactor(cli): extract machine argument assembly into buildMachineArgs
brunomenezes Aug 17, 2026
bb480f2
feat(cli): parse [nvrams] section of cartesi.toml
brunomenezes Aug 17, 2026
87ff888
feat(cli): pass nvrams to cartesi-machine as --nvram flags
brunomenezes Aug 17, 2026
a036b23
feat(cli): build nvram backing images
brunomenezes Aug 17, 2026
20758fe
feat(cli): verify nvram images are built before opening a shell
brunomenezes Aug 17, 2026
e96c50b
chore(cli): require cartesi-machine 0.21.0
brunomenezes Aug 17, 2026
0b191de
fix(cli): honor forceDocker when checking the cartesi-machine version
brunomenezes Aug 18, 2026
370bd54
feat(cli): add a cartesi-machine version check
brunomenezes Aug 18, 2026
55777c2
feat(cli): fail early when the cartesi-machine version is unsupported
brunomenezes Aug 18, 2026
3cec013
test(cli): allow overriding the sdk image used in integration tests
brunomenezes Aug 18, 2026
f2490cf
test(cli): Adjust cartesi-machine-stored-hash logic and tests.
brunomenezes Aug 18, 2026
2269e8b
test(cli): Add nvram integration tests.
brunomenezes Aug 18, 2026
2d4fe71
wip(cli): Point CI integration tests at the PR's SDK image.
brunomenezes Oct 3, 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/clear-falcons-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/cli": patch
---

Fix the cartesi-machine version check ignoring its `forceDocker` option, which made it report the version of the host binary instead of the one inside the SDK image.
5 changes: 5 additions & 0 deletions .changeset/every-banks-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/sdk": patch
---

Bump cartesi-base-image debian:trixie to latest version.
5 changes: 5 additions & 0 deletions .changeset/free-facts-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/cli": patch
---

`build` and `shell` now check the cartesi-machine version before booting and stop with an explicit message when it is unsupported, instead of surfacing the emulator's `unrecognized option` traceback.
5 changes: 5 additions & 0 deletions .changeset/fresh-pumas-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/sdk": patch
---

Bump anvil and foundry to 1.5.1, and the cartesi-rollups-prt release providing the anvil state to 3.0.0-alpha.5.
5 changes: 5 additions & 0 deletions .changeset/lucky-pandas-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/sdk": patch
---

Bump cartesi-rollups-node to 2.0.0-alpha.13, which requires machine-emulator 0.21.0.
5 changes: 5 additions & 0 deletions .changeset/small-carrots-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/sdk": patch
---

Bump image-kernel to 0.21.0, linux-kernel to 6.5.13-ctsi-2-v0.21.0 and machine-emulator to 0.21.0. Add machine-emulator dependency lua-lpeg
5 changes: 5 additions & 0 deletions .changeset/tidy-owls-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/sdk": patch
---

Drop the @cartesi/devnet dependency from the image. The anvil state dump is now downloaded directly from the cartesi/dave release selected by CARTESI_PRT_VERSION, so the image no longer ships /usr/share/cartesi/deployments nor DEVNET_VERSION. A PRT_VERSION file is written instead.
5 changes: 5 additions & 0 deletions .changeset/tired-lights-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/cli": patch
---

Add support for `nvrams` in `cartesi.toml`. An nvram is a raw range of bytes the guest reaches through a `/dev/uio*` device, with no filesystem and no mount point, so writes are visible to the emulator without a page cache in between. Declare one with `[nvrams.<label>]` and either `size`, for a range filled with zeros, or `filename`, pointing at an existing raw image whose size defines the range. Add `shared` so guest writes are persisted to the image, and `user` so the unprivileged entrypoint user can write to it. Up to 8 nvrams are supported, their labels cannot collide with drive labels, and sizes must be a multiple of 4Ki.
5 changes: 5 additions & 0 deletions .changeset/violet-flies-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/cli": patch
---

Require cartesi-machine 0.21.0. The `nvrams` configuration depends on its `--nvram` option, so the default SDK image has to be bumped to one shipping 0.21.0, and a host install of previous version will no longer work.
5 changes: 5 additions & 0 deletions .changeset/wild-camels-sink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/cli": patch
---

`doctor` now reports the cartesi-machine version and fails when it does not satisfy the version required by the CLI.
12 changes: 12 additions & 0 deletions .github/workflows/cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
paths:
- ".github/workflows/cli.yaml"
- "apps/cli/**"
- "packages/sdk/**"
- "packages/tsconfig/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
Expand All @@ -18,6 +19,9 @@ jobs:
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
# TEMPORARY: run the integration tests against the SDK image sdk.yaml
# builds for this PR, instead of the released cartesi/sdk version.
CARTESI_TEST_SDK: ghcr.io/cartesi/sdk:pr-${{ github.event.number }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -41,6 +45,14 @@ jobs:
- name: Build
run: bun run build --filter @cartesi/cli

# TEMPORARY: needed to pull the PR-tagged SDK image referenced by CARTESI_TEST_SDK.
- name: Login to GitHub Container Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Test
run: bun test apps/cli/

Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/builder/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export { build as buildDirectory } from "./directory.js";
export { build as buildDocker } from "./docker.js";
export { build as buildEmpty } from "./empty.js";
export { build as buildNone } from "./none.js";
export { build as buildNvram } from "./nvram.js";
export { build as buildTar } from "./tar.js";
47 changes: 47 additions & 0 deletions apps/cli/src/builder/nvram.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import fs from "fs-extra";
import path from "node:path";
import {
MissingNvramSourceError,
NVRAM_ALIGNMENT,
type NvramConfig,
nvramHasImage,
nvramImageFilename,
} from "../config.js";

export const build = async (
label: string,
nvram: NvramConfig,
destination: string,
): Promise<void> => {
// a pristine nvram needs no image, cartesi-machine fills its range with zeros
if (!nvramHasImage(nvram)) {
return;
}

const target = path.join(destination, nvramImageFilename(label));
const source = nvram.filename;

if (source === undefined) {
// shared with no image of its own, start it filled with zeros
if (nvram.size === undefined) {
throw new MissingNvramSourceError(label);
}
await fs.writeFile(target, Buffer.alloc(nvram.size));
return;
}

const { size } = await fs.stat(source);
if (nvram.size !== undefined && nvram.size !== size) {
throw new Error(
`Size ${nvram.size} of nvram '${label}' does not match the ${size} bytes of ${source}`,
);
}
if (size % NVRAM_ALIGNMENT !== 0) {
throw new Error(
`Image ${source} of nvram '${label}' has ${size} bytes, which is not a multiple of ${NVRAM_ALIGNMENT}`,
);
}

// copy it into the destination, so it is reachable when running inside the sdk image
await fs.copyFile(source, target);
};
68 changes: 51 additions & 17 deletions apps/cli/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import {
buildDocker,
buildEmpty,
buildNone,
buildNvram,
buildTar,
} from "../builder/index.js";
import type { Config, DriveConfig, ImageInfo } from "../config.js";
import type { Config, DriveConfig, ImageInfo, NvramConfig } from "../config.js";
import { bootMachine } from "../machine.js";

// context for Listr build tasks
Expand Down Expand Up @@ -79,6 +80,17 @@ const buildDriveTask = (
},
});

const buildNvramTask = (
label: string,
nvram: NvramConfig,
): ListrTask<BuildContext> => ({
title: `Building nvram ${chalk.cyan(label)}`,
task: async (ctx, task) => {
await buildNvram(label, nvram, ctx.destination);
task.title = `Build nvram ${chalk.cyan(label)}`;
},
});

export const createBuildCommand = () => {
return new Command("build")
.description(
Expand Down Expand Up @@ -129,23 +141,45 @@ export const createBuildCommand = () => {
([name, drive]) => buildDriveTask(name, drive),
);

const builds = new Listr(
[
{
title: "Build drives",
task: async (_ctx, task) => {
return task.newListr(driveTasks, {
concurrent: true,
rendererOptions: {
collapseSubtasks: false,
},
ctx,
});
},
},
],
{ ctx, renderer: verbose ? "verbose" : "default" },
// tasks to build the images backing nvrams, pristine ones need none
const nvramTasks = Object.entries(config.nvrams).map(
([label, nvram]) => buildNvramTask(label, nvram),
);

const groups: ListrTask<BuildContext>[] = [
{
title: "Build drives",
task: async (_ctx, task) => {
return task.newListr(driveTasks, {
concurrent: true,
rendererOptions: {
collapseSubtasks: false,
},
ctx,
});
},
},
];

if (nvramTasks.length > 0) {
groups.push({
title: "Build nvrams",
task: async (_ctx, task) => {
return task.newListr(nvramTasks, {
concurrent: true,
rendererOptions: {
collapseSubtasks: false,
},
ctx,
});
},
});
}

const builds = new Listr(groups, {
ctx,
renderer: verbose ? "verbose" : "default",
});
const result = await builds.run();

// if only build drives, quit here
Expand Down
27 changes: 27 additions & 0 deletions apps/cli/src/commands/doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import chalk from "chalk";
import { execa } from "execa";
import ora, { type Ora } from "ora";
import semver from "semver";
import { DEFAULT_SDK_IMAGE, DEFAULT_SDK_VERSION } from "../config.js";
import { cartesiMachine } from "../exec/index.js";

const MINIMUM_DOCKER_VERSION = "25.0.0"; // Replace with our minimum required Docker version
const MINIMUM_DOCKER_COMPOSE_VERSION = "2.24.0"; // Replace with our minimum required Docker Compose version
Expand Down Expand Up @@ -119,13 +121,38 @@ const checkBuildx = async (progress: Ora): Promise<true | never> => {
return true;
};

const checkCartesiMachine = async (progress: Ora): Promise<true | never> => {
progress.start("Checking Cartesi Machine version...");

// doctor does not read cartesi.toml, so check against the default sdk image. the host binary
// still takes precedence, which is the install most likely to be out of date
const v = await cartesiMachine.version({
image: `${DEFAULT_SDK_IMAGE}:${DEFAULT_SDK_VERSION}`,
});

if (v === null) {
throw new Error(
"Could not determine the Cartesi Machine version. Check that Docker is running.",
);
}
if (!semver.satisfies(v.format(), cartesiMachine.requiredVersion)) {
throw new Error(
`Unsupported Cartesi Machine version. Required version is ${cartesiMachine.requiredVersion.raw}. Installed version is ${v.format()}.`,
);
}
progress.succeed(`Cartesi Machine ${chalk.cyan(v.format())}`);

return true;
};

export const createDoctorCommand = () => {
return new Command("doctor").action(async () => {
const progress = ora();
try {
await checkDocker(progress);
await checkCompose(progress);
await checkBuildx(progress);
await checkCartesiMachine(progress);
progress.succeed("Your system is ready.");
} catch (e: unknown) {
progress.fail((e as Error).message);
Expand Down
12 changes: 12 additions & 0 deletions apps/cli/src/commands/shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ExecaError } from "execa";
import fs from "fs-extra";
import path from "node:path";
import { getApplicationConfig, getContextPath } from "../base.js";
import { nvramHasImage, nvramImageFilename } from "../config.js";
import { bootMachine } from "../machine.js";

export const createShellCommand = () => {
Expand Down Expand Up @@ -33,6 +34,17 @@ export const createShellCommand = () => {
}
}

// check if all nvrams backed by an image are built, pristine ones have none
for (const [label, nvram] of Object.entries(config.nvrams)) {
if (!nvramHasImage(nvram)) {
continue;
}
const pathname = getContextPath(nvramImageFilename(label));
if (!fs.existsSync(pathname)) {
throw new Error(`nvram '${label}' not built, run 'build'`);
}
}

// create shell entrypoint
config.machine.entrypoint = command;

Expand Down
Loading
Loading