diff --git a/tests/smoketests/blueprints.test.ts b/tests/smoketests/blueprints.test.ts index e9c010b65..d345dbd1f 100644 --- a/tests/smoketests/blueprints.test.ts +++ b/tests/smoketests/blueprints.test.ts @@ -1,4 +1,6 @@ +import { BlueprintView } from '@runloop/api-client/resources/blueprints'; import { makeClient, THIRTY_SECOND_TIMEOUT, uniqueName } from './utils'; +import { DevboxView } from '@runloop/api-client/resources/devboxes'; const client = makeClient(); @@ -34,17 +36,23 @@ describe('smoketest: blueprints', () => { test( 'start devbox from base blueprint by ID', async () => { - const devbox = await client.devboxes.createAndAwaitRunning( - { - blueprint_id: blueprintId!, - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }, - { - polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, - }, - ); - expect(devbox.blueprint_id).toBe(blueprintId); - await client.devboxes.shutdown(devbox.id); + let devbox: DevboxView | undefined; + try { + devbox = await client.devboxes.createAndAwaitRunning( + { + blueprint_id: blueprintId!, + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }, + { + polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, + }, + ); + expect(devbox.blueprint_id).toBe(blueprintId); + } finally { + if (devbox) { + await client.devboxes.shutdown(devbox.id); + } + } }, THIRTY_SECOND_TIMEOUT, ); @@ -52,17 +60,58 @@ describe('smoketest: blueprints', () => { test( 'start devbox from base blueprint by Name', async () => { - const devbox = await client.devboxes.createAndAwaitRunning( - { - blueprint_name: blueprintName, - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }, - { - polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, - }, - ); - expect(devbox.blueprint_id).toBeTruthy(); - await client.devboxes.shutdown(devbox.id); + let devbox: DevboxView | undefined; + try { + devbox = await client.devboxes.createAndAwaitRunning( + { + blueprint_name: blueprintName, + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }, + { + polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, + }, + ); + expect(devbox.blueprint_id).toBeTruthy(); + } finally { + if (devbox) { + await client.devboxes.shutdown(devbox.id); + } + } + }, + THIRTY_SECOND_TIMEOUT, + ); + }); + + // Only run secrets test in CI where the secret is available + (process.env['RUN_SMOKETESTS'] ? describe : describe.skip)('blueprint secrets', () => { + const secretsBlueprintName = uniqueName('bp-secrets'); + + test( + 'create blueprint with secret in Dockerfile and await build', + async () => { + let bpt: BlueprintView | undefined; + try { + bpt = await client.blueprints.createAndAwaitBuildCompleted( + { + name: secretsBlueprintName, + dockerfile: + 'FROM runloop:runloop/starter-arm64\nARG GITHUB_TOKEN\nRUN git config --global credential.helper \'!f() { echo "username=x-access-token"; echo "password=$GITHUB_TOKEN"; }; f\' && git clone https://github.com/runloopai/runloop-fe.git /workspace/runloop-fe && git config --global --unset credential.helper\nWORKDIR /workspace/runloop-fe', + secrets: { + GITHUB_TOKEN: 'GITHUB_TOKEN_FOR_SMOKETESTS', + }, + }, + { + polling: { maxAttempts: 180, pollingIntervalMs: 5_000, timeoutMs: 30 * 60 * 1000 }, + }, + ); + + expect(bpt.status).toBe('build_complete'); + expect(bpt.parameters.secrets?.['GITHUB_TOKEN']).toBe('GITHUB_TOKEN_FOR_SMOKETESTS'); + } finally { + if (bpt) { + await client.blueprints.delete(bpt.id); + } + } }, THIRTY_SECOND_TIMEOUT, ); diff --git a/tests/smoketests/devboxes.test.ts b/tests/smoketests/devboxes.test.ts index 769127698..9bb155333 100644 --- a/tests/smoketests/devboxes.test.ts +++ b/tests/smoketests/devboxes.test.ts @@ -1,3 +1,4 @@ +import { DevboxView } from '@runloop/api-client/resources/devboxes'; import { makeClient, THIRTY_SECOND_TIMEOUT, uniqueName } from './utils'; const client = makeClient(); @@ -18,12 +19,18 @@ describe('smoketest: devboxes', () => { test( 'create devbox', async () => { - const created = await client.devboxes.create({ - name: uniqueName('smoke-devbox'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }); - expect(created?.id).toBeTruthy(); - await client.devboxes.shutdown(created.id); + let devbox: DevboxView | undefined; + try { + devbox = await client.devboxes.create({ + name: uniqueName('smoke-devbox'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }); + expect(devbox?.id).toBeTruthy(); + } finally { + if (devbox) { + await client.devboxes.shutdown(devbox.id); + } + } }, THIRTY_SECOND_TIMEOUT, ); diff --git a/tests/smoketests/object-oriented/blueprint.test.ts b/tests/smoketests/object-oriented/blueprint.test.ts index d40a00e7a..fbb237996 100644 --- a/tests/smoketests/object-oriented/blueprint.test.ts +++ b/tests/smoketests/object-oriented/blueprint.test.ts @@ -1,6 +1,6 @@ import { RunloopSDK } from '@runloop/api-client'; import { makeClient, THIRTY_SECOND_TIMEOUT, uniqueName } from '../utils'; -import { Blueprint } from '@runloop/api-client/objects'; +import { Blueprint, Devbox } from '@runloop/api-client/objects'; const client = makeClient(); const sdk = new RunloopSDK({ @@ -67,15 +67,19 @@ describe('smoketest: object-oriented blueprint', () => { test('create devbox from blueprint (instance method)', async () => { expect(blueprint).toBeDefined(); // Use blueprint instance method to create devbox - const devbox = await blueprint.createDevbox({ - name: uniqueName('devbox-from-blueprint-instance'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }); - expect(devbox).toBeDefined(); - expect(devbox.id).toBeTruthy(); - - // Clean up the devbox - await devbox.shutdown(); + let devbox: Devbox | undefined; + try { + devbox = await blueprint.createDevbox({ + name: uniqueName('devbox-from-blueprint-instance'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }); + expect(devbox).toBeDefined(); + expect(devbox.id).toBeTruthy(); + } finally { + if (devbox) { + await devbox.shutdown(); + } + } }); test('delete blueprint', async () => { @@ -100,18 +104,22 @@ describe('smoketest: object-oriented blueprint', () => { test('get blueprint by ID', async () => { // First create a blueprint - const blueprint = await sdk.blueprint.create({ - name: uniqueName('sdk-blueprint-retrieve'), - dockerfile: 'FROM ubuntu:20.04', - }); - expect(blueprint.id).toBeTruthy(); - - // Retrieve it by ID - const retrieved = await sdk.blueprint.fromId(blueprint.id); - expect(retrieved.id).toBe(blueprint.id); - - // Clean up - await blueprint.delete(); + let blueprint: Blueprint | undefined; + try { + blueprint = await sdk.blueprint.create({ + name: uniqueName('sdk-blueprint-retrieve'), + dockerfile: 'FROM ubuntu:20.04', + }); + expect(blueprint?.id).toBeTruthy(); + + // Retrieve it byID + const retrieved = sdk.blueprint.fromId(blueprint.id); + expect(retrieved.id).toBe(blueprint.id); + } finally { + if (blueprint) { + await blueprint.delete(); + } + } }); }); }); diff --git a/tests/smoketests/object-oriented/devbox.test.ts b/tests/smoketests/object-oriented/devbox.test.ts index 5389ca48e..ced752842 100644 --- a/tests/smoketests/object-oriented/devbox.test.ts +++ b/tests/smoketests/object-oriented/devbox.test.ts @@ -108,19 +108,24 @@ describe('smoketest: object-oriented devbox', () => { }); test('get devbox by ID', async () => { - // First create a devbox - const devbox = await sdk.devbox.create({ - name: uniqueName('sdk-devbox-retrieve'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }); - expect(devbox.id).toBeTruthy(); + let devbox: Devbox | undefined; + try { + devbox = await sdk.devbox.create({ + name: uniqueName('sdk-devbox-retrieve'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }); + expect(devbox.id).toBeTruthy(); - // Retrieve it by ID - const retrieved = await sdk.devbox.fromId(devbox.id); - expect(retrieved.id).toBe(devbox.id); + // Retrieve it by ID + const retrieved = sdk.devbox.fromId(devbox.id); + expect(retrieved.id).toBe(devbox.id); - // Clean up - await devbox.shutdown(); + // Clean up + } finally { + if (devbox) { + await devbox.shutdown(); + } + } }); }); diff --git a/tests/smoketests/object-oriented/snapshot.test.ts b/tests/smoketests/object-oriented/snapshot.test.ts index 6162a3597..dc5bb2228 100644 --- a/tests/smoketests/object-oriented/snapshot.test.ts +++ b/tests/smoketests/object-oriented/snapshot.test.ts @@ -47,18 +47,19 @@ describe('smoketest: object-oriented snapshot', () => { test('create snapshot async from devbox', async () => { expect(devbox).toBeDefined(); - const asyncSnapshot = await devbox.snapshotDiskAsync({ - name: uniqueName('sdk-snapshot-async'), - commit_message: 'Test async snapshot from SDK', - }); - expect(asyncSnapshot).toBeDefined(); - expect(asyncSnapshot.id).toBeTruthy(); - - // Wait for it to complete - await asyncSnapshot.awaitCompleted(); - - // Clean up - await asyncSnapshot.delete(); + let asyncSnapshot: Snapshot | undefined; + try { + asyncSnapshot = await devbox.snapshotDiskAsync({ + name: uniqueName('sdk-snapshot-async'), + commit_message: 'Test async snapshot from SDK', + }); + expect(asyncSnapshot).toBeDefined(); + expect(asyncSnapshot.id).toBeTruthy(); + } finally { + if (asyncSnapshot) { + await asyncSnapshot.delete(); + } + } }); test('get snapshot info', async () => { @@ -89,27 +90,35 @@ describe('smoketest: object-oriented snapshot', () => { test('create devbox from snapshot (SDK method)', async () => { expect(snapshot).toBeDefined(); // Use SDK method to create devbox from snapshot - const newDevbox = await sdk.devbox.createFromSnapshot(snapshot.id, { - name: uniqueName('devbox-from-snapshot-sdk'), - }); - expect(newDevbox).toBeDefined(); - expect(newDevbox.id).toBeTruthy(); - - // Clean up the devbox - await newDevbox.shutdown(); + let newDevbox: Devbox | undefined; + try { + newDevbox = await sdk.devbox.createFromSnapshot(snapshot.id, { + name: uniqueName('devbox-from-snapshot-sdk'), + }); + expect(newDevbox).toBeDefined(); + expect(newDevbox.id).toBeTruthy(); + } finally { + if (newDevbox) { + await newDevbox.shutdown(); + } + } }); test('create devbox from snapshot (instance method)', async () => { expect(snapshot).toBeDefined(); // Use snapshot instance method to create devbox - const newDevbox = await snapshot.createDevbox({ - name: uniqueName('devbox-from-snapshot-instance'), - }); - expect(newDevbox).toBeDefined(); - expect(newDevbox.id).toBeTruthy(); - - // Clean up the devbox - await newDevbox.shutdown(); + let newDevbox: Devbox | undefined; + try { + newDevbox = await snapshot.createDevbox({ + name: uniqueName('devbox-from-snapshot-instance'), + }); + expect(newDevbox).toBeDefined(); + expect(newDevbox.id).toBeTruthy(); + } finally { + if (newDevbox) { + await newDevbox.shutdown(); + } + } }); test('delete snapshot', async () => { @@ -134,43 +143,56 @@ describe('smoketest: object-oriented snapshot', () => { test('list snapshots for specific devbox', async () => { // Create a devbox and snapshot - const devbox = await sdk.devbox.create({ - name: uniqueName('sdk-devbox-snapshot-list'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }); - const snapshot = await devbox.snapshotDisk({ - name: uniqueName('sdk-snapshot-list'), - commit_message: 'Test snapshot for list', - }); - - // List snapshots for this devbox - const snapshots = await sdk.snapshot.list({ devbox_id: devbox.id }); - expect(Array.isArray(snapshots)).toBe(true); - expect(snapshots.length).toBeGreaterThan(0); - - // Clean up - await snapshot.delete(); - await devbox.shutdown(); + let devbox: Devbox | undefined; + let snapshot: Snapshot | undefined; + try { + devbox = await sdk.devbox.create({ + name: uniqueName('sdk-devbox-snapshot-list'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }); + + snapshot = await devbox.snapshotDisk({ + name: uniqueName('sdk-snapshot-list'), + commit_message: 'Test snapshot for list', + }); + + const snapshots = await sdk.snapshot.list({ devbox_id: devbox.id }); + expect(Array.isArray(snapshots)).toBe(true); + expect(snapshots.length).toBeGreaterThan(0); + } finally { + if (devbox) { + await devbox.shutdown(); + } + if (snapshot) { + await snapshot.delete(); + } + } }); test('get snapshot by ID', async () => { - // Create a devbox and snapshot - const devbox = await sdk.devbox.create({ - name: uniqueName('sdk-devbox-snapshot-retrieve'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }); - const snapshot = await devbox.snapshotDisk({ - name: uniqueName('sdk-snapshot-retrieve'), - commit_message: 'Test snapshot for retrieve', - }); - - // Retrieve it by ID - const retrieved = await sdk.snapshot.fromId(snapshot.id); - expect(retrieved.id).toBe(snapshot.id); - - // Clean up - await snapshot.delete(); - await devbox.shutdown(); + let devbox: Devbox | undefined; + let snapshot: Snapshot | undefined; + try { + devbox = await sdk.devbox.create({ + name: uniqueName('sdk-devbox-snapshot-retrieve'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }); + + snapshot = await devbox.snapshotDisk({ + name: uniqueName('sdk-snapshot-retrieve'), + commit_message: 'Test snapshot for retrieve', + }); + + const retrieved = sdk.snapshot.fromId(snapshot.id); + expect(retrieved.id).toBe(snapshot.id); + } finally { + if (devbox) { + await devbox.shutdown(); + } + if (snapshot) { + await snapshot.delete(); + } + } }); }); }); diff --git a/tests/smoketests/object-oriented/storage-object.test.ts b/tests/smoketests/object-oriented/storage-object.test.ts index 66f02cb3e..9cd631f0a 100644 --- a/tests/smoketests/object-oriented/storage-object.test.ts +++ b/tests/smoketests/object-oriented/storage-object.test.ts @@ -1,5 +1,6 @@ import { RunloopSDK } from '@runloop/api-client'; import { makeClient, THIRTY_SECOND_TIMEOUT, uniqueName } from '../utils'; +import { Devbox, StorageObject } from '@runloop/api-client/objects'; const client = makeClient(); const sdk = new RunloopSDK({ @@ -14,105 +15,129 @@ describe('smoketest: object-oriented storage object', () => { test( 'create storage object', async () => { - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object'), - content_type: 'text', - metadata: { test: 'sdk-smoketest' }, - }); - expect(storageObject).toBeDefined(); - expect(storageObject.id).toBeTruthy(); - - // Clean up - await storageObject.delete(); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object'), + content_type: 'text', + metadata: { test: 'sdk-smoketest' }, + }); + expect(storageObject).toBeDefined(); + expect(storageObject.id).toBeTruthy(); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }, THIRTY_SECOND_TIMEOUT, ); test('get storage object info', async () => { - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object-info'), - content_type: 'text', - metadata: { test: 'sdk-smoketest' }, - }); - - const info = await storageObject.getInfo(); - expect(info.id).toBe(storageObject.id); - expect(info.name).toContain('sdk-storage-object-info'); - expect(info.content_type).toBe('text'); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object-info'), + content_type: 'text', + metadata: { test: 'sdk-smoketest' }, + }); - // Clean up - await storageObject.delete(); + const info = await storageObject.getInfo(); + expect(info.id).toBe(storageObject.id); + expect(info.name).toContain('sdk-storage-object-info'); + expect(info.content_type).toBe('text'); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }); test('upload content to storage object', async () => { - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object-upload'), - content_type: 'text', - metadata: { test: 'sdk-smoketest' }, - }); - - await storageObject.uploadContent('Hello from SDK storage object!'); - await storageObject.complete(); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object-upload'), + content_type: 'text', + metadata: { test: 'sdk-smoketest' }, + }); - // Verify the content was uploaded - const info = await storageObject.getInfo(); - expect(info.state).toBe('READ_ONLY'); + await storageObject.uploadContent('Hello from SDK storage object!'); + await storageObject.complete(); - // Clean up - await storageObject.delete(); + // Verify the content was uploaded + const info = await storageObject.getInfo(); + expect(info.state).toBe('READ_ONLY'); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }); test('get download URL', async () => { - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object-download'), - content_type: 'text', - metadata: { test: 'sdk-smoketest' }, - }); - - await storageObject.uploadContent('Hello from SDK storage object!'); - await storageObject.complete(); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object-download'), + content_type: 'text', + metadata: { test: 'sdk-smoketest' }, + }); - const downloadUrl = await storageObject.getDownloadUrl(3600); - expect(downloadUrl.download_url).toBeTruthy(); - expect(downloadUrl.download_url).toContain('http'); + await storageObject.uploadContent('Hello from SDK storage object!'); + await storageObject.complete(); - // Clean up - await storageObject.delete(); + const downloadUrl = await storageObject.getDownloadUrl(3600); + expect(downloadUrl.download_url).toBeTruthy(); + expect(downloadUrl.download_url).toContain('http'); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }); test('download content as text', async () => { - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object-download-text'), - content_type: 'text', - metadata: { test: 'sdk-smoketest' }, - }); - - await storageObject.uploadContent('Hello from SDK storage object!'); - await storageObject.complete(); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object-download-text'), + content_type: 'text', + metadata: { test: 'sdk-smoketest' }, + }); - const content = await storageObject.downloadAsText(); - expect(content).toBe('Hello from SDK storage object!'); + await storageObject.uploadContent('Hello from SDK storage object!'); + await storageObject.complete(); - // Clean up - await storageObject.delete(); + const content = await storageObject.downloadAsText(); + expect(content).toBe('Hello from SDK storage object!'); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }); test('download content as buffer', async () => { - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object-download-buffer'), - content_type: 'text', - metadata: { test: 'sdk-smoketest' }, - }); - - await storageObject.uploadContent('Hello from SDK storage object!'); - await storageObject.complete(); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object-download-buffer'), + content_type: 'text', + metadata: { test: 'sdk-smoketest' }, + }); - const buffer = await storageObject.downloadAsBuffer(); - expect(Buffer.isBuffer(buffer)).toBe(true); - expect(buffer.toString()).toBe('Hello from SDK storage object!'); + await storageObject.uploadContent('Hello from SDK storage object!'); + await storageObject.complete(); - // Clean up - await storageObject.delete(); + const buffer = await storageObject.downloadAsBuffer(); + expect(Buffer.isBuffer(buffer)).toBe(true); + expect(buffer.toString()).toBe('Hello from SDK storage object!'); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }); test('delete storage object', async () => { @@ -136,39 +161,44 @@ describe('smoketest: object-oriented storage object', () => { describe('static upload methods', () => { test('upload from text', async () => { - const uploaded = await sdk.storageObject.uploadFromText( - 'Hello from uploadFromText!', - uniqueName('sdk-text-upload'), - { metadata: { source: 'uploadFromText' } }, - ); - expect(uploaded).toBeDefined(); - expect(uploaded.id).toBeTruthy(); - - // Verify content - const content = await uploaded.downloadAsText(); - expect(content).toBe('Hello from uploadFromText!'); - - // Clean up - await uploaded.delete(); + let uploaded: StorageObject | undefined; + try { + uploaded = await sdk.storageObject.uploadFromText( + 'Hello from uploadFromText!', + uniqueName('sdk-text-upload'), + { metadata: { source: 'uploadFromText' } }, + ); + expect(uploaded).toBeDefined(); + expect(uploaded.id).toBeTruthy(); + + // Verify content + const content = await uploaded.downloadAsText(); + expect(content).toBe('Hello from uploadFromText!'); + } finally { + if (uploaded) { + await uploaded.delete(); + } + } }); test('upload from buffer', async () => { - const buffer = Buffer.from('Hello from uploadFromBuffer!'); - const uploaded = await sdk.storageObject.uploadFromBuffer( - buffer, - uniqueName('sdk-buffer-upload'), - 'text', - { metadata: { source: 'uploadFromBuffer' } }, - ); - expect(uploaded).toBeDefined(); - expect(uploaded.id).toBeTruthy(); - - // Verify content - const content = await uploaded.downloadAsText(); - expect(content).toBe('Hello from uploadFromBuffer!'); - - // Clean up - await uploaded.delete(); + let uploaded: StorageObject | undefined; + try { + const buffer = Buffer.from('Hello from uploadFromBuffer!'); + uploaded = await sdk.storageObject.uploadFromBuffer(buffer, uniqueName('sdk-buffer-upload'), 'text', { + metadata: { source: 'uploadFromBuffer' }, + }); + expect(uploaded).toBeDefined(); + expect(uploaded.id).toBeTruthy(); + + // Verify content + const content = await uploaded.downloadAsText(); + expect(content).toBe('Hello from uploadFromBuffer!'); + } finally { + if (uploaded) { + await uploaded.delete(); + } + } }); test('upload from file', async () => { @@ -215,85 +245,101 @@ describe('smoketest: object-oriented storage object', () => { }); test('get storage object by ID', async () => { - // First create a storage object - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-storage-object-retrieve'), - content_type: 'text', - }); - expect(storageObject.id).toBeTruthy(); - - // Retrieve it by ID - const retrieved = await sdk.storageObject.fromId(storageObject.id); - expect(retrieved.id).toBe(storageObject.id); + let storageObject: StorageObject | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-storage-object-retrieve'), + content_type: 'text', + }); + expect(storageObject.id).toBeTruthy(); - // Clean up - await storageObject.delete(); + // Retrieve it by ID + const retrieved = await sdk.storageObject.fromId(storageObject.id); + expect(retrieved.id).toBe(storageObject.id); + } finally { + if (storageObject) { + await storageObject.delete(); + } + } }); }); describe('storage object mounting to devbox', () => { test('mount storage object to devbox', async () => { - // Create a storage object with content - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-mount-object'), - content_type: 'text', - }); - await storageObject.uploadContent('Hello from mounted storage object!'); - await storageObject.complete(); - - // Create devbox with mounted storage object - const devbox = await sdk.devbox.create({ - name: uniqueName('sdk-devbox-mount'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - mounts: [ - { - type: 'object_mount', - object_id: storageObject.id, - object_path: '/home/user/mounted-data', - }, - ], - }); - expect(devbox).toBeDefined(); - expect(devbox.id).toBeTruthy(); - - // Clean up - await devbox.shutdown(); - await storageObject.delete(); + let storageObject: StorageObject | undefined; + let devbox: Devbox | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-mount-object'), + content_type: 'text', + }); + await storageObject.uploadContent('Hello from mounted storage object!'); + await storageObject.complete(); + + // Create devbox with mounted storage object + devbox = await sdk.devbox.create({ + name: uniqueName('sdk-devbox-mount'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + mounts: [ + { + type: 'object_mount', + object_id: storageObject.id, + object_path: '/home/user/mounted-data', + }, + ], + }); + expect(devbox).toBeDefined(); + expect(devbox.id).toBeTruthy(); + } finally { + if (devbox) { + await devbox.shutdown(); + } + if (storageObject) { + await storageObject.delete(); + } + } }); test('access mounted storage object in devbox', async () => { // Create a storage object with content - const storageObject = await sdk.storageObject.create({ - name: uniqueName('sdk-mount-object-access'), - content_type: 'text', - }); - await storageObject.uploadContent('Hello from mounted storage object!'); - await storageObject.complete(); - - // Create devbox with mounted storage object - const devbox = await sdk.devbox.create({ - name: uniqueName('sdk-devbox-mount-access'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - mounts: [ - { - type: 'object_mount', - object_id: storageObject.id, - object_path: '/home/user/mounted-data', - }, - ], - }); - - // List the mounted directory - const result = await devbox.cmd.exec({ command: 'ls -la /home/user/mounted-data' }); - expect(result.exitCode).toBe(0); + let storageObject: StorageObject | undefined; + let devbox: Devbox | undefined; + try { + storageObject = await sdk.storageObject.create({ + name: uniqueName('sdk-mount-object-access'), + content_type: 'text', + }); + await storageObject.uploadContent('Hello from mounted storage object!'); + await storageObject.complete(); + + // Create devbox with mounted storage object + devbox = await sdk.devbox.create({ + name: uniqueName('sdk-devbox-mount-access'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + mounts: [ + { + type: 'object_mount', + object_id: storageObject.id, + object_path: '/home/user/mounted-data', + }, + ], + }); - // Read the mounted file - const content = await devbox.file.read({ file_path: '/home/user/mounted-data' }); - expect(content).toBe('Hello from mounted storage object!'); + // List the mounted directory + const result = await devbox.cmd.exec({ command: 'ls -la /home/user/mounted-data' }); + expect(result.exitCode).toBe(0); - // Clean up - await devbox.shutdown(); - await storageObject.delete(); + // Read the mounted file + const content = await devbox.file.read({ file_path: '/home/user/mounted-data' }); + expect(content).toBe('Hello from mounted storage object!'); + } finally { + if (devbox) { + await devbox.shutdown(); + } + if (storageObject) { + await storageObject.delete(); + } + } }); }); }); diff --git a/tests/smoketests/scenarios-benchmarks.test.ts b/tests/smoketests/scenarios-benchmarks.test.ts index bdd88030d..e49ebabc5 100644 --- a/tests/smoketests/scenarios-benchmarks.test.ts +++ b/tests/smoketests/scenarios-benchmarks.test.ts @@ -1,3 +1,4 @@ +import { ScenarioRunView } from '@runloop/api-client/resources/scenarios'; import { makeClient, THIRTY_SECOND_TIMEOUT, uniqueName } from './utils'; const client = makeClient(); @@ -45,11 +46,17 @@ describe('smoketest: scenarios and benchmarks', () => { test( 'score and complete scenario run', async () => { - const scored = await client.scenarios.runs.scoreAndComplete(runId!, { - polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, - }); - expect(['completed', 'scored', 'running', 'failed', 'timeout', 'canceled']).toContain(scored.state); - await client.devboxes.shutdown(scored.devbox_id); + let scored: ScenarioRunView | undefined; + try { + scored = await client.scenarios.runs.scoreAndComplete(runId!, { + polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, + }); + expect(['completed', 'scored', 'running', 'failed', 'timeout', 'canceled']).toContain(scored.state); + } finally { + if (scored) { + await client.devboxes.shutdown(scored.devbox_id); + } + } }, THIRTY_SECOND_TIMEOUT, ); diff --git a/tests/smoketests/snapshots.test.ts b/tests/smoketests/snapshots.test.ts index 300bca410..0fb56da9f 100644 --- a/tests/smoketests/snapshots.test.ts +++ b/tests/smoketests/snapshots.test.ts @@ -1,3 +1,4 @@ +import { DevboxView } from '@runloop/api-client/resources/devboxes'; import { makeClient, uniqueName } from './utils'; const client = makeClient(); @@ -6,42 +7,47 @@ describe('smoketest: devbox snapshots', () => { let devboxId: string | undefined; let snapshotId: string | undefined; - afterAll(async () => { - if (devboxId) { - await client.devboxes.shutdown(devboxId); - } - if (snapshotId) { - await client.devboxes.diskSnapshots.delete(snapshotId); - } - }); - test('snapshot devbox', async () => { - const created = await client.devboxes.createAndAwaitRunning( - { - name: uniqueName('snap-devbox'), - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }, - { - polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, - }, - ); - devboxId = created.id; + let devbox: DevboxView | undefined; + try { + devbox = await client.devboxes.createAndAwaitRunning( + { + name: uniqueName('snap-devbox'), + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }, + { + polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, + }, + ); + devboxId = devbox.id; - const snap = await client.devboxes.snapshotDisk(devboxId!, { name: uniqueName('snap') }); - expect(snap.id).toBeTruthy(); - snapshotId = snap.id; + const snap = await client.devboxes.snapshotDisk(devboxId!, { name: uniqueName('snap') }); + expect(snap.id).toBeTruthy(); + snapshotId = snap.id; + } finally { + if (devbox) { + await client.devboxes.shutdown(devbox.id); + } + } }, 30_000); test('launch devbox from snapshot', async () => { - const launched = await client.devboxes.createAndAwaitRunning( - { - snapshot_id: snapshotId!, - launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes - }, - { - polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, - }, - ); - expect(launched.snapshot_id).toBe(snapshotId); + let devbox: DevboxView | undefined; + try { + devbox = await client.devboxes.createAndAwaitRunning( + { + snapshot_id: snapshotId!, + launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes + }, + { + polling: { maxAttempts: 120, pollingIntervalMs: 5_000, timeoutMs: 20 * 60 * 1000 }, + }, + ); + expect(devbox.snapshot_id).toBe(snapshotId); + } finally { + if (devbox) { + await client.devboxes.shutdown(devbox.id); + } + } }, 30_000); });