Conversation
# Conflicts: # src/otomi-stack.ts
There was a problem hiding this comment.
Pull request overview
This PR refactors how Git configuration is handled by moving credentials/config out of values and into a dedicated Kubernetes Secret, and updates related Git helper logic and sanitization.
Changes:
- Introduces
GitConfigand stores/reads Git config from a cluster Secret (apl-git-config) with defaults (GIT_DEFAULT_CONFIG/GIT_LEGACY_CONFIG). - Updates git client initialization/migration flow to use
GitConfigobjects rather than individual env vars. - Changes sanitization/tests to mask credentials embedded in repo URLs instead of replacing raw password tokens.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/validators.ts | Makes git env vars optional by default (undefined). |
| src/utils/workloadUtils.ts | Adds note about internal Gitea credential encoding behavior. |
| src/utils/codeRepoUtils.ts | Adds note about Gitea-specific branch extraction behavior. |
| src/utils.ts | Changes credential sanitization to mask URL-embedded credentials. |
| src/utils.test.ts | Updates sanitization tests to match URL-masking behavior. |
| src/otomi-stack.ts | Adds Secret-backed Git config management and re-init logic. |
| src/otomi-stack.test.ts | Updates tests to align with new Git constructor/config flow. |
| src/otomi-models.ts | Adds GitConfig type used across stack/git layers. |
| src/middleware/session.ts | Makes cleanAllSessions async and deletes session root via rm. |
| src/git/connect.ts | Refactors remote SHA lookup + adds Git URL auth helpers. |
| src/git.ts | Refactors Git to accept GitConfig for auth/remote operations. |
| src/git.test.ts | Updates tests for GitConfig-based APIs. |
| src/constants.ts | Adds Secret name and default/legacy Git config constants. |
| src/app.ts | Refreshes Git config/client before checking latest remote SHA. |
| src/api/v2/git.ts | Updates migration endpoint to accept GitConfig payload. |
Comments suppressed due to low confidence (2)
src/utils/workloadUtils.ts:387
- If
GIT_USER/GIT_PASSWORDare not set, this will generate URLs containing the literal stringundefined, which will always fail authentication and can be hard to diagnose. Guard against missing credentials before encoding them into the URL.
// FIXME: When Gitea is present and hosting charts, but the Values repo is somewhere else, this breaks
const [protocol, bareUrl] = url.split('://')
const encodedUser = encodeURIComponent(process.env.GIT_USER as string)
const encodedPassword = encodeURIComponent(process.env.GIT_PASSWORD as string)
return `${protocol}://${encodedUser}:${encodedPassword}@${bareUrl}`
src/utils/codeRepoUtils.ts:180
- If
GIT_USER/GIT_PASSWORDare not set, this will embedundefinedinto the URL. Add a guard to avoid producing an invalid URL (and to make failures easier to understand).
// FIXME: When values is not on Gitea, this is broken
const username = process.env.GIT_USER as string
const accessToken = process.env.GIT_PASSWORD as string
formattedRepoUrl = repoUrl.replace(
'https://',
`https://${encodeURIComponent(username)}:${encodeURIComponent(accessToken)}@`,
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (2)
src/utils/workloadUtils.ts:387
encodeGitCredentialsnow unconditionally castsprocess.env.GIT_USER/GIT_PASSWORDtostring. WithGIT_USER/GIT_PASSWORDmade optional invalidators.ts, this can inject literalundefinedinto the URL (e.g.http://undefined:undefined@...) and cause hard-to-debug auth failures. Guard for missing env vars (or better: plumb credentials from the new GitConfig/Secret), and avoid encoding when credentials are absent.
// FIXME: When Gitea is present and hosting charts, but the Values repo is somewhere else, this breaks
const [protocol, bareUrl] = url.split('://')
const encodedUser = encodeURIComponent(process.env.GIT_USER as string)
const encodedPassword = encodeURIComponent(process.env.GIT_PASSWORD as string)
return `${protocol}://${encodedUser}:${encodedPassword}@${bareUrl}`
src/utils/codeRepoUtils.ts:180
extractRepositoryRefscastsprocess.env.GIT_USER/GIT_PASSWORDtostringand always injects them into the URL forhttps://gitea...repos. Since those env vars are now optional, this can generatehttps://undefined:undefined@...and break remote listing. Only inject credentials when both env vars are present (or switch to Secret/GitConfig-based credentials).
// FIXME: When values is not on Gitea, this is broken
const username = process.env.GIT_USER as string
const accessToken = process.env.GIT_PASSWORD as string
formattedRepoUrl = repoUrl.replace(
'https://',
`https://${encodeURIComponent(username)}:${encodeURIComponent(accessToken)}@`,
)
| if (remoteHasContent) { | ||
| res.json({ message: 'New repository is not empty', statusCode: 400 }) | ||
| return | ||
| } |
There was a problem hiding this comment.
This is very obscure indeed, but currently this is the way Console handles this. Need to check first if we can adjust without breaking it.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (4)
src/middleware/session.ts:70
cleanAllSessions()currently resets the module-levelreadOnlyStacktoundefined. With the newrefreshGitClient()flow (which callscleanAllSessions()and then reinitializes a stack), clearingreadOnlyStackbreaks subsequentlockApi()calls (they dereferencereadOnlyStackunconditionally) and can leave the API in an inconsistent state. SincecleanAllSessions()is nowasyncand is awaited byrefreshGitClient(), it’s safer to keepreadOnlyStackand let the caller reinitialize it as needed.
await rm(rootPath, { recursive: true, force: true })
sessions = {}
// @ts-ignore
readOnlyStack = undefined
}
src/utils/workloadUtils.ts:387
encodeGitCredentials()will embed the literal string'undefined'into the URL whenGIT_USER/GIT_PASSWORDare not set, because of theas stringcasts. That produces an invalid credential URL and can accidentally leak confusing values into logs. If credentials are missing, return the original URL (or throw a clear error) instead of encoding undefined.
const [protocol, bareUrl] = url.split('://')
const encodedUser = encodeURIComponent(process.env.GIT_USER as string)
const encodedPassword = encodeURIComponent(process.env.GIT_PASSWORD as string)
return `${protocol}://${encodedUser}:${encodedPassword}@${bareUrl}`
src/utils/codeRepoUtils.ts:179
extractRepositoryRefs()builds an authenticated URL for Gitea usingprocess.env.GIT_USER/process.env.GIT_PASSWORDcast tostring. If either env var is unset, the resulting URL will containundefined:undefined@...and auth will fail in a non-obvious way. Add a guard so you either skip auth rewriting or throw a clear error when creds are missing.
const username = process.env.GIT_USER as string
const accessToken = process.env.GIT_PASSWORD as string
formattedRepoUrl = repoUrl.replace(
'https://',
`https://${encodeURIComponent(username)}:${encodeURIComponent(accessToken)}@`,
src/api/v2/git.ts:43
- These error paths return a JSON body with
statusCode, but they never set the actual HTTP response status (so it stays200). Other v2 endpoints useres.status(...), and clients may treat these failures as success unless the HTTP status is set explicitly.
const error = { message: `Cannot connect to new git remote`, statusCode: 404 }
res.json(error)
return
} else {
const error = { message: `Error connecting to new git remote`, statusCode: 400 }
This PR changes the Git configuration for longer requiring environment variables, but read the Git configuration from the same Secret
apl-secets/apl-git-configas apl-operator.Currently still breaks when Gitea is used in addition to an external repository, as Gitea admin password is not separated cleanly from internal Git credentials.