diff --git a/.changeset/seven-moments-prove.md b/.changeset/seven-moments-prove.md new file mode 100644 index 00000000..3afe7349 --- /dev/null +++ b/.changeset/seven-moments-prove.md @@ -0,0 +1,5 @@ +--- +"@cartesi/cli": minor +--- + +Require cartesi-machine 0.22. Machines stored by 0.21 can't be loaded by 0.22: rebuild and redeploy every application. diff --git a/.github/workflows/cli.yaml b/.github/workflows/cli.yaml index f8438122..caf6b7ac 100644 --- a/.github/workflows/cli.yaml +++ b/.github/workflows/cli.yaml @@ -3,7 +3,9 @@ on: pull_request: paths: - ".github/workflows/cli.yaml" + - ".github/workflows/sdk.yaml" - "apps/cli/**" + - "packages/sdk/**" - "packages/tsconfig/**" concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} @@ -13,11 +15,21 @@ permissions: packages: write pull-requests: write jobs: + sdk: + uses: ./.github/workflows/sdk.yaml + secrets: inherit + permissions: + contents: read + packages: write + id-token: write + actions: write build: + needs: sdk runs-on: ubuntu-latest env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }} + SDK_TAG: pr-${{ github.event.pull_request.number }} steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -28,6 +40,20 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 + - 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: Retag SDK images + run: | + for image in sdk rollups-runtime rollups-database; do + docker pull "ghcr.io/cartesi/$image:$SDK_TAG" + docker tag "ghcr.io/cartesi/$image:$SDK_TAG" "cartesi/$image:$SDK_TAG" + done + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 @@ -45,6 +71,9 @@ jobs: - name: Test run: bun test apps/cli/ + env: + CARTESI_TEST_SDK: cartesi/sdk:${{ env.SDK_TAG }} + CARTESI_TEST_RUNTIME_VERSION: ${{ env.SDK_TAG }} - name: Coverage Report uses: 70-10/bun-coverage-report-action@6173866ce2a31456a726ff3f4c91f230bd94a9e9 # v1.0.3 diff --git a/.github/workflows/sdk.yaml b/.github/workflows/sdk.yaml index e1da4d3f..13110199 100644 --- a/.github/workflows/sdk.yaml +++ b/.github/workflows/sdk.yaml @@ -6,12 +6,8 @@ on: required: true DOCKERHUB_TOKEN: required: true - pull_request: - paths: - - ".github/workflows/sdk.yaml" - - "packages/sdk/**" concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + group: sdk-${{ github.ref }} cancel-in-progress: true permissions: contents: read @@ -83,6 +79,9 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Fetch rollups-node packages + run: ./packages/sdk/scripts/fetch-rollups-node.sh + - name: Build and push uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0 if: ${{ !startsWith(github.ref, 'refs/tags/sdk@') }} diff --git a/apps/cli/src/exec/cartesi-machine.ts b/apps/cli/src/exec/cartesi-machine.ts index 30571500..1fb60112 100644 --- a/apps/cli/src/exec/cartesi-machine.ts +++ b/apps/cli/src/exec/cartesi-machine.ts @@ -4,7 +4,7 @@ import { type ExecaOptionsDockerFallback, } from "./util.js"; -export const requiredVersion = new Range("^0.21.0"); +export const requiredVersion = new Range("^0.22.0"); export const boot = ( args: readonly string[], diff --git a/apps/cli/tests/integration/commands/fixtures/accounts-withdrawal-layouts.ts b/apps/cli/tests/integration/commands/fixtures/accounts-withdrawal-layouts.ts index 4b39f691..e05b8581 100644 --- a/apps/cli/tests/integration/commands/fixtures/accounts-withdrawal-layouts.ts +++ b/apps/cli/tests/integration/commands/fixtures/accounts-withdrawal-layouts.ts @@ -21,9 +21,6 @@ export type Layout = { at: number; // offset of data, the rest is zeros data: Buffer; }; - // TODO: the machine-tool of rollups-node v2.0.0-alpha.13 only looks for the - // accounts drive among the flash drives, unskip once it finds nvrams too - skip?: boolean; }; const scratchDrive = ` @@ -76,7 +73,6 @@ accounts_drive = true `, label: "accounts", device: "/dev/uio0", - skip: true, }, { name: "the beginning of a larger nvram", @@ -96,7 +92,6 @@ accounts_drive_size = "4Mi" label: "state", device: "/dev/uio1", accountsSize: 4 * MiB, - skip: true, }, { // like a DEX, which memory-maps its state after the accounts, from an image @@ -118,6 +113,5 @@ accounts_drive_size = "4Mi" at: 4 * MiB, data: Buffer.alloc(8 * MiB, 0xab), }, - skip: true, }, ]; diff --git a/apps/cli/tests/integration/commands/withdrawal-layouts.test.ts b/apps/cli/tests/integration/commands/withdrawal-layouts.test.ts index 350e7529..02ed278c 100644 --- a/apps/cli/tests/integration/commands/withdrawal-layouts.test.ts +++ b/apps/cli/tests/integration/commands/withdrawal-layouts.test.ts @@ -65,9 +65,7 @@ ${layout.accountsSize ? `ACCOUNTS_SIZE = "${layout.accountsSize}"` : ""} }; layouts.forEach((layout, index) => { - const describeLayout = layout.skip ? describe.skip : describe; - - describeLayout(`emergency withdrawal from ${layout.name}`, () => { + describe(`emergency withdrawal from ${layout.name}`, () => { const projectName = `layouts-${index}-${process.pid}`; let appDir: string; let cleanup: () => void; diff --git a/apps/cli/tests/integration/config.ts b/apps/cli/tests/integration/config.ts index dfdb0af4..3583327b 100644 --- a/apps/cli/tests/integration/config.ts +++ b/apps/cli/tests/integration/config.ts @@ -100,10 +100,12 @@ export async function createTemporaryCartesiApplication(options?: { // Build with the same image the snapshot readers use. Without this the // build falls back to the released SDK while the readers use TEST_SDK, // and a snapshot written by one emulator is rejected by the other. - fs.appendFileSync( - path.join(appDir, "cartesi.toml"), - `\nsdk = "${TEST_SDK}"\n`, - ); + // Prepended, so the key stays top-level whatever tables the config ends with. + const configPath = path.join(appDir, "cartesi.toml"); + const config = fs.existsSync(configPath) + ? fs.readFileSync(configPath, "utf-8") + : ""; + fs.writeFileSync(configPath, `sdk = "${TEST_SDK}"\n${config}`); // Change directory into the created application process.chdir(appDir); diff --git a/apps/cli/tests/integration/machine/nvram.test.ts b/apps/cli/tests/integration/machine/nvram.test.ts index db55bed1..a96e9b2a 100644 --- a/apps/cli/tests/integration/machine/nvram.test.ts +++ b/apps/cli/tests/integration/machine/nvram.test.ts @@ -24,7 +24,7 @@ const found = await cartesiMachine.version({ const supported = found !== null && satisfies(found.format(), cartesiMachine.requiredVersion); -// no sdk key here: the helper appends `sdk = "${TEST_SDK}"` itself, and TOML rejects duplicates +// no sdk key here: the helper prepends `sdk = "${TEST_SDK}"` itself, and TOML rejects duplicates const CONFIG = `[nvrams.input] size = "4Ki" @@ -54,7 +54,7 @@ describe.skipIf(!supported)("when booting a machine with nvrams", () => { * Boots the built application with a different entrypoint, the way the shell command does. */ const boot = async (command: string) => { - // the app's own config, which carries the sdk pin the helper appended + // the app's own config, which carries the sdk pin the helper prepended const config = parse([ fs.readFileSync(path.join(app.appDir, "cartesi.toml"), "utf-8"), ]); diff --git a/apps/cli/tests/unit/exec/cartesi-machine.test.ts b/apps/cli/tests/unit/exec/cartesi-machine.test.ts index eb0c10cc..2ef48f52 100644 --- a/apps/cli/tests/unit/exec/cartesi-machine.test.ts +++ b/apps/cli/tests/unit/exec/cartesi-machine.test.ts @@ -9,11 +9,11 @@ import { const semver = (version: string) => parse(version) as SemVer; describe("requiredVersion", () => { - it.each(["0.21.0", "0.21.3"])("should accept %s", (version) => { + it.each(["0.22.0", "0.22.3"])("should accept %s", (version) => { expect(satisfies(version, requiredVersion)).toBeTruthy(); }); - it.each(["0.20.0", "0.20.9", "0.22.0", "1.0.0"])( + it.each(["0.21.0", "0.21.9", "0.23.0", "1.0.0"])( "should reject %s", (version) => { expect(satisfies(version, requiredVersion)).toBeFalsy(); @@ -22,11 +22,11 @@ describe("requiredVersion", () => { }); describe("assertSupported", () => { - it.each(["0.21.0", "0.21.3"])("should accept %s", (version) => { + it.each(["0.22.0", "0.22.3"])("should accept %s", (version) => { expect(() => assertSupported(semver(version))).not.toThrow(); }); - it.each(["0.20.0", "0.22.0"])("should reject %s", (version) => { + it.each(["0.21.0", "0.23.0"])("should reject %s", (version) => { expect(() => assertSupported(semver(version))).toThrowError( new UnsupportedVersionError(semver(version)), ); diff --git a/packages/sdk/.gitignore b/packages/sdk/.gitignore index 85b2aef5..a8453c9c 100644 --- a/packages/sdk/.gitignore +++ b/packages/sdk/.gitignore @@ -1 +1,2 @@ build.json +rollups-node/ diff --git a/packages/sdk/Dockerfile b/packages/sdk/Dockerfile index 72af7b36..53ca58e2 100644 --- a/packages/sdk/Dockerfile +++ b/packages/sdk/Dockerfile @@ -88,7 +88,7 @@ RUN < /opt/devnet/anvil_state.json rm /tmp/prt-anvil.tar.gz echo ${CARTESI_PRT_VERSION} > /opt/devnet/PRT_VERSION @@ -160,11 +160,11 @@ ARG CARTESI_PRT_VERSION ARG TARGETARCH WORKDIR /tmp RUN </dev/null; then sha256sum "$@"; else shasum -a 256 "$@"; fi +} + +if [[ -z "$RUN_ID" ]]; then + page="$BASE/workflows/build/${BRANCH//\//%2F}" + RUN_ID="$(curl -fsSL "$page" | grep -oE 'actions/runs/[0-9]+/artifacts\.zip' | head -n1 | grep -oE '[0-9]+' || true)" + [[ -n "$RUN_ID" ]] || { echo "no successful run found at $page" >&2; exit 1; } +fi + +url="$BASE/actions/runs/$RUN_ID/artifacts.zip" +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT +curl -fsSL "$url" -o "$tmp/artifacts.zip" +unzip -q "$tmp/artifacts.zip" -d "$tmp/artifacts" + +mkdir -p "$DEST" +rm -f "$DEST"/*.deb +for arch in amd64 arm64; do + src=("$tmp"/artifacts/cartesi-rollups-node-v*_"$arch".deb) + [[ -f "${src[0]}" ]] || { echo "missing $arch .deb in run $RUN_ID" >&2; exit 1; } + cp "${src[0]}" "$DEST/cartesi-rollups-node_$arch.deb" +done + +{ + echo "run: https://github.com/cartesi/rollups-node/actions/runs/$RUN_ID" + echo "url: $url" + (cd "$DEST" && sha256 cartesi-rollups-node_*.deb) +} | tee "$DEST/SOURCE"