Skip to content

Commit 4b6d67e

Browse files
authored
Merge branch 'master' into feat/lint-internal-function-used-once
2 parents 4aa4932 + 75c8f2a commit 4b6d67e

36 files changed

Lines changed: 1862 additions & 113 deletions

.github/workflows/benchmarks-dispatch.yml

Lines changed: 87 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,13 @@ jobs:
3939
script: |
4040
const usage = [
4141
'**Usage:** `derek bench <subcommand> [args]` (also `decofe bench ...`).\n',
42-
'- `bench invariant [compare-ref=REF] [timeout=N] [workers=N] [benchmark-type=property|optimization]`',
43-
'- `bench symex [compare-ref=REF] [timeout=N]`',
42+
'- `bench invariant [compare-ref=REF] [timeout=N] [workers=N] [benchmark-type=property|optimization]`\n',
43+
'- `bench symex [compare-ref=REF] [timeout=N]`\n',
44+
'- `bench test [compare-ref=REF] [timeout=N] [isolate=true|false]`\n',
45+
'- `bench build [compare-ref=REF] [timeout=N] [cache=true|false]`\n',
46+
'- `bench fuzz [compare-ref=REF] [timeout=N]`\n',
47+
'- `bench coverage [compare-ref=REF] [timeout=N]`\n',
48+
'- `bench all [compare-ref=REF] [timeout=N]`',
4449
].join('');
4550
const actor = context.payload.comment.user.login;
4651
const trustedAssociations = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']);
@@ -82,17 +87,11 @@ jobs:
8287
const subcommand = subMatch ? subMatch[1].toLowerCase() : '';
8388
const rawArgs = (subMatch ? afterBench.slice(subMatch[0].length) : afterBench).trim();
8489
85-
// Only `invariant` and `symex` are live; build/all are reserved.
86-
const supported = new Set(['invariant', 'symex']);
87-
const planned = new Set(['build', 'all']);
90+
const supported = new Set(['invariant', 'symex', 'test', 'build', 'fuzz', 'coverage', 'all']);
8891
if (!subcommand) {
8992
await failWithComment('Missing bench subcommand.');
9093
return;
9194
}
92-
if (planned.has(subcommand)) {
93-
await failWithComment(`\`bench ${subcommand}\` is not available yet.`);
94-
return;
95-
}
9695
if (!supported.has(subcommand)) {
9796
await failWithComment(`Unknown bench subcommand \`${subcommand}\`.`);
9897
return;
@@ -139,6 +138,62 @@ jobs:
139138
return { unknown, invalid };
140139
};
141140
141+
const parseFoundryBenchArgs = (opts, boolArgs = new Set()) => {
142+
const { unknown, invalid } = parseArgs(
143+
opts,
144+
new Set(['compare-ref']),
145+
new Set(['timeout']),
146+
Object.fromEntries(Array.from(boolArgs).map((key) => [key, new Set(['true', 'false'])])),
147+
);
148+
149+
const safeRef = /^[A-Za-z0-9._/-]{1,128}$/;
150+
if (!safeRef.test(opts['compare-ref'])) {
151+
invalid.push("`compare-ref` may only contain letters, numbers, '.', '_', '-', and '/'");
152+
}
153+
const timeout = Number(opts.timeout);
154+
if (!Number.isInteger(timeout) || timeout < 60 || timeout > 1800) {
155+
invalid.push('`timeout` must be between 60 and 1800 seconds');
156+
}
157+
return { unknown, invalid };
158+
};
159+
160+
const buildFoundryBenchPayload = (opts, benchmarks) => ({
161+
repository: repoFullName,
162+
event: 'foundry-bench',
163+
data: {
164+
subcommand,
165+
benchmarks,
166+
pr_number: String(context.issue.number),
167+
head_repo: pr.head.repo.full_name,
168+
actor,
169+
foundry_git_ref: pr.head.sha,
170+
compare_foundry_git_ref: opts['compare-ref'],
171+
timeout_seconds: opts.timeout,
172+
},
173+
});
174+
175+
const foundryBenchSummary = (opts, benchmarks, extra = []) => [
176+
`subcommand: \`${subcommand}\``,
177+
`PR SHA: \`${pr.head.sha.slice(0, 12)}\``,
178+
`compare-ref: \`${opts['compare-ref']}\``,
179+
`timeout: \`${opts.timeout}s\``,
180+
`benchmarks: \`${benchmarks}\``,
181+
...extra,
182+
].join(', ');
183+
184+
const foundryBenchmarksBySubcommand = {
185+
symex: 'forge_symbolic_test',
186+
fuzz: 'forge_fuzz_test',
187+
coverage: 'forge_coverage',
188+
all: [
189+
'forge_isolate_test',
190+
'forge_build_no_cache',
191+
'forge_fuzz_test',
192+
'forge_coverage',
193+
'forge_symbolic_test',
194+
].join(','),
195+
};
196+
142197
let payload;
143198
let summary;
144199
@@ -208,57 +263,46 @@ jobs:
208263
].join(', ');
209264
}
210265
211-
if (subcommand === 'symex') {
266+
if (subcommand !== 'invariant') {
212267
const opts = {
213268
'compare-ref': 'master',
214269
timeout: '600',
215270
};
216-
const { unknown, invalid } = parseArgs(
217-
opts,
218-
new Set(['compare-ref']),
219-
new Set(['timeout']),
220-
{},
221-
);
222271
223-
const safeRef = /^[A-Za-z0-9._/-]{1,128}$/;
224-
if (!safeRef.test(opts['compare-ref'])) {
225-
invalid.push("`compare-ref` may only contain letters, numbers, '.', '_', '-', and '/'");
272+
const boolArgs = new Set();
273+
if (subcommand === 'test') {
274+
opts.isolate = 'true';
275+
boolArgs.add('isolate');
226276
}
227-
const timeout = Number(opts.timeout);
228-
if (!Number.isInteger(timeout) || timeout < 60 || timeout > 1800) {
229-
invalid.push('`timeout` must be between 60 and 1800 seconds');
277+
if (subcommand === 'build') {
278+
opts.cache = 'false';
279+
boolArgs.add('cache');
280+
}
281+
282+
const { unknown, invalid } = parseFoundryBenchArgs(opts, boolArgs);
283+
284+
let benchmarks = foundryBenchmarksBySubcommand[subcommand];
285+
const extra = [];
286+
if (subcommand === 'test') {
287+
benchmarks = opts.isolate === 'true' ? 'forge_isolate_test' : 'forge_test';
288+
extra.push(`isolate: \`${opts.isolate}\``);
289+
} else if (subcommand === 'build') {
290+
benchmarks = opts.cache === 'true' ? 'forge_build_with_cache' : 'forge_build_no_cache';
291+
extra.push(`cache: \`${opts.cache}\``);
230292
}
231293
232294
const errors = [];
233295
if (unknown.length) errors.push(`Unknown argument(s): \`${unknown.join('`, `')}\``);
234296
if (invalid.length) errors.push(`Invalid value(s): ${invalid.join(', ')}`);
235297
if (errors.length) {
236-
await failWithComment(`Invalid \`bench symex\` command\n\n${errors.join('\n')}`);
298+
await failWithComment(`Invalid \`bench ${subcommand}\` command\n\n${errors.join('\n')}`);
237299
return;
238300
}
239301
240302
// PR identity + safe knobs only; benchmark targets and pod sizing
241303
// are owned by the server-side foundry-bench workflow.
242-
payload = {
243-
repository: repoFullName,
244-
event: 'foundry-bench',
245-
data: {
246-
subcommand: 'symex',
247-
pr_number: String(context.issue.number),
248-
head_repo: pr.head.repo.full_name,
249-
actor,
250-
foundry_git_ref: pr.head.sha,
251-
compare_foundry_git_ref: opts['compare-ref'],
252-
timeout_seconds: opts.timeout,
253-
},
254-
};
255-
256-
summary = [
257-
`subcommand: \`symex\``,
258-
`PR SHA: \`${pr.head.sha.slice(0, 12)}\``,
259-
`compare-ref: \`${opts['compare-ref']}\``,
260-
`timeout: \`${opts.timeout}s\``,
261-
].join(', ');
304+
payload = buildFoundryBenchPayload(opts, benchmarks);
305+
summary = foundryBenchSummary(opts, benchmarks, extra);
262306
}
263307
264308
core.setOutput('actor', actor);

Cargo.lock

Lines changed: 28 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benches/src/lib.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -557,22 +557,20 @@ impl BenchmarkProject {
557557
)
558558
}
559559

560-
/// Benchmark forge test with --no-isolate flag
561-
pub fn bench_forge_no_isolate_test(
560+
/// Benchmark forge test with isolate mode
561+
pub fn bench_forge_isolate_test(
562562
&self,
563563
version: &str,
564564
runs: u32,
565565
verbose: bool,
566566
) -> Result<HyperfineResult> {
567567
// Build before running tests
568568
self.hyperfine(
569-
"forge_no_isolate_test",
569+
"forge_isolate_test",
570570
version,
571-
&self.cmd(
572-
"FOUNDRY_DYNAMIC_TEST_LINKING=false FOUNDRY_ISOLATE=false forge test --no-isolate",
573-
),
571+
&self.cmd("FOUNDRY_DYNAMIC_TEST_LINKING=false FOUNDRY_ISOLATE=true forge test"),
574572
runs,
575-
Some("FOUNDRY_DYNAMIC_TEST_LINKING=false FOUNDRY_ISOLATE=false forge build"),
573+
Some("FOUNDRY_DYNAMIC_TEST_LINKING=false FOUNDRY_ISOLATE=true forge build"),
576574
None,
577575
None,
578576
verbose,
@@ -678,7 +676,7 @@ impl BenchmarkProject {
678676
"forge_build_with_cache" => self.bench_forge_build_with_cache(version, runs, verbose),
679677
"forge_fuzz_test" => self.bench_forge_fuzz_test(version, runs, verbose),
680678
"forge_coverage" => self.bench_forge_coverage(version, runs, verbose),
681-
"forge_no_isolate_test" => self.bench_forge_no_isolate_test(version, runs, verbose),
679+
"forge_isolate_test" => self.bench_forge_isolate_test(version, runs, verbose),
682680
"forge_symbolic_test" => self.bench_forge_symbolic_test(version, runs, verbose),
683681
_ => eyre::bail!("Unknown benchmark: {}", benchmark),
684682
}

benches/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const ALL_BENCHMARKS: [&str; 7] = [
1515
"forge_build_with_cache",
1616
"forge_fuzz_test",
1717
"forge_coverage",
18-
"forge_no_isolate_test",
18+
"forge_isolate_test",
1919
"forge_symbolic_test",
2020
];
2121

benches/src/results.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ pub fn format_benchmark_name(name: &str) -> String {
304304
"forge_build_with_cache" => "Forge Build (With Cache)",
305305
"forge_fuzz_test" => "Forge Fuzz Test",
306306
"forge_coverage" => "Forge Coverage",
307-
"forge_no_isolate_test" => "Forge Test (No Isolate)",
307+
"forge_isolate_test" => "Forge Test (Isolated)",
308308
"forge_symbolic_test" => "Forge Symbolic Test",
309309
_ => name,
310310
}

0 commit comments

Comments
 (0)