Skip to content

Commit a4aec93

Browse files
designcodeclaude
andauthored
chore(repo): migrate biome config and disable cognitive-complexity rule (#195)
* chore(repo): migrate biome config and disable cognitive-complexity rule Migrate biome.json to the 2.5.3 schema and the new `preset` field, and turn off noExcessiveCognitiveComplexity. The rule produced 55 non-blocking warnings, mostly on legitimately branchy CLI command handlers; disabling it clears the noise (biome check is now clean). Assisted-by: Opus 4.8 via Claude Code Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(cli): sweep the run's buckets on teardown and raise hook timeout The CLI integration suite's beforeAll timed out (30s) sweeping stale tigris-cli-test-* buckets left by prior failed runs — a self-worsening loop. Add a prefix-scoped catch-all in the top-level afterAll so every run deletes all the buckets it created (all names use testPrefix), and raise hookTimeout to 120s so a slow setup doesn't fail the suite. Assisted-by: Opus 4.8 via Claude Code Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(repo): make integration suites clean up their resources reliably - agent-kit: capture the fork/workspace cleanup handle before asserting, and track the base bucket before creating it, so a failed assertion no longer orphans fork buckets or their IAM access keys. Guard afterEach so one failed removal can't strand the rest. - storage fork/merge/rebase: push buckets to cleanup before createBucket so a create/assert failure still deletes them. - storage integration softDelete: guard each removeBucket so force- removing an already-soft-deleted bucket can't strand the others. Deliberately did not add a shared test-* bucket sweep: storage runs test files in parallel, so a per-file sweep would delete other files' in-flight buckets. Assisted-by: Opus 4.8 via Claude Code Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent db35676 commit a4aec93

6 files changed

Lines changed: 77 additions & 24 deletions

File tree

biome.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.5.0/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.5.3/schema.json",
33
"vcs": {
44
"enabled": true,
55
"clientKind": "git",
@@ -30,10 +30,10 @@
3030
"linter": {
3131
"enabled": true,
3232
"rules": {
33-
"recommended": true,
33+
"preset": "recommended",
3434
"complexity": {
3535
"noBannedTypes": "error",
36-
"noExcessiveCognitiveComplexity": "warn"
36+
"noExcessiveCognitiveComplexity": "off"
3737
},
3838
"correctness": {
3939
"noUnusedImports": "error",

packages/agent-kit/test/integration.test.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -190,23 +190,32 @@ describe.skipIf(skipTests)('createForks / teardownForks', () => {
190190

191191
afterEach(async () => {
192192
if (forkSet) {
193-
await teardownForks(forkSet);
193+
try {
194+
await teardownForks(forkSet);
195+
} catch {
196+
// best-effort — don't let a cleanup failure mask the test result
197+
}
194198
forkSet = undefined;
195199
}
196200
for (const bucket of extraBucketsToCleanup) {
197-
await removeBucket(bucket, { force: true });
201+
try {
202+
await removeBucket(bucket, { force: true });
203+
} catch {
204+
// best-effort
205+
}
198206
}
199207
extraBucketsToCleanup.length = 0;
200208
});
201209

202210
it('should create forks from a base bucket', async () => {
203211
// Create a base bucket with snapshots and data
204212
const baseBucket = uniqueName('forks-base');
213+
// Track before creating so a mid-create failure still cleans it up.
214+
extraBucketsToCleanup.push(baseBucket);
205215
const wsResult = await createWorkspace(baseBucket, {
206216
enableSnapshots: true,
207217
});
208218
expect(wsResult.error).toBeUndefined();
209-
extraBucketsToCleanup.push(baseBucket);
210219

211220
await put('dataset.json', '{"items": [1,2,3]}', {
212221
config: { bucket: baseBucket },
@@ -216,14 +225,17 @@ describe.skipIf(skipTests)('createForks / teardownForks', () => {
216225
const result = await createForks(baseBucket, 2, {
217226
prefix: uniqueName('fork'),
218227
});
228+
// Capture the handle before asserting so teardown revokes keys and deletes
229+
// fork buckets even if an assertion below throws.
230+
forkSet = result.data;
219231

220232
expect(result.error).toBeUndefined();
221233
expect(result.data!.forks).toHaveLength(2);
222234
expect(result.data!.snapshotId).toBeTruthy();
223-
forkSet = result.data!;
235+
const forks = result.data!;
224236

225237
// Verify each fork has the data from the base bucket
226-
for (const fork of forkSet.forks) {
238+
for (const fork of forks.forks) {
227239
const getResult = await get('dataset.json', 'string', {
228240
config: { bucket: fork.bucket },
229241
});
@@ -233,40 +245,44 @@ describe.skipIf(skipTests)('createForks / teardownForks', () => {
233245

234246
// Verify forks are isolated — write to fork 0, fork 1 unchanged
235247
await put('fork-0-only.txt', 'only in fork 0', {
236-
config: { bucket: forkSet.forks[0].bucket },
248+
config: { bucket: forks.forks[0].bucket },
237249
});
238250

239251
const fork1Check = await get('fork-0-only.txt', 'string', {
240-
config: { bucket: forkSet.forks[1].bucket },
252+
config: { bucket: forks.forks[1].bucket },
241253
});
242254
expect(fork1Check.error).toBeDefined();
243255
});
244256

245257
it('should create forks with scoped credentials', async () => {
246258
const baseBucket = uniqueName('forks-creds');
259+
// Track before creating so a mid-create failure still cleans it up.
260+
extraBucketsToCleanup.push(baseBucket);
247261
const wsResult = await createWorkspace(baseBucket, {
248262
enableSnapshots: true,
249263
});
250264
expect(wsResult.error).toBeUndefined();
251-
extraBucketsToCleanup.push(baseBucket);
252265

253266
const result = await createForks(baseBucket, 2, {
254267
prefix: uniqueName('fork-cred'),
255268
credentials: { role: 'Editor' },
256269
});
270+
// Capture the handle before asserting so teardown revokes the forks'
271+
// access keys even if an assertion below throws.
272+
forkSet = result.data;
257273

258274
expect(result.error).toBeUndefined();
259-
forkSet = result.data!;
275+
const forks = result.data!;
260276

261277
// Each fork should have its own credentials
262-
for (const fork of forkSet.forks) {
278+
for (const fork of forks.forks) {
263279
expect(fork.credentials).toBeDefined();
264280
expect(fork.credentials!.accessKeyId).toBeTruthy();
265281
expect(fork.credentials!.secretAccessKey).toBeTruthy();
266282
}
267283

268284
// Verify scoped credentials can write to their own fork
269-
const fork = forkSet.forks[0];
285+
const fork = forks.forks[0];
270286
const putResult = await put('scoped-write.txt', 'written with scoped key', {
271287
config: {
272288
bucket: fork.bucket,
@@ -279,16 +295,20 @@ describe.skipIf(skipTests)('createForks / teardownForks', () => {
279295

280296
it('should teardown forks cleanly', async () => {
281297
const baseBucket = uniqueName('forks-td');
298+
// Track before creating so a mid-create failure still cleans it up.
299+
extraBucketsToCleanup.push(baseBucket);
282300
const wsResult = await createWorkspace(baseBucket, {
283301
enableSnapshots: true,
284302
});
285303
expect(wsResult.error).toBeUndefined();
286-
extraBucketsToCleanup.push(baseBucket);
287304

288305
const result = await createForks(baseBucket, 2, {
289306
prefix: uniqueName('fork-td'),
290307
credentials: { role: 'Editor' },
291308
});
309+
// Capture the handle before asserting so teardown revokes keys / deletes
310+
// fork buckets if an assertion below throws.
311+
forkSet = result.data;
292312
expect(result.error).toBeUndefined();
293313
const created = result.data!;
294314

@@ -297,15 +317,14 @@ describe.skipIf(skipTests)('createForks / teardownForks', () => {
297317
// Teardown
298318
const teardown = await teardownForks(created);
299319
expect(teardown.error).toBeUndefined();
320+
// Torn down explicitly; prevent afterEach from double-tearing-down.
321+
forkSet = undefined;
300322

301323
// Verify forks are deleted
302324
for (const bucket of forkBuckets) {
303325
const info = await getBucketInfo(bucket);
304326
expect(info.error).toBeDefined();
305327
}
306-
307-
// Forks cleaned up, don't double-teardown in afterEach
308-
forkSet = undefined;
309328
});
310329
});
311330

packages/cli/test/cli.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,28 @@ describe.skipIf(skipTests)('CLI Integration Tests', () => {
377377
console.log(`Cleaning up second test bucket: ${otherBucket}`);
378378
runCli(`rm ${t3(otherBucket)}/* -f`);
379379
runCli(`rm ${t3(otherBucket)} -f`);
380+
381+
// Catch-all: delete every bucket this run created. All test bucket names
382+
// are prefixed with testPrefix, so this guarantees the suite cleans up
383+
// after itself even if a nested block's teardown was skipped by a failure.
384+
// Keeping leftovers to a minimum keeps the beforeAll stale-bucket sweep
385+
// fast (a growing sweep is what caused the setup hook to time out).
386+
const listResult = runCli('buckets list --format json');
387+
if (listResult.exitCode === 0 && listResult.stdout.trim()) {
388+
try {
389+
const parsed = JSON.parse(listResult.stdout.trim()) as {
390+
items: Array<{ name: string }>;
391+
};
392+
for (const bucket of parsed.items) {
393+
if (!bucket.name.startsWith(testPrefix)) continue;
394+
console.log(`Cleaning up leftover test bucket: ${bucket.name}`);
395+
runCli(`rm ${t3(bucket.name)}/* -r -f`);
396+
runCli(`rm ${t3(bucket.name)} -f`);
397+
}
398+
} catch {
399+
// Best-effort — don't fail teardown on cleanup errors.
400+
}
401+
}
380402
});
381403

382404
describe('ls command', () => {

packages/cli/vitest.config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ export default defineConfig({
2424
NODE_ENV: 'test',
2525
},
2626
testTimeout: 30000,
27-
hookTimeout: 30000,
27+
// Integration setup/teardown hooks do live-gateway work (bucket
28+
// create/delete, plus a best-effort sweep of stale buckets), which can
29+
// exceed 30s under load. Give hooks more headroom so a slow setup doesn't
30+
// fail the whole suite.
31+
hookTimeout: 120000,
2832
coverage: {
2933
provider: 'v8',
3034
reporter: ['text', 'json', 'html'],

packages/storage/src/test/fork-merge-rebase.integration.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ describe.skipIf(skipTests)('mergeFork integration', () => {
2828
const bucketsToCleanup: string[] = [];
2929

3030
beforeAll(async () => {
31+
// Track before creating so a create/assert failure still cleans up.
32+
bucketsToCleanup.push(sourceBucket);
3133
const src = await createBucket(sourceBucket, {
3234
enableSnapshot: true,
3335
config,
@@ -36,14 +38,14 @@ describe.skipIf(skipTests)('mergeFork integration', () => {
3638
src.error,
3739
`source bucket create failed: ${src.error?.message}`
3840
).toBeUndefined();
39-
bucketsToCleanup.push(sourceBucket);
4041

4142
// Seed the source with an object that exists before either fork is made.
4243
const seed = await put('base.txt', 'base', {
4344
config: bucketConfig(sourceBucket),
4445
});
4546
expect(seed.error).toBeUndefined();
4647

48+
bucketsToCleanup.push(forkBucket);
4749
const fork = await createBucket(forkBucket, {
4850
sourceBucketName: sourceBucket,
4951
config,
@@ -52,7 +54,6 @@ describe.skipIf(skipTests)('mergeFork integration', () => {
5254
fork.error,
5355
`fork create failed: ${fork.error?.message}`
5456
).toBeUndefined();
55-
bucketsToCleanup.push(forkBucket);
5657

5758
await waitForConsistency();
5859
}, 60_000);
@@ -126,24 +127,25 @@ describe.skipIf(skipTests)('rebaseFork integration', () => {
126127
const bucketsToCleanup: string[] = [];
127128

128129
beforeAll(async () => {
130+
// Track before creating so a create/assert failure still cleans up.
131+
bucketsToCleanup.push(sourceBucket);
129132
const src = await createBucket(sourceBucket, {
130133
enableSnapshot: true,
131134
config,
132135
});
133136
expect(src.error).toBeUndefined();
134-
bucketsToCleanup.push(sourceBucket);
135137

136138
const seed = await put('base.txt', 'base', {
137139
config: bucketConfig(sourceBucket),
138140
});
139141
expect(seed.error).toBeUndefined();
140142

143+
bucketsToCleanup.push(forkBucket);
141144
const fork = await createBucket(forkBucket, {
142145
sourceBucketName: sourceBucket,
143146
config,
144147
});
145148
expect(fork.error).toBeUndefined();
146-
bucketsToCleanup.push(forkBucket);
147149

148150
await waitForConsistency();
149151
}, 60_000);

packages/storage/src/test/integration.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,8 +928,14 @@ describe.skipIf(skipTests)('Tigris Storage Integration Tests', () => {
928928
});
929929

930930
afterAll(async () => {
931+
// Per-item guard: force-removing an already-soft-deleted bucket can
932+
// error, and one failure must not strand the remaining buckets.
931933
for (const bucket of bucketsToCleanup) {
932-
await removeBucket(bucket, { force: true, config });
934+
try {
935+
await removeBucket(bucket, { force: true, config });
936+
} catch {
937+
// best-effort cleanup
938+
}
933939
}
934940
});
935941

0 commit comments

Comments
 (0)