From 2b46e8a9d6ba5cc0915172b029590f0e9dc4dc74 Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 15:51:50 -0700 Subject: [PATCH 1/7] support passing in token manually in auth header --- docs/docs/connections/ado-cloud.mdx | 6 +++ docs/docs/connections/ado-server.mdx | 9 +++- .../schemas/v3/azuredevops.schema.mdx | 4 +- .../snippets/schemas/v3/connection.schema.mdx | 4 +- docs/snippets/schemas/v3/index.schema.mdx | 4 +- packages/backend/src/git.ts | 43 ++++++++++++++++--- packages/backend/src/repoManager.ts | 3 ++ packages/backend/src/types.ts | 3 +- packages/backend/src/utils.ts | 43 +++++++++++++------ packages/schemas/src/v3/azuredevops.schema.ts | 4 +- packages/schemas/src/v3/azuredevops.type.ts | 2 +- packages/schemas/src/v3/connection.schema.ts | 4 +- packages/schemas/src/v3/connection.type.ts | 2 +- packages/schemas/src/v3/index.schema.ts | 4 +- packages/schemas/src/v3/index.type.ts | 2 +- schemas/v3/azuredevops.json | 4 +- 16 files changed, 102 insertions(+), 39 deletions(-) diff --git a/docs/docs/connections/ado-cloud.mdx b/docs/docs/connections/ado-cloud.mdx index d4e51bd6..cc20c745 100644 --- a/docs/docs/connections/ado-cloud.mdx +++ b/docs/docs/connections/ado-cloud.mdx @@ -15,6 +15,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "cloud", "repos": [ "organizationName/projectName/repoName", "organizationName/projectName/repoName2 @@ -26,6 +27,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "cloud", "orgs": [ "organizationName", "organizationName2 @@ -37,6 +39,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "cloud", "projects": [ "organizationName/projectName", "organizationName/projectName2" @@ -48,6 +51,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "cloud", // Include all repos in my-org... "orgs": [ "my-org" @@ -91,6 +95,7 @@ Next, provide the access token via the `token` property, either as an environmen ```json { "type": "azuredevops", + "deploymentType": "cloud", "token": { // note: this env var can be named anything. It // doesn't need to be `ADO_TOKEN`. @@ -121,6 +126,7 @@ Next, provide the access token via the `token` property, either as an environmen ```json { "type": "azuredevops", + "deploymentType": "cloud", "token": { "secret": "mysecret" } diff --git a/docs/docs/connections/ado-server.mdx b/docs/docs/connections/ado-server.mdx index b2586056..1cfc0252 100644 --- a/docs/docs/connections/ado-server.mdx +++ b/docs/docs/connections/ado-server.mdx @@ -16,7 +16,8 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", - "useTfsPath": true + "deploymentType": "server", + "useTfsPath": true, "repos": [ "organizationName/projectName/repoName", "organizationName/projectName/repoName2 @@ -28,6 +29,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "server", "repos": [ "organizationName/projectName/repoName", "organizationName/projectName/repoName2 @@ -39,6 +41,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "server", "orgs": [ "collectionName", "collectionName2" @@ -50,6 +53,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "server", "projects": [ "collectionName/projectName", "collectionName/projectName2" @@ -61,6 +65,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview), ```json { "type": "azuredevops", + "deploymentType": "server", // Include all repos in my-org... "orgs": [ "my-org" @@ -104,6 +109,7 @@ Next, provide the access token via the `token` property, either as an environmen ```json { "type": "azuredevops", + "deploymentType": "server", "token": { // note: this env var can be named anything. It // doesn't need to be `ADO_TOKEN`. @@ -134,6 +140,7 @@ Next, provide the access token via the `token` property, either as an environmen ```json { "type": "azuredevops", + "deploymentType": "server", "token": { "secret": "mysecret" } diff --git a/docs/snippets/schemas/v3/azuredevops.schema.mdx b/docs/snippets/schemas/v3/azuredevops.schema.mdx index a36132ff..fab796de 100644 --- a/docs/snippets/schemas/v3/azuredevops.schema.mdx +++ b/docs/snippets/schemas/v3/azuredevops.schema.mdx @@ -62,7 +62,6 @@ "cloud", "server" ], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -199,7 +198,8 @@ }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false } diff --git a/docs/snippets/schemas/v3/connection.schema.mdx b/docs/snippets/schemas/v3/connection.schema.mdx index 3203cadd..48750ae1 100644 --- a/docs/snippets/schemas/v3/connection.schema.mdx +++ b/docs/snippets/schemas/v3/connection.schema.mdx @@ -931,7 +931,6 @@ "cloud", "server" ], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -1068,7 +1067,8 @@ }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false }, diff --git a/docs/snippets/schemas/v3/index.schema.mdx b/docs/snippets/schemas/v3/index.schema.mdx index 82e18d11..9df06a9f 100644 --- a/docs/snippets/schemas/v3/index.schema.mdx +++ b/docs/snippets/schemas/v3/index.schema.mdx @@ -1214,7 +1214,6 @@ "cloud", "server" ], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -1351,7 +1350,8 @@ }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false }, diff --git a/packages/backend/src/git.ts b/packages/backend/src/git.ts index 3f24b00e..f154953a 100644 --- a/packages/backend/src/git.ts +++ b/packages/backend/src/git.ts @@ -1,16 +1,19 @@ import { CheckRepoActions, GitConfigScope, simpleGit, SimpleGitProgressEvent } from 'simple-git'; import { mkdir } from 'node:fs/promises'; import { env } from './env.js'; +import { doesHaveEmbeddedToken } from './utils.js'; type onProgressFn = (event: SimpleGitProgressEvent) => void; export const cloneRepository = async ( { cloneUrl, + authHeader, path, onProgress, }: { cloneUrl: string, + authHeader?: string, path: string, onProgress?: onProgressFn } @@ -24,13 +27,29 @@ export const cloneRepository = async ( path, }) - await git.clone( - cloneUrl, - path, - [ - "--bare", - ] - ); + if (authHeader) { + if (doesHaveEmbeddedToken(cloneUrl)) { + throw new Error("Cannot use auth header when clone URL has embedded token"); + } + + await git.clone( + cloneUrl, + path, + [ + "--bare", + "-c", + `http.extraHeader=${authHeader}`, + ] + ) + } else { + await git.clone( + cloneUrl, + path, + [ + "--bare", + ] + ) + } await unsetGitConfig(path, ["remote.origin.url"]); } catch (error: unknown) { @@ -50,10 +69,12 @@ export const cloneRepository = async ( export const fetchRepository = async ( { cloneUrl, + authHeader, path, onProgress, }: { cloneUrl: string, + authHeader?: string, path: string, onProgress?: onProgressFn } @@ -65,6 +86,14 @@ export const fetchRepository = async ( path: path, }) + if (authHeader) { + if (doesHaveEmbeddedToken(cloneUrl)) { + throw new Error("Cannot use auth header when clone URL has embedded token"); + } + + await git.addConfig("http.extraHeader", authHeader); + } + await git.fetch([ cloneUrl, "+refs/heads/*:refs/heads/*", diff --git a/packages/backend/src/repoManager.ts b/packages/backend/src/repoManager.ts index 12bf7173..a0147942 100644 --- a/packages/backend/src/repoManager.ts +++ b/packages/backend/src/repoManager.ts @@ -175,6 +175,7 @@ export class RepoManager { const credentials = await getAuthCredentialsForRepo(repo, this.db); const cloneUrlMaybeWithToken = credentials?.cloneUrlWithToken ?? repo.cloneUrl; + const authHeader = credentials?.authToken ?? undefined; if (existsSync(repoPath) && !isReadOnly) { // @NOTE: in #483, we changed the cloning method s.t., we _no longer_ @@ -188,6 +189,7 @@ export class RepoManager { logger.info(`Fetching ${repo.displayName}...`); const { durationMs } = await measure(() => fetchRepository({ cloneUrl: cloneUrlMaybeWithToken, + authHeader, path: repoPath, onProgress: ({ method, stage, progress }) => { logger.debug(`git.${method} ${stage} stage ${progress}% complete for ${repo.displayName}`) @@ -203,6 +205,7 @@ export class RepoManager { const { durationMs } = await measure(() => cloneRepository({ cloneUrl: cloneUrlMaybeWithToken, + authHeader, path: repoPath, onProgress: ({ method, stage, progress }) => { logger.debug(`git.${method} ${stage} stage ${progress}% complete for ${repo.displayName}`) diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 0a9e76ff..5edee85a 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -59,5 +59,6 @@ export type RepoWithConnections = Repo & { connections: (RepoToConnection & { co export type RepoAuthCredentials = { hostUrl?: string; token: string; - cloneUrlWithToken: string; + cloneUrlWithToken?: string; + authToken?: string; } \ No newline at end of file diff --git a/packages/backend/src/utils.ts b/packages/backend/src/utils.ts index 6ea8e5ff..99f638e8 100644 --- a/packages/backend/src/utils.ts +++ b/packages/backend/src/utils.ts @@ -193,19 +193,31 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P const config = connection.config as unknown as AzureDevOpsConnectionConfig; if (config.token) { const token = await getTokenFromConfig(config.token, connection.orgId, db, logger); - return { - hostUrl: config.url, - token, - cloneUrlWithToken: createGitCloneUrlWithToken( - repo.cloneUrl, - { - // @note: If we don't provide a username, the password will be set as the username. This seems to work - // for ADO cloud but not for ADO server. To fix this, we set a placeholder username to ensure the password - // is set correctly - username: 'user', - password: token - } - ), + + // For ADO server, multiple auth schemes may be supported. If the ADO deployment supports NTLM, the git clone will default + // to this over basic auth. As a result, we cannot embed the token in the clone URL and must force basic auth by passing in the token + // appropriately in the header. To do this, we set the authToken field here + if (config.deploymentType === 'server') { + return { + hostUrl: config.url, + token, + authToken: "Authorization: Basic " + Buffer.from(`:${token}`).toString('base64') + } + } else { + return { + hostUrl: config.url, + token, + cloneUrlWithToken: createGitCloneUrlWithToken( + repo.cloneUrl, + { + // @note: If we don't provide a username, the password will be set as the username. This seems to work + // for ADO cloud but not for ADO server. To fix this, we set a placeholder username to ensure the password + // is set correctly + username: 'user', + password: token + } + ), + } } } } @@ -228,4 +240,9 @@ const createGitCloneUrlWithToken = (cloneUrl: string, credentials: { username?: url.password = credentials.password; } return url.toString(); +} + +export const doesHaveEmbeddedToken = (cloneUrl: string) => { + const url = new URL(cloneUrl); + return url.username || url.password; } \ No newline at end of file diff --git a/packages/schemas/src/v3/azuredevops.schema.ts b/packages/schemas/src/v3/azuredevops.schema.ts index 02bc989d..3b36fbed 100644 --- a/packages/schemas/src/v3/azuredevops.schema.ts +++ b/packages/schemas/src/v3/azuredevops.schema.ts @@ -61,7 +61,6 @@ const schema = { "cloud", "server" ], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -198,7 +197,8 @@ const schema = { }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false } as const; diff --git a/packages/schemas/src/v3/azuredevops.type.ts b/packages/schemas/src/v3/azuredevops.type.ts index eec963bc..b6ef68da 100644 --- a/packages/schemas/src/v3/azuredevops.type.ts +++ b/packages/schemas/src/v3/azuredevops.type.ts @@ -28,7 +28,7 @@ export interface AzureDevOpsConnectionConfig { /** * The type of Azure DevOps deployment */ - deploymentType?: "cloud" | "server"; + deploymentType: "cloud" | "server"; /** * Use legacy TFS path format (/tfs) in API URLs. Required for older TFS installations (TFS 2018 and earlier). When true, API URLs will include /tfs in the path (e.g., https://server/tfs/collection/_apis/...). */ diff --git a/packages/schemas/src/v3/connection.schema.ts b/packages/schemas/src/v3/connection.schema.ts index cb867694..e0bcbc48 100644 --- a/packages/schemas/src/v3/connection.schema.ts +++ b/packages/schemas/src/v3/connection.schema.ts @@ -930,7 +930,6 @@ const schema = { "cloud", "server" ], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -1067,7 +1066,8 @@ const schema = { }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false }, diff --git a/packages/schemas/src/v3/connection.type.ts b/packages/schemas/src/v3/connection.type.ts index 7922ef20..df31c465 100644 --- a/packages/schemas/src/v3/connection.type.ts +++ b/packages/schemas/src/v3/connection.type.ts @@ -340,7 +340,7 @@ export interface AzureDevOpsConnectionConfig { /** * The type of Azure DevOps deployment */ - deploymentType?: "cloud" | "server"; + deploymentType: "cloud" | "server"; /** * Use legacy TFS path format (/tfs) in API URLs. Required for older TFS installations (TFS 2018 and earlier). When true, API URLs will include /tfs in the path (e.g., https://server/tfs/collection/_apis/...). */ diff --git a/packages/schemas/src/v3/index.schema.ts b/packages/schemas/src/v3/index.schema.ts index c8fe48e8..38ec2f0a 100644 --- a/packages/schemas/src/v3/index.schema.ts +++ b/packages/schemas/src/v3/index.schema.ts @@ -1213,7 +1213,6 @@ const schema = { "cloud", "server" ], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -1350,7 +1349,8 @@ const schema = { }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false }, diff --git a/packages/schemas/src/v3/index.type.ts b/packages/schemas/src/v3/index.type.ts index 2bea9453..4e8982dc 100644 --- a/packages/schemas/src/v3/index.type.ts +++ b/packages/schemas/src/v3/index.type.ts @@ -473,7 +473,7 @@ export interface AzureDevOpsConnectionConfig { /** * The type of Azure DevOps deployment */ - deploymentType?: "cloud" | "server"; + deploymentType: "cloud" | "server"; /** * Use legacy TFS path format (/tfs) in API URLs. Required for older TFS installations (TFS 2018 and earlier). When true, API URLs will include /tfs in the path (e.g., https://server/tfs/collection/_apis/...). */ diff --git a/schemas/v3/azuredevops.json b/schemas/v3/azuredevops.json index f9b6bd81..6cc27833 100644 --- a/schemas/v3/azuredevops.json +++ b/schemas/v3/azuredevops.json @@ -30,7 +30,6 @@ "deploymentType": { "type": "string", "enum": ["cloud", "server"], - "default": "cloud", "description": "The type of Azure DevOps deployment" }, "useTfsPath": { @@ -129,7 +128,8 @@ }, "required": [ "type", - "token" + "token", + "deploymentType" ], "additionalProperties": false } \ No newline at end of file From c40576d0a5f35a3fafc19f15563da3f93dda8756 Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 15:57:27 -0700 Subject: [PATCH 2/7] remove unneeded PAT embed check --- packages/backend/src/git.ts | 9 --------- packages/backend/src/utils.ts | 5 ----- 2 files changed, 14 deletions(-) diff --git a/packages/backend/src/git.ts b/packages/backend/src/git.ts index f154953a..88d97ec6 100644 --- a/packages/backend/src/git.ts +++ b/packages/backend/src/git.ts @@ -1,7 +1,6 @@ import { CheckRepoActions, GitConfigScope, simpleGit, SimpleGitProgressEvent } from 'simple-git'; import { mkdir } from 'node:fs/promises'; import { env } from './env.js'; -import { doesHaveEmbeddedToken } from './utils.js'; type onProgressFn = (event: SimpleGitProgressEvent) => void; @@ -28,10 +27,6 @@ export const cloneRepository = async ( }) if (authHeader) { - if (doesHaveEmbeddedToken(cloneUrl)) { - throw new Error("Cannot use auth header when clone URL has embedded token"); - } - await git.clone( cloneUrl, path, @@ -87,10 +82,6 @@ export const fetchRepository = async ( }) if (authHeader) { - if (doesHaveEmbeddedToken(cloneUrl)) { - throw new Error("Cannot use auth header when clone URL has embedded token"); - } - await git.addConfig("http.extraHeader", authHeader); } diff --git a/packages/backend/src/utils.ts b/packages/backend/src/utils.ts index 99f638e8..0ea3371a 100644 --- a/packages/backend/src/utils.ts +++ b/packages/backend/src/utils.ts @@ -241,8 +241,3 @@ const createGitCloneUrlWithToken = (cloneUrl: string, credentials: { username?: } return url.toString(); } - -export const doesHaveEmbeddedToken = (cloneUrl: string) => { - const url = new URL(cloneUrl); - return url.username || url.password; -} \ No newline at end of file From c5a921fff55f821c8062c8e3ed6533ff419584d6 Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 15:59:48 -0700 Subject: [PATCH 3/7] cleanup authheader usage --- packages/backend/src/git.ts | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/packages/backend/src/git.ts b/packages/backend/src/git.ts index 88d97ec6..06680ba5 100644 --- a/packages/backend/src/git.ts +++ b/packages/backend/src/git.ts @@ -26,25 +26,12 @@ export const cloneRepository = async ( path, }) - if (authHeader) { - await git.clone( - cloneUrl, - path, - [ - "--bare", - "-c", - `http.extraHeader=${authHeader}`, - ] - ) - } else { - await git.clone( - cloneUrl, - path, - [ - "--bare", - ] - ) - } + const cloneArgs = [ + "--bare", + ...(authHeader ? ["-c", `http.extraHeader=${authHeader}`] : []) + ]; + + await git.clone(cloneUrl, path, cloneArgs); await unsetGitConfig(path, ["remote.origin.url"]); } catch (error: unknown) { From 6e446735626ac08d024be26ddcb64c6a20685cde Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 16:03:25 -0700 Subject: [PATCH 4/7] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c54d1c34..1cc25277 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- Manually pass auth token for ado server deployments. [#543](https://github.com/sourcebot-dev/sourcebot/pull/543) + ## [4.7.2] - 2025-09-22 ### Fixed From df8c72c3c52b73c540e28998d1c4708a48fbecea Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 16:35:09 -0700 Subject: [PATCH 5/7] var name typo --- packages/backend/src/repoManager.ts | 2 +- packages/backend/src/types.ts | 2 +- packages/backend/src/utils.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/repoManager.ts b/packages/backend/src/repoManager.ts index a0147942..89e41673 100644 --- a/packages/backend/src/repoManager.ts +++ b/packages/backend/src/repoManager.ts @@ -175,7 +175,7 @@ export class RepoManager { const credentials = await getAuthCredentialsForRepo(repo, this.db); const cloneUrlMaybeWithToken = credentials?.cloneUrlWithToken ?? repo.cloneUrl; - const authHeader = credentials?.authToken ?? undefined; + const authHeader = credentials?.authHeader ?? undefined; if (existsSync(repoPath) && !isReadOnly) { // @NOTE: in #483, we changed the cloning method s.t., we _no longer_ diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 5edee85a..2ea42d04 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -60,5 +60,5 @@ export type RepoAuthCredentials = { hostUrl?: string; token: string; cloneUrlWithToken?: string; - authToken?: string; + authHeader?: string; } \ No newline at end of file diff --git a/packages/backend/src/utils.ts b/packages/backend/src/utils.ts index 0ea3371a..e6ac5f93 100644 --- a/packages/backend/src/utils.ts +++ b/packages/backend/src/utils.ts @@ -196,12 +196,12 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P // For ADO server, multiple auth schemes may be supported. If the ADO deployment supports NTLM, the git clone will default // to this over basic auth. As a result, we cannot embed the token in the clone URL and must force basic auth by passing in the token - // appropriately in the header. To do this, we set the authToken field here + // appropriately in the header. To do this, we set the authHeader field here if (config.deploymentType === 'server') { return { hostUrl: config.url, token, - authToken: "Authorization: Basic " + Buffer.from(`:${token}`).toString('base64') + authHeader: "Authorization: Basic " + Buffer.from(`:${token}`).toString('base64') } } else { return { From 397c430c5a8c08d4ee0d377c5e8e9ec228ac8437 Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 17:00:02 -0700 Subject: [PATCH 6/7] unset auth header in fetch --- packages/backend/src/git.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/backend/src/git.ts b/packages/backend/src/git.ts index 06680ba5..f49207ad 100644 --- a/packages/backend/src/git.ts +++ b/packages/backend/src/git.ts @@ -78,6 +78,10 @@ export const fetchRepository = async ( "--prune", "--progress" ]); + + if (authHeader) { + await git.raw(["config", "--unset", "http.extraHeader", authHeader]); + } } catch (error: unknown) { const baseLog = `Failed to fetch repository: ${path}`; if (env.SOURCEBOT_LOG_LEVEL !== "debug") { From 4f9cb6701f278ee41e4681cc78522397a46c35ec Mon Sep 17 00:00:00 2001 From: msukkari Date: Sat, 27 Sep 2025 17:02:03 -0700 Subject: [PATCH 7/7] move unset to finally in fetch --- packages/backend/src/git.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/git.ts b/packages/backend/src/git.ts index f49207ad..c1110625 100644 --- a/packages/backend/src/git.ts +++ b/packages/backend/src/git.ts @@ -78,10 +78,6 @@ export const fetchRepository = async ( "--prune", "--progress" ]); - - if (authHeader) { - await git.raw(["config", "--unset", "http.extraHeader", authHeader]); - } } catch (error: unknown) { const baseLog = `Failed to fetch repository: ${path}`; if (env.SOURCEBOT_LOG_LEVEL !== "debug") { @@ -92,6 +88,16 @@ export const fetchRepository = async ( } else { throw new Error(`${baseLog}. Error: ${error}`); } + } finally { + if (authHeader) { + const git = simpleGit({ + progress: onProgress, + }).cwd({ + path: path, + }) + + await git.raw(["config", "--unset", "http.extraHeader", authHeader]); + } } }