From ed390c16724bd8db7b45b9670377a72a34a99d76 Mon Sep 17 00:00:00 2001 From: axi92 Date: Tue, 19 May 2026 17:04:51 +0200 Subject: [PATCH] feat: support custom SSH user in git auth configuration - Allow sshUser setting to override default 'git' user in insteadOf config - When sshUser is empty, default to 'git@github.com' - When sshUser is provided (e.g., 'customuser'), use 'customuser@github.com' - Updated tests to verify custom SSH user behavior in auth configuration Co-Authored-By: Claude:Qwen3-Coder-Next-4bit --- __test__/git-auth-helper.test.ts | 85 ++++++++++++++++++++++++++++++++ dist/index.js | 5 +- src/git-auth-helper.ts | 6 ++- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index ad3566a..a30b358 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -974,6 +974,91 @@ describe('git-auth-helper tests', () => { ).toBe(false) expect((authHelper as any).testCredentialsConfigPath('')).toBe(false) }) + + const configureAuth_uses_default_git_user_when_sshUser_empty = + 'configureAuth uses default git user when sshUser is empty' + it(configureAuth_uses_default_git_user_when_sshUser_empty, async () => { + // Arrange + await setup(configureAuth_uses_default_git_user_when_sshUser_empty) + settings.sshUser = '' + settings.sshKey = '' + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + + // Act + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + + // Assert - verify that git@github.com is in the insteadOf config + const home = git.env['HOME'] || tempHomedir + const configContent = ( + await fs.promises.readFile(path.join(home, '.gitconfig')) + ).toString() + expect(configContent.indexOf('url.https://github.com/.insteadOf git@github.com')).toBeGreaterThanOrEqual(0) + }) + + const configureAuth_uses_custom_ssh_user_when_sshUser_provided = + 'configureAuth uses custom SSH user when sshUser is provided' + it(configureAuth_uses_custom_ssh_user_when_sshUser_provided, async () => { + // Arrange + await setup(configureAuth_uses_custom_ssh_user_when_sshUser_provided) + settings.sshUser = 'customuser' + settings.sshKey = '' + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + + // Act + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + + // Assert - verify that customuser@github.com is in the insteadOf config + const home = git.env['HOME'] || tempHomedir + const configContent = ( + await fs.promises.readFile(path.join(home, '.gitconfig')) + ).toString() + expect(configContent.indexOf('url.https://github.com/.insteadOf customuser@github.com')).toBeGreaterThanOrEqual(0) + }) + + const configureGlobalAuth_with_custom_sshUser = + 'configureGlobalAuth with custom sshUser' + it(configureGlobalAuth_with_custom_sshUser, async () => { + // Arrange + await setup(configureGlobalAuth_with_custom_sshUser) + settings.sshUser = 'admin' + settings.sshKey = '' + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + + // Act + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + + // Assert - verify the .insteadOf config contains the custom user + const home = git.env['HOME'] || tempHomedir + const configContent = ( + await fs.promises.readFile(path.join(home, '.gitconfig')) + ).toString() + expect(configContent.indexOf('url.https://github.com/.insteadOf admin@github.com')).toBeGreaterThanOrEqual(0) + }) + + const configureSubmoduleAuth_with_custom_sshUser = + 'configureSubmoduleAuth with custom sshUser' + it(configureSubmoduleAuth_with_custom_sshUser, async () => { + // Arrange + await setup(configureSubmoduleAuth_with_custom_sshUser) + settings.sshUser = 'deploy' + settings.sshKey = '' + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + await authHelper.configureAuth() + const mockSubmoduleForeach = git.submoduleForeach as jest.Mock + mockSubmoduleForeach.mockClear() + + // Act + await authHelper.configureSubmoduleAuth() + + // Assert - verify the insteadOf config uses the custom user + expect(mockSubmoduleForeach).toHaveBeenCalledTimes(3) + expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch( + /url.*insteadOf.*deploy@github.com:/ + ) + }) }) async function setup(testName: string): Promise { diff --git a/dist/index.js b/dist/index.js index 57729b2..49b1857 100644 --- a/dist/index.js +++ b/dist/index.js @@ -174,7 +174,10 @@ class GitAuthHelper { this.tokenConfigValue = `AUTHORIZATION: basic ${basicCredential}`; // Instead of SSH URL this.insteadOfKey = `url.${serverUrl.origin}/.insteadOf`; // "origin" is SCHEME://HOSTNAME[:PORT] - this.insteadOfValues.push(`git@${serverUrl.hostname}:`); + const sshUser = this.settings.sshUser && this.settings.sshUser.length > 0 + ? this.settings.sshUser + : 'git'; + this.insteadOfValues.push(`${sshUser}@${serverUrl.hostname}:`); if (this.settings.workflowOrganizationId) { this.insteadOfValues.push(`org-${this.settings.workflowOrganizationId}@github.com:`); } diff --git a/src/git-auth-helper.ts b/src/git-auth-helper.ts index e67db14..fe3f573 100644 --- a/src/git-auth-helper.ts +++ b/src/git-auth-helper.ts @@ -65,7 +65,11 @@ class GitAuthHelper { // Instead of SSH URL this.insteadOfKey = `url.${serverUrl.origin}/.insteadOf` // "origin" is SCHEME://HOSTNAME[:PORT] - this.insteadOfValues.push(`git@${serverUrl.hostname}:`) + const sshUser = + this.settings.sshUser && this.settings.sshUser.length > 0 + ? this.settings.sshUser + : 'git' + this.insteadOfValues.push(`${sshUser}@${serverUrl.hostname}:`) if (this.settings.workflowOrganizationId) { this.insteadOfValues.push( `org-${this.settings.workflowOrganizationId}@github.com:`