Skip to content
Draft
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 crates/cli/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub fn bail_machine_diagnostic(
/// the report's cause chain; the [`ExitCode`] returned by
/// [`ExitCode::from`] uses the same signals.
pub fn report_machine_error(report: &eyre::Report) {
let message = format!("{report}");
let message = format!("{report:#}");
let envelope =
JsonEnvelope::error(JsonMessage::error(diagnostic_code_for_report(report), message));
let _ = print_json(&envelope);
Expand Down
29 changes: 28 additions & 1 deletion crates/common/src/tempo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ impl TempoSponsor {
tx: &mut N::TransactionRequest,
sender: Address,
) -> Result<TempoSponsorPreview>
where
N::TransactionRequest: FoundryTransactionBuilder<N>,
{
let preview = self.attach_inner::<N>(tx, sender, true).await?;
Ok(preview)
}

/// Same as [`Self::attach_and_print`] but does not write the preview to stderr.
pub async fn attach_silent<N: Network>(
&self,
tx: &mut N::TransactionRequest,
sender: Address,
) -> Result<TempoSponsorPreview>
where
N::TransactionRequest: FoundryTransactionBuilder<N>,
{
self.attach_inner::<N>(tx, sender, false).await
}

async fn attach_inner<N: Network>(
&self,
tx: &mut N::TransactionRequest,
sender: Address,
print: bool,
) -> Result<TempoSponsorPreview>
where
N::TransactionRequest: FoundryTransactionBuilder<N>,
{
Expand All @@ -82,7 +107,9 @@ impl TempoSponsor {
valid_after: tx.valid_after().map(|v| v.get()),
digest,
};
preview.print()?;
if print {
preview.print()?;
}

let signature = if let Some(signature) = self.signature {
signature
Expand Down
79 changes: 56 additions & 23 deletions crates/forge/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ pub fn run_command(args: Forge) -> Result<()> {
CacheSubcommands::Clean(cmd) => cmd.run(),
CacheSubcommands::Ls(cmd) => cmd.run(),
},
ForgeSubcommand::Create(cmd) => global.block_on(cmd.run()),
ForgeSubcommand::Create(cmd) => {
cmd.reject_machine_unsupported_flags()?;
global.block_on(cmd.run())
}
ForgeSubcommand::Update(cmd) => cmd.run(),
ForgeSubcommand::Install(cmd) => global.block_on(cmd.run()),
ForgeSubcommand::Remove(cmd) => cmd.run(),
Expand Down Expand Up @@ -269,9 +272,11 @@ mod tests {
}

/// Every adopted command must pin its exact `command_id`, output mode,
/// and schema refs. A drift in any of those is an agent-contract break.
/// schema refs, `side_effects`, and `reads_stdin`. A drift in any of
/// those is an agent-contract break.
#[test]
fn registered_commands_pin_stable_ids() {
use foundry_cli::introspect::SideEffects;
let cmd = <Forge as clap::CommandFactory>::command();
let doc = build_document(&cmd, &REGISTRY);
fn find<'a>(
Expand All @@ -295,41 +300,69 @@ mod tests {
.unwrap_or_else(|| panic!("{id} missing from forge introspect"))
};

// (command_id, expected output_mode, expected result_schema_ref,
// expected event_schema_ref). `session_schema_ref` must be absent
// for every adopted command in this PR.
let pins: &[(&str, OutputMode, &str, Option<&str>)] = &[
("forge.build", OutputMode::Envelope, "foundry:forge.build@v1", None),
(
"forge.test",
OutputMode::Stream,
"foundry:forge.test@v1",
Some("foundry:forge.test.event@v1"),
),
(
"forge.script",
OutputMode::Stream,
"foundry:forge.script@v1",
Some("foundry:forge.script.event@v1"),
),
struct Pin {
id: &'static str,
mode: OutputMode,
result_ref: &'static str,
event_ref: Option<&'static str>,
side_effects: SideEffects,
reads_stdin: bool,
}

let pins = &[
Pin {
id: "forge.build",
mode: OutputMode::Envelope,
result_ref: "foundry:forge.build@v1",
event_ref: None,
side_effects: SideEffects::FsWrite,
reads_stdin: false,
},
Pin {
id: "forge.create",
mode: OutputMode::Envelope,
result_ref: "foundry:forge.create@v1",
event_ref: None,
side_effects: SideEffects::ChainWrite,
reads_stdin: false,
},
Pin {
id: "forge.test",
mode: OutputMode::Stream,
result_ref: "foundry:forge.test@v1",
event_ref: Some("foundry:forge.test.event@v1"),
side_effects: SideEffects::None,
reads_stdin: false,
},
Pin {
id: "forge.script",
mode: OutputMode::Stream,
result_ref: "foundry:forge.script@v1",
event_ref: Some("foundry:forge.script.event@v1"),
side_effects: SideEffects::ChainWrite,
reads_stdin: false,
},
];
for (id, mode, result_ref, event_ref) in pins {
for pin in pins {
let id = pin.id;
let info = lookup(id);
assert_eq!(info.capabilities.output_mode, *mode, "{id} output_mode drift");
assert_eq!(info.capabilities.output_mode, pin.mode, "{id} output_mode drift");
assert_eq!(
info.capabilities.result_schema_ref.as_deref(),
Some(*result_ref),
Some(pin.result_ref),
"{id} result_schema_ref drift"
);
assert_eq!(
info.capabilities.event_schema_ref.as_deref(),
*event_ref,
pin.event_ref,
"{id} event_schema_ref drift"
);
assert_eq!(
info.capabilities.session_schema_ref, None,
"{id} must not declare session_schema_ref"
);
assert_eq!(info.capabilities.side_effects, pin.side_effects, "{id} side_effects drift");
assert_eq!(info.capabilities.reads_stdin, pin.reads_stdin, "{id} reads_stdin drift");
}
}
}
Loading
Loading