Skip to content

Commit ef40b75

Browse files
lutterclaude
andcommitted
gnd: Enforce asc compiler version 0.19.23
gnd's compilation output is sensitive to asc version changes, so we now enforce that asc version 0.19.23 is installed. The version check runs before compilation and provides helpful error messages with installation instructions. For cases where bypassing the check is necessary, users can use either: - --skip-asc-version-check flag - GND_SKIP_ASC_VERSION_CHECK=1 environment variable Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent da2edf5 commit ef40b75

4 files changed

Lines changed: 73 additions & 9 deletions

File tree

gnd/src/commands/build.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ pub struct BuildOpt {
5959
/// Networks config file path
6060
#[clap(long, default_value = "networks.json")]
6161
pub network_file: PathBuf,
62+
63+
/// Skip the asc version check (use with caution)
64+
#[clap(long, env = "GND_SKIP_ASC_VERSION_CHECK")]
65+
pub skip_asc_version_check: bool,
6266
}
6367

6468
/// Result of a build operation.
@@ -238,6 +242,7 @@ async fn build_subgraph(opt: &BuildOpt) -> Result<BuildResult> {
238242
&global_file,
239243
&opt.output_format,
240244
&mut compiled_files,
245+
opt.skip_asc_version_check,
241246
)?;
242247
}
243248
}
@@ -255,6 +260,7 @@ async fn build_subgraph(opt: &BuildOpt) -> Result<BuildResult> {
255260
&global_file,
256261
&opt.output_format,
257262
&mut compiled_files,
263+
opt.skip_asc_version_check,
258264
)?;
259265
}
260266
}
@@ -551,6 +557,7 @@ fn compile_data_source_mapping(
551557
global_file: &Path,
552558
output_format: &str,
553559
compiled_files: &mut HashSet<String>,
560+
skip_version_check: bool,
554561
) -> Result<()> {
555562
let cache_key = file_hash(mapping_path)?;
556563

@@ -582,6 +589,7 @@ fn compile_data_source_mapping(
582589
global_file: global_file.to_path_buf(),
583590
output_file,
584591
output_format: output_format.to_string(),
592+
skip_version_check,
585593
};
586594

587595
compile_mapping(&options)?;
@@ -601,6 +609,7 @@ fn compile_template_mapping(
601609
global_file: &Path,
602610
output_format: &str,
603611
compiled_files: &mut HashSet<String>,
612+
skip_version_check: bool,
604613
) -> Result<()> {
605614
let cache_key = file_hash(mapping_path)?;
606615

@@ -638,6 +647,7 @@ fn compile_template_mapping(
638647
global_file: global_file.to_path_buf(),
639648
output_file,
640649
output_format: output_format.to_string(),
650+
skip_version_check,
641651
};
642652

643653
compile_mapping(&options)?;

gnd/src/commands/deploy.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ pub struct DeployOpt {
7070
/// Fork subgraph ID for debugging
7171
#[clap(long)]
7272
pub debug_fork: Option<String>,
73+
74+
/// Skip the asc version check (use with caution)
75+
#[clap(long, env = "GND_SKIP_ASC_VERSION_CHECK")]
76+
pub skip_asc_version_check: bool,
7377
}
7478

7579
/// Run the deploy command.
@@ -135,6 +139,7 @@ async fn build_and_upload(opt: &DeployOpt) -> Result<String> {
135139
ipfs: Some(opt.ipfs.clone()),
136140
network: opt.network.clone(),
137141
network_file: opt.network_file.clone(),
142+
skip_asc_version_check: opt.skip_asc_version_check,
138143
};
139144

140145
match run_build(build_opt).await? {

gnd/src/commands/publish.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ pub struct PublishOpt {
6464
/// Networks config file path
6565
#[clap(long, default_value = "networks.json")]
6666
pub network_file: PathBuf,
67+
68+
/// Skip the asc version check (use with caution)
69+
#[clap(long, env = "GND_SKIP_ASC_VERSION_CHECK")]
70+
pub skip_asc_version_check: bool,
6771
}
6872

6973
/// Run the publish command.
@@ -118,6 +122,7 @@ pub async fn run_publish(opt: PublishOpt) -> Result<()> {
118122
ipfs: Some(opt.ipfs),
119123
network: opt.network,
120124
network_file: opt.network_file,
125+
skip_asc_version_check: opt.skip_asc_version_check,
121126
};
122127

123128
match run_build(build_opt).await? {

gnd/src/compiler/asc.rs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,44 @@ pub struct AscCompileOptions {
2323
pub output_file: PathBuf,
2424
/// Output format: "wasm" or "wast".
2525
pub output_format: String,
26+
/// Skip the asc version check (use with caution).
27+
pub skip_version_check: bool,
2628
}
2729

30+
/// The required AssemblyScript compiler version.
31+
/// gnd functionality is very sensitive to asc version changes.
32+
const REQUIRED_ASC_VERSION: &str = "0.19.23";
33+
2834
/// Compile an AssemblyScript mapping file to WebAssembly.
2935
///
3036
/// This shells out to the `asc` command-line tool with the appropriate flags
3137
/// to match the graph-cli behavior.
38+
///
39+
/// Requires asc version 0.19.23 to be installed.
3240
pub fn compile_mapping(options: &AscCompileOptions) -> Result<()> {
41+
// Check that asc is available
42+
if !is_asc_available() {
43+
return Err(anyhow!(
44+
"AssemblyScript compiler (asc) not found. Please install it with:\n \
45+
npm install -g assemblyscript@{REQUIRED_ASC_VERSION}"
46+
));
47+
}
48+
49+
// Check version unless explicitly skipped
50+
if !options.skip_version_check {
51+
let version = get_asc_version()?;
52+
if version != REQUIRED_ASC_VERSION {
53+
return Err(anyhow!(
54+
"AssemblyScript compiler version mismatch: found {}, required {}.\n \
55+
Please install the correct version with:\n \
56+
npm install -g assemblyscript@{REQUIRED_ASC_VERSION}\n\n \
57+
If you know what you're doing, use --skip-asc-version-check or set GND_SKIP_ASC_VERSION_CHECK=1 to bypass this check.",
58+
version,
59+
REQUIRED_ASC_VERSION
60+
));
61+
}
62+
}
63+
3364
// Determine input and output paths relative to base_dir
3465
let input_rel = options
3566
.input_file
@@ -147,8 +178,7 @@ pub fn find_graph_ts(source_dir: &Path) -> Result<(Vec<PathBuf>, PathBuf)> {
147178
}
148179

149180
/// Check if the asc compiler is available.
150-
#[allow(dead_code)]
151-
pub fn is_asc_available() -> bool {
181+
fn is_asc_available() -> bool {
152182
Command::new("asc")
153183
.arg("--version")
154184
.output()
@@ -157,8 +187,7 @@ pub fn is_asc_available() -> bool {
157187
}
158188

159189
/// Get the asc compiler version.
160-
#[allow(dead_code)]
161-
pub fn get_asc_version() -> Result<String> {
190+
fn get_asc_version() -> Result<String> {
162191
let output = Command::new("asc")
163192
.arg("--version")
164193
.output()
@@ -168,7 +197,13 @@ pub fn get_asc_version() -> Result<String> {
168197
return Err(anyhow!("asc --version failed"));
169198
}
170199

171-
let version = String::from_utf8_lossy(&output.stdout).trim().to_string();
200+
// Output is "Version X.Y.Z", extract just the version number
201+
let version_output = String::from_utf8_lossy(&output.stdout);
202+
let version = version_output
203+
.trim()
204+
.strip_prefix("Version ")
205+
.unwrap_or(version_output.trim())
206+
.to_string();
172207
Ok(version)
173208
}
174209

@@ -207,9 +242,18 @@ mod tests {
207242
}
208243

209244
#[test]
210-
fn test_is_asc_available() {
211-
// This test just verifies the function doesn't panic
212-
// The actual result depends on whether asc is installed
213-
let _ = is_asc_available();
245+
fn test_asc_version_check() {
246+
// Skip if asc is not installed
247+
if !is_asc_available() {
248+
return;
249+
}
250+
251+
let version = get_asc_version().unwrap();
252+
// Version should be a semver-like string (e.g., "0.19.23")
253+
assert!(
254+
version.split('.').count() >= 2,
255+
"Version '{}' doesn't look like a semver",
256+
version
257+
);
214258
}
215259
}

0 commit comments

Comments
 (0)