Skip to content

Commit 4a19328

Browse files
committed
refactor(devnet): Improve anvil version detection and parsing.
1 parent 5625142 commit 4a19328

4 files changed

Lines changed: 82 additions & 10 deletions

File tree

.changeset/shiny-tables-divide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cartesi/devnet": patch
3+
---
4+
5+
Refactor anvil version detection by normalizing the stdout and recovering a clean semver of the normalized object. Throws errors to provide feedback accordingly.

bun.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/devnet/anvil.ts

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,68 @@
11
import { $ } from "bun";
22
import pRetry from "p-retry";
3+
import { SemVer } from "semver";
4+
5+
/**
6+
* Represents the output of the `anvil --version` command after parsing it into a structured format.
7+
* Type defined based on anvil version 1.4.3-v1.4.3 output.
8+
*
9+
* @example
10+
* // anvil Version: 1.4.3-v1.4.3
11+
* // Commit SHA: fa9f934bdac4bcf57e694e852a61997dda90668a
12+
* // Build Timestamp: 2025-10-22T04:37:38.758664000Z (1761107858)
13+
* // Build Profile: maxperf
14+
*
15+
*/
16+
type AnvilVersionStdout = {
17+
anvil_version: string;
18+
commit_sha: string;
19+
build_timestamp: string;
20+
build_profile: string;
21+
};
22+
23+
type AnvilVersionStdoutKeys = keyof AnvilVersionStdout;
24+
25+
const normalizeAnvilVersionOutput = (output: string) => {
26+
return output.split("\n").reduce(
27+
(curr, next) => {
28+
const trimmedLine = next.trim();
29+
const firstColonIndex = trimmedLine.indexOf(":");
30+
31+
if (firstColonIndex === -1) return curr;
32+
33+
const prop = trimmedLine.slice(0, firstColonIndex);
34+
const value = trimmedLine.slice(firstColonIndex + 1);
35+
const key = prop
36+
.trim()
37+
.toLowerCase()
38+
.replace(/\s+/g, "_") as AnvilVersionStdoutKeys;
39+
40+
if (key && value) {
41+
curr[key] = value.trim();
42+
}
43+
44+
return curr;
45+
},
46+
{} as Partial<AnvilVersionStdout>,
47+
);
48+
};
49+
50+
/**
51+
* Get the clean version of an anvil version string.
52+
* Anvil uses semver with a quirk by suffixing the version with tag-names e.g. 1.4.3-v1.4.3,
53+
* so we need to parse it with semver and get the clean version.
54+
* @param anvilVersion
55+
* @returns
56+
*/
57+
const getCleanVersion = (anvilVersion: string) => {
58+
try {
59+
const semver = new SemVer(anvilVersion, { loose: true });
60+
return `${semver.major}.${semver.minor}.${semver.patch}`;
61+
} catch {
62+
// If the version is not a valid semver, return null
63+
return null;
64+
}
65+
};
366

467
/**
568
* Get the installed anvil version
@@ -8,19 +71,21 @@ import pRetry from "p-retry";
871
export const version = async () => {
972
const output = await $`anvil --version`.text();
1073

11-
// anvil Version: 1.4.3-v1.4.3
12-
// Commit SHA: fa9f934bdac4bcf57e694e852a61997dda90668a
13-
// Build Timestamp: 2025-10-22T04:37:38.758664000Z (1761107858)
14-
// Build Profile: maxperf
74+
const data = normalizeAnvilVersionOutput(output);
1575

16-
// parse the output to get the version
17-
const versionMatch = output.match(
18-
/Version: (\d+\.\d+\.\d+)-v(\d+\.\d+\.\d+)/,
19-
);
20-
if (!versionMatch) {
76+
if (!data.anvil_version) {
2177
throw new Error("Failed to parse anvil version. Is anvil installed?");
2278
}
23-
return versionMatch[1];
79+
80+
const cleanVersion = getCleanVersion(data.anvil_version);
81+
82+
if (!cleanVersion) {
83+
throw new Error(
84+
`Anvil version "${data.anvil_version}" is not a valid semver.`,
85+
);
86+
}
87+
88+
return cleanVersion;
2489
};
2590

2691
type StartOptions = {

packages/devnet/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"devDependencies": {
1818
"@types/bun": "^1.3.9",
1919
"@types/fs-extra": "^11.0.4",
20+
"@types/semver": "^7.7.1",
2021
"fs-extra": "^11.3.2",
2122
"listr2": "^10.1.0",
2223
"modern-tar": "^0.7.3",

0 commit comments

Comments
 (0)