generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 45
Unify bedrock & openai client creation for integ tests #340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
c53c0f2
Unify bedrock & openai client creation
zastrowm 552802b
Throw when keys are not available on CI/CD
zastrowm acd1d25
Fix OpenAI skip logic
zastrowm b2b3ef9
Increase test timeout
zastrowm 5eec98a
Merge remote-tracking branch 'upstream/main' into unify_client_creation
zastrowm 74b796d
Address PR comments
zastrowm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| /** | ||
| * Global setup that runs once before all integration tests and possibly runs in the *parent* process. | ||
| * | ||
| * _setup-test on the other hand runs in the *child* process. | ||
| */ | ||
|
|
||
| import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager' | ||
| import type { TestProject } from 'vitest/node' | ||
| import type { ProvidedContext } from 'vitest' | ||
| import { fromNodeProviderChain } from '@aws-sdk/credential-providers' | ||
|
|
||
| /** | ||
| * Load API keys as environment variables from AWS Secrets Manager | ||
| */ | ||
| async function loadApiKeysFromSecretsManager(): Promise<void> { | ||
| const client = new SecretsManagerClient({ | ||
| region: process.env.AWS_REGION || 'us-east-1', | ||
| }) | ||
|
|
||
| try { | ||
| const secretName = 'model-provider-api-key' | ||
| const command = new GetSecretValueCommand({ | ||
| SecretId: secretName, | ||
| }) | ||
| const response = await client.send(command) | ||
|
|
||
| if (response.SecretString) { | ||
| const secret = JSON.parse(response.SecretString) | ||
| // Only add API keys for currently supported providers | ||
| const supportedProviders = ['openai'] | ||
| Object.entries(secret).forEach(([key, value]) => { | ||
| if (supportedProviders.includes(key.toLowerCase())) { | ||
| process.env[`${key.toUpperCase()}_API_KEY`] = String(value) | ||
| } | ||
| }) | ||
| } | ||
| } catch (e) { | ||
| console.warn('Error retrieving secret', e) | ||
| } | ||
|
|
||
| /* | ||
| * Validate that required environment variables are set when running in GitHub Actions. | ||
| * This prevents tests from being unintentionally skipped due to missing credentials. | ||
| */ | ||
| if (process.env.GITHUB_ACTIONS !== 'true') { | ||
| console.warn('Tests running outside GitHub Actions, skipping required provider validation') | ||
| return | ||
| } | ||
|
|
||
| const requiredProviders: Set<string> = new Set(['OPENAI_API_KEY']) | ||
|
|
||
| for (const provider of requiredProviders) { | ||
| if (!process.env[provider]) { | ||
| throw new Error(`Missing required environment variables for ${provider}`) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Perform shared setup for the integration tests. | ||
| */ | ||
| export async function setup(project: TestProject): Promise<void> { | ||
| console.log('Global setup: Loading API keys from Secrets Manager...') | ||
| await loadApiKeysFromSecretsManager() | ||
| console.log('Global setup: API keys loaded into environment') | ||
|
|
||
| const isCI = !!globalThis.process.env.CI | ||
|
|
||
| project.provide('isBrowser', project.isBrowserEnabled()) | ||
| project.provide('isCI', isCI) | ||
| project.provide('provider-openai', await getOpenAITestContext(isCI)) | ||
| project.provide('provider-bedrock', await getBedrockTestContext(isCI)) | ||
| } | ||
|
|
||
| async function getOpenAITestContext(isCI: boolean): Promise<ProvidedContext['provider-openai']> { | ||
| const apiKey = process.env.OPENAI_API_KEY | ||
| const shouldSkip = !apiKey | ||
|
|
||
| if (shouldSkip) { | ||
| console.log('⏭️ OpenAI API key not available - integration tests will be skipped') | ||
| if (isCI) { | ||
| throw new Error('CI/CD should be running all tests') | ||
| } | ||
| } else { | ||
| console.log('⏭️ OpenAI API key available - integration tests will run') | ||
| } | ||
|
|
||
| return { | ||
| apiKey: apiKey, | ||
| shouldSkip: shouldSkip, | ||
| } | ||
| } | ||
|
|
||
| async function getBedrockTestContext(isCI: boolean): Promise<ProvidedContext['provider-bedrock']> { | ||
| try { | ||
| const credentialProvider = fromNodeProviderChain() | ||
| const credentials = await credentialProvider() | ||
| console.log('⏭️ Bedrock credentials available - integration tests will run') | ||
| return { | ||
| shouldSkip: false, | ||
| credentials: credentials, | ||
| } | ||
| } catch { | ||
| console.log('⏭️ Bedrock credentials not available - integration tests will be skipped') | ||
| if (isCI) { | ||
| throw new Error('CI/CD should be running all tests') | ||
| } | ||
| return { | ||
| shouldSkip: true, | ||
| credentials: undefined, | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /** | ||
| * Test setup that runs once before all integration tests, but in the *child* process. | ||
| * | ||
| * _setup-global on the other hand runs in the *parent* process. | ||
| */ | ||
|
|
||
| import { beforeAll } from 'vitest' | ||
| import { configureLogging } from '$/sdk/logging/index.js' | ||
| import { isCI } from './test-helpers.js' | ||
|
|
||
| beforeAll(() => { | ||
| // When running under CI/CD, preserve all logs including debug | ||
| if (isCI()) { | ||
| configureLogging({ | ||
| debug: (...args: unknown[]) => console.debug(...args), | ||
| info: (...args: unknown[]) => console.info(...args), | ||
| warn: (...args: unknown[]) => console.warn(...args), | ||
| error: (...args: unknown[]) => console.error(...args), | ||
| }) | ||
| } | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /** | ||
| * Contains helpers for creating various model providers that work both in node & the browser | ||
| */ | ||
|
|
||
| import { inject } from 'vitest' | ||
| import { BedrockModel, type BedrockModelOptions } from '$/sdk/models/bedrock.js' | ||
| import { OpenAIModel, type OpenAIModelOptions } from '$/sdk/models/openai.js' | ||
|
|
||
| export const bedrock = { | ||
| name: 'BedrockModel', | ||
| get skip() { | ||
| return inject('provider-bedrock').shouldSkip | ||
| }, | ||
| createModel: (options: BedrockModelOptions = {}): BedrockModel => { | ||
| const credentials = inject('provider-bedrock').credentials | ||
| if (!credentials) { | ||
| throw new Error('No Bedrock credentials provided') | ||
| } | ||
|
|
||
| return new BedrockModel({ | ||
| ...options, | ||
| clientConfig: { | ||
| ...(options.clientConfig ?? {}), | ||
| credentials: credentials, | ||
| }, | ||
| }) | ||
| }, | ||
| } | ||
|
|
||
| export const openai = { | ||
| name: 'OpenAIModel', | ||
| get skip() { | ||
| return inject('provider-openai').shouldSkip | ||
| }, | ||
| createModel: (config: OpenAIModelOptions = {}): OpenAIModel => { | ||
| const apiKey = inject('provider-openai').apiKey | ||
| if (!apiKey) { | ||
| throw new Error('No OpenAI apiKey provided') | ||
| } | ||
|
|
||
| return new OpenAIModel({ | ||
| ...config, | ||
| apiKey: apiKey, | ||
| clientConfig: { | ||
| ...(config.clientConfig ?? {}), | ||
| dangerouslyAllowBrowser: true, | ||
| }, | ||
| }) | ||
| }, | ||
| } | ||
|
|
||
| export const allProviders = [bedrock, openai] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.