-
Notifications
You must be signed in to change notification settings - Fork 438
refactor: unify environment variable structure and improve author resolution logic #359
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,16 +15,22 @@ export const ENVIRONMENT: Environment = isEnvironment(envValue) ? envValue : 'de | |
|
|
||
| /** | ||
| * Environment-specific configuration. | ||
| * | ||
| * Base URL vars (BRV_IAM_BASE_URL, BRV_COGIT_BASE_URL, BRV_LLM_BASE_URL) | ||
| * store only the root domain (e.g., http://localhost:8080). | ||
| * API version paths (/api/v1, /api/v3) are appended at the point of use. | ||
| * | ||
| * OIDC URLs are derived from iamBaseUrl; no separate env vars needed. | ||
| */ | ||
| type EnvironmentConfig = { | ||
| apiBaseUrl: string | ||
| authorizationUrl: string | ||
| clientId: string | ||
| cogitApiBaseUrl: string | ||
| cogitBaseUrl: string | ||
| gitRemoteBaseUrl: string | ||
| hubRegistryUrl: string | ||
| iamBaseUrl: string | ||
| issuerUrl: string | ||
| llmApiBaseUrl: string | ||
| llmBaseUrl: string | ||
| scopes: string[] | ||
| tokenUrl: string | ||
| webAppUrl: string | ||
|
|
@@ -51,19 +57,24 @@ const readRequiredEnv = (name: string): string => { | |
| return value | ||
| } | ||
|
|
||
| export const getCurrentConfig = (): EnvironmentConfig => ({ | ||
| apiBaseUrl: readRequiredEnv('BRV_API_BASE_URL'), | ||
| authorizationUrl: readRequiredEnv('BRV_AUTHORIZATION_URL'), | ||
| clientId: DEFAULTS.clientId, | ||
| cogitApiBaseUrl: readRequiredEnv('BRV_COGIT_API_BASE_URL'), | ||
| gitRemoteBaseUrl: readRequiredEnv('BRV_GIT_REMOTE_BASE_URL'), | ||
| hubRegistryUrl: DEFAULTS.hubRegistryUrl, | ||
| issuerUrl: readRequiredEnv('BRV_ISSUER_URL'), | ||
| llmApiBaseUrl: readRequiredEnv('BRV_LLM_API_BASE_URL'), | ||
| scopes: [...DEFAULTS.scopes[ENVIRONMENT]], | ||
| tokenUrl: readRequiredEnv('BRV_TOKEN_URL'), | ||
| webAppUrl: readRequiredEnv('BRV_WEB_APP_URL'), | ||
| }) | ||
| export const getCurrentConfig = (): EnvironmentConfig => { | ||
| const iamBaseUrl = readRequiredEnv('BRV_IAM_BASE_URL') | ||
| const oidcBase = `${iamBaseUrl}/api/v1/oidc` | ||
|
|
||
| return { | ||
| authorizationUrl: `${oidcBase}/authorize`, | ||
| clientId: DEFAULTS.clientId, | ||
| cogitBaseUrl: readRequiredEnv('BRV_COGIT_BASE_URL'), | ||
| gitRemoteBaseUrl: readRequiredEnv('BRV_GIT_REMOTE_BASE_URL'), | ||
| hubRegistryUrl: DEFAULTS.hubRegistryUrl, | ||
| iamBaseUrl, | ||
| issuerUrl: oidcBase, | ||
| llmBaseUrl: readRequiredEnv('BRV_LLM_BASE_URL'), | ||
| scopes: [...DEFAULTS.scopes[ENVIRONMENT]], | ||
| tokenUrl: `${oidcBase}/token`, | ||
| webAppUrl: readRequiredEnv('BRV_WEB_APP_URL'), | ||
| } | ||
| } | ||
|
|
||
| export const getGitRemoteBaseUrl = (): string => | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick (consistency): |
||
| process.env.BRV_GIT_REMOTE_BASE_URL ?? 'https://byterover.dev' | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -101,9 +101,10 @@ export async function setupFeatureHandlers({ | |||||
| const envConfig = getCurrentConfig() | ||||||
| const tokenStore = createTokenStore() | ||||||
| const projectConfigStore = new ProjectConfigStore() | ||||||
| const userService = new HttpUserService({apiBaseUrl: envConfig.apiBaseUrl}) | ||||||
| const teamService = new HttpTeamService({apiBaseUrl: envConfig.apiBaseUrl}) | ||||||
| const spaceService = new HttpSpaceService({apiBaseUrl: envConfig.apiBaseUrl}) | ||||||
| const iamApiV1 = `${envConfig.iamBaseUrl}/api/v1` | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (correctness): Same trailing-slash hazard here. If
Suggested change
|
||||||
| const userService = new HttpUserService({apiBaseUrl: iamApiV1}) | ||||||
| const teamService = new HttpTeamService({apiBaseUrl: iamApiV1}) | ||||||
| const spaceService = new HttpSpaceService({apiBaseUrl: iamApiV1}) | ||||||
|
|
||||||
| // Auth handler requires async OIDC discovery | ||||||
| const discoveryService = new OidcDiscoveryService() | ||||||
|
|
@@ -145,8 +146,9 @@ export async function setupFeatureHandlers({ | |||||
| const contextTreeWriterService = new FileContextTreeWriterService({snapshotService: contextTreeSnapshotService}) | ||||||
| const contextTreeMerger = new FileContextTreeMerger({snapshotService: contextTreeSnapshotService}) | ||||||
| const contextFileReader = new FileContextFileReader() | ||||||
| const cogitPushService = new HttpCogitPushService({apiBaseUrl: envConfig.cogitApiBaseUrl}) | ||||||
| const cogitPullService = new HttpCogitPullService({apiBaseUrl: envConfig.cogitApiBaseUrl}) | ||||||
| const cogitApiV1 = `${envConfig.cogitBaseUrl}/api/v1` | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (correctness): Same trailing-slash concern for
Suggested change
|
||||||
| const cogitPushService = new HttpCogitPushService({apiBaseUrl: cogitApiV1}) | ||||||
| const cogitPullService = new HttpCogitPullService({apiBaseUrl: cogitApiV1}) | ||||||
|
|
||||||
| // ConnectorManager factory — creates per-project instances since constructor binds to projectRoot | ||||||
| const fileService = new FsFileService() | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,13 +2,10 @@ import {expect} from 'chai' | |
|
|
||
| describe('Environment Configuration', () => { | ||
| const ENV_VARS = { | ||
| BRV_API_BASE_URL: 'https://api.test', | ||
| BRV_AUTHORIZATION_URL: 'https://auth.test/authorize', | ||
| BRV_COGIT_API_BASE_URL: 'https://cogit.test', | ||
| BRV_COGIT_BASE_URL: 'https://cogit.test', | ||
| BRV_GIT_REMOTE_BASE_URL: 'https://cogit-git.test', | ||
| BRV_ISSUER_URL: 'https://issuer.test', | ||
| BRV_LLM_API_BASE_URL: 'https://llm.test', | ||
| BRV_TOKEN_URL: 'https://auth.test/token', | ||
| BRV_IAM_BASE_URL: 'https://iam.test', | ||
| BRV_LLM_BASE_URL: 'https://llm.test', | ||
| BRV_WEB_APP_URL: 'https://app.test', | ||
| } | ||
|
|
||
|
|
@@ -78,12 +75,13 @@ describe('Environment Configuration', () => { | |
| const {getCurrentConfig} = await import(`../../../src/server/config/environment.js?t=${Date.now()}`) | ||
| const config = getCurrentConfig() | ||
|
|
||
| expect(config.apiBaseUrl).to.equal('https://api.test') | ||
| expect(config.authorizationUrl).to.equal('https://auth.test/authorize') | ||
| expect(config.cogitApiBaseUrl).to.equal('https://cogit.test') | ||
| expect(config.issuerUrl).to.equal('https://issuer.test') | ||
| expect(config.llmApiBaseUrl).to.equal('https://llm.test') | ||
| expect(config.tokenUrl).to.equal('https://auth.test/token') | ||
| expect(config.iamBaseUrl).to.equal('https://iam.test') | ||
| expect(config.authorizationUrl).to.equal('https://iam.test/api/v1/oidc/authorize') | ||
| expect(config.cogitBaseUrl).to.equal('https://cogit.test') | ||
| expect(config.gitRemoteBaseUrl).to.equal('https://cogit-git.test') | ||
| expect(config.issuerUrl).to.equal('https://iam.test/api/v1/oidc') | ||
| expect(config.llmBaseUrl).to.equal('https://llm.test') | ||
| expect(config.tokenUrl).to.equal('https://iam.test/api/v1/oidc/token') | ||
| expect(config.webAppUrl).to.equal('https://app.test') | ||
| }) | ||
|
|
||
|
|
@@ -125,11 +123,11 @@ describe('Environment Configuration', () => { | |
|
|
||
| it('should throw when a required env var is missing', async () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (testing): Only for (const key of ['BRV_COGIT_BASE_URL', 'BRV_GIT_REMOTE_BASE_URL', 'BRV_LLM_BASE_URL', 'BRV_WEB_APP_URL']) {
it(`should throw when ${key} is missing`, async () => {
delete process.env[key]
const {getCurrentConfig} = await import(`../../../src/server/config/environment.js?t=${Date.now()}`)
expect(() => getCurrentConfig()).to.throw(`Missing required environment variable: ${key}`)
})
}Not a blocker, but improves safety net for future env-var changes. |
||
| delete process.env.BRV_ENV | ||
| delete process.env.BRV_API_BASE_URL | ||
| delete process.env.BRV_IAM_BASE_URL | ||
|
|
||
| const {getCurrentConfig} = await import(`../../../src/server/config/environment.js?t=${Date.now()}`) | ||
|
|
||
| expect(() => getCurrentConfig()).to.throw('Missing required environment variable: BRV_API_BASE_URL') | ||
| expect(() => getCurrentConfig()).to.throw('Missing required environment variable: BRV_IAM_BASE_URL') | ||
| }) | ||
| }) | ||
| }) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (correctness): If
BRV_IAM_BASE_URLis set with a trailing slash (e.g.http://localhost:3000/), all derived OIDC URLs will contain a double slash (http://localhost:3000//api/v1/oidc/authorize). Consider normalizing the value:Same protection would be good for
cogitBaseUrlandllmBaseUrlinfeature-handlers.ts.