2020-03-02 19:33:30 +03:00
import * as core from '@actions/core'
import * as fs from 'fs'
import * as gitAuthHelper from '../lib/git-auth-helper'
import * as io from '@actions/io'
2020-03-11 22:55:17 +03:00
import * as os from 'os'
2020-03-02 19:33:30 +03:00
import * as path from 'path'
2020-03-11 22:55:17 +03:00
import * as stateHelper from '../lib/state-helper'
2020-03-02 19:33:30 +03:00
import { IGitCommandManager } from '../lib/git-command-manager'
import { IGitSourceSettings } from '../lib/git-source-settings'
2020-03-11 22:55:17 +03:00
const isWindows = process . platform === 'win32'
2020-03-02 19:33:30 +03:00
const testWorkspace = path . join ( __dirname , '_temp' , 'git-auth-helper' )
const originalRunnerTemp = process . env [ 'RUNNER_TEMP' ]
2020-03-05 22:21:59 +03:00
const originalHome = process . env [ 'HOME' ]
2020-03-02 19:33:30 +03:00
let workspace : string
2020-03-05 22:21:59 +03:00
let localGitConfigPath : string
let globalGitConfigPath : string
2020-03-02 19:33:30 +03:00
let runnerTemp : string
2020-03-05 22:21:59 +03:00
let tempHomedir : string
let git : IGitCommandManager & { env : { [ key : string ] : string } }
2020-03-02 19:33:30 +03:00
let settings : IGitSourceSettings
2020-03-11 22:55:17 +03:00
let sshPath : string
2022-09-26 19:34:52 +03:00
let githubServerUrl : string
2020-03-02 19:33:30 +03:00
describe ( 'git-auth-helper tests' , ( ) = > {
beforeAll ( async ( ) = > {
2020-03-11 22:55:17 +03:00
// SSH
sshPath = await io . which ( 'ssh' )
2020-03-02 19:33:30 +03:00
// Clear test workspace
await io . rmRF ( testWorkspace )
} )
beforeEach ( ( ) = > {
// Mock setSecret
jest . spyOn ( core , 'setSecret' ) . mockImplementation ( ( secret : string ) = > { } )
2020-03-05 22:21:59 +03:00
// Mock error/warning/info/debug
jest . spyOn ( core , 'error' ) . mockImplementation ( jest . fn ( ) )
jest . spyOn ( core , 'warning' ) . mockImplementation ( jest . fn ( ) )
jest . spyOn ( core , 'info' ) . mockImplementation ( jest . fn ( ) )
jest . spyOn ( core , 'debug' ) . mockImplementation ( jest . fn ( ) )
2020-03-11 22:55:17 +03:00
// Mock state helper
jest . spyOn ( stateHelper , 'setSshKeyPath' ) . mockImplementation ( jest . fn ( ) )
jest
. spyOn ( stateHelper , 'setSshKnownHostsPath' )
. mockImplementation ( jest . fn ( ) )
2020-03-02 19:33:30 +03:00
} )
afterEach ( ( ) = > {
// Unregister mocks
jest . restoreAllMocks ( )
2020-03-05 22:21:59 +03:00
// Restore HOME
if ( originalHome ) {
process . env [ 'HOME' ] = originalHome
} else {
delete process . env [ 'HOME' ]
}
2020-03-02 19:33:30 +03:00
} )
afterAll ( ( ) = > {
// Restore RUNNER_TEMP
delete process . env [ 'RUNNER_TEMP' ]
if ( originalRunnerTemp ) {
process . env [ 'RUNNER_TEMP' ] = originalRunnerTemp
}
} )
2022-09-26 19:34:52 +03:00
async function testAuthHeader (
testName : string ,
serverUrl : string | undefined = undefined
) {
2020-03-02 19:33:30 +03:00
// Arrange
2022-09-26 19:34:52 +03:00
let expectedServerUrl = 'https://github.com'
if ( serverUrl ) {
githubServerUrl = serverUrl
expectedServerUrl = githubServerUrl
}
await setup ( testName )
2020-03-02 19:33:30 +03:00
expect ( settings . authToken ) . toBeTruthy ( ) // sanity check
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
// Assert config
2020-03-05 22:21:59 +03:00
const configContent = (
await fs . promises . readFile ( localGitConfigPath )
) . toString ( )
2020-03-02 19:33:30 +03:00
const basicCredential = Buffer . from (
` x-access-token: ${ settings . authToken } ` ,
'utf8'
) . toString ( 'base64' )
expect (
configContent . indexOf (
2022-09-26 19:34:52 +03:00
` http. ${ expectedServerUrl } /.extraheader AUTHORIZATION: basic ${ basicCredential } `
2020-03-02 19:33:30 +03:00
)
) . toBeGreaterThanOrEqual ( 0 )
2022-09-26 19:34:52 +03:00
}
const configureAuth_configuresAuthHeader =
'configureAuth configures auth header'
it ( configureAuth_configuresAuthHeader , async ( ) = > {
await testAuthHeader ( configureAuth_configuresAuthHeader )
} )
const configureAuth_AcceptsGitHubServerUrl =
'inject https://my-ghes-server.com as github server url'
it ( configureAuth_AcceptsGitHubServerUrl , async ( ) = > {
await testAuthHeader (
configureAuth_AcceptsGitHubServerUrl ,
'https://my-ghes-server.com'
)
} )
const configureAuth_AcceptsGitHubServerUrlSetToGHEC =
'inject https://github.com as github server url'
it ( configureAuth_AcceptsGitHubServerUrlSetToGHEC , async ( ) = > {
await testAuthHeader (
configureAuth_AcceptsGitHubServerUrl ,
'https://github.com'
)
2020-03-02 19:33:30 +03:00
} )
2020-03-05 22:21:59 +03:00
const configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse =
'configureAuth configures auth header even when persist credentials false'
it (
configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse ,
async ( ) = > {
// Arrange
await setup (
configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse
)
expect ( settings . authToken ) . toBeTruthy ( ) // sanity check
settings . persistCredentials = false
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
2020-03-02 19:33:30 +03:00
2020-03-05 22:21:59 +03:00
// Act
await authHelper . configureAuth ( )
2020-03-02 19:33:30 +03:00
2020-03-05 22:21:59 +03:00
// Assert config
const configContent = (
await fs . promises . readFile ( localGitConfigPath )
) . toString ( )
expect (
configContent . indexOf (
` http.https://github.com/.extraheader AUTHORIZATION `
)
) . toBeGreaterThanOrEqual ( 0 )
}
)
2020-03-02 19:33:30 +03:00
2020-03-11 22:55:17 +03:00
const configureAuth_copiesUserKnownHosts =
'configureAuth copies user known hosts'
it ( configureAuth_copiesUserKnownHosts , async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
` Skipped test " ${ configureAuth_copiesUserKnownHosts } ". Executable 'ssh' not found in the PATH. \ n `
)
return
}
// Arange
await setup ( configureAuth_copiesUserKnownHosts )
expect ( settings . sshKey ) . toBeTruthy ( ) // sanity check
// Mock fs.promises.readFile
const realReadFile = fs . promises . readFile
2024-04-24 19:04:10 +03:00
jest
. spyOn ( fs . promises , 'readFile' )
. mockImplementation ( async ( file : any , options : any ) : Promise < Buffer > = > {
2020-03-11 22:55:17 +03:00
const userKnownHostsPath = path . join (
os . homedir ( ) ,
'.ssh' ,
'known_hosts'
)
if ( file === userKnownHostsPath ) {
return Buffer . from ( 'some-domain.com ssh-rsa ABCDEF' )
}
return await realReadFile ( file , options )
2024-04-24 19:04:10 +03:00
} )
2020-03-11 22:55:17 +03:00
// Act
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
// Assert known hosts
const actualSshKnownHostsPath = await getActualSshKnownHostsPath ( )
const actualSshKnownHostsContent = (
await fs . promises . readFile ( actualSshKnownHostsPath )
) . toString ( )
expect ( actualSshKnownHostsContent ) . toMatch (
/some-domain\.com ssh-rsa ABCDEF/
)
expect ( actualSshKnownHostsContent ) . toMatch ( /github\.com ssh-rsa AAAAB3N/ )
} )
2020-03-05 22:21:59 +03:00
const configureAuth_registersBasicCredentialAsSecret =
'configureAuth registers basic credential as secret'
it ( configureAuth_registersBasicCredentialAsSecret , async ( ) = > {
2020-03-02 19:33:30 +03:00
// Arrange
2020-03-05 22:21:59 +03:00
await setup ( configureAuth_registersBasicCredentialAsSecret )
2020-03-02 19:33:30 +03:00
expect ( settings . authToken ) . toBeTruthy ( ) // sanity check
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
// Assert secret
const setSecretSpy = core . setSecret as jest . Mock < any , any >
expect ( setSecretSpy ) . toHaveBeenCalledTimes ( 1 )
const expectedSecret = Buffer . from (
` x-access-token: ${ settings . authToken } ` ,
'utf8'
) . toString ( 'base64' )
expect ( setSecretSpy ) . toHaveBeenCalledWith ( expectedSecret )
} )
2020-03-11 22:55:17 +03:00
const setsSshCommandEnvVarWhenPersistCredentialsFalse =
'sets SSH command env var when persist-credentials false'
it ( setsSshCommandEnvVarWhenPersistCredentialsFalse , async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
` Skipped test " ${ setsSshCommandEnvVarWhenPersistCredentialsFalse } ". Executable 'ssh' not found in the PATH. \ n `
)
return
}
// Arrange
await setup ( setsSshCommandEnvVarWhenPersistCredentialsFalse )
settings . persistCredentials = false
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
// Assert git env var
const actualKeyPath = await getActualSshKeyPath ( )
const actualKnownHostsPath = await getActualSshKnownHostsPath ( )
const expectedSshCommand = ` " ${ sshPath } " -i " $ RUNNER_TEMP/ ${ path . basename (
actualKeyPath
) } " -o StrictHostKeyChecking=yes -o CheckHostIP=no -o " UserKnownHostsFile = $RUNNER_TEMP / $ { path . basename (
actualKnownHostsPath
) } " `
expect ( git . setEnvironmentVariable ) . toHaveBeenCalledWith (
'GIT_SSH_COMMAND' ,
expectedSshCommand
)
// Asserty git config
const gitConfigLines = ( await fs . promises . readFile ( localGitConfigPath ) )
. toString ( )
. split ( '\n' )
. filter ( x = > x )
expect ( gitConfigLines ) . toHaveLength ( 1 )
expect ( gitConfigLines [ 0 ] ) . toMatch ( /^http\./ )
} )
const configureAuth_setsSshCommandWhenPersistCredentialsTrue =
'sets SSH command when persist-credentials true'
it ( configureAuth_setsSshCommandWhenPersistCredentialsTrue , async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
` Skipped test " ${ configureAuth_setsSshCommandWhenPersistCredentialsTrue } ". Executable 'ssh' not found in the PATH. \ n `
)
return
}
// Arrange
await setup ( configureAuth_setsSshCommandWhenPersistCredentialsTrue )
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
// Assert git env var
const actualKeyPath = await getActualSshKeyPath ( )
const actualKnownHostsPath = await getActualSshKnownHostsPath ( )
const expectedSshCommand = ` " ${ sshPath } " -i " $ RUNNER_TEMP/ ${ path . basename (
actualKeyPath
) } " -o StrictHostKeyChecking=yes -o CheckHostIP=no -o " UserKnownHostsFile = $RUNNER_TEMP / $ { path . basename (
actualKnownHostsPath
) } " `
expect ( git . setEnvironmentVariable ) . toHaveBeenCalledWith (
'GIT_SSH_COMMAND' ,
expectedSshCommand
)
// Asserty git config
expect ( git . config ) . toHaveBeenCalledWith (
'core.sshCommand' ,
expectedSshCommand
)
} )
const configureAuth_writesExplicitKnownHosts = 'writes explicit known hosts'
it ( configureAuth_writesExplicitKnownHosts , async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
` Skipped test " ${ configureAuth_writesExplicitKnownHosts } ". Executable 'ssh' not found in the PATH. \ n `
)
return
}
// Arrange
await setup ( configureAuth_writesExplicitKnownHosts )
expect ( settings . sshKey ) . toBeTruthy ( ) // sanity check
settings . sshKnownHosts = 'my-custom-host.com ssh-rsa ABC123'
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
// Assert known hosts
const actualSshKnownHostsPath = await getActualSshKnownHostsPath ( )
const actualSshKnownHostsContent = (
await fs . promises . readFile ( actualSshKnownHostsPath )
) . toString ( )
expect ( actualSshKnownHostsContent ) . toMatch (
/my-custom-host\.com ssh-rsa ABC123/
)
expect ( actualSshKnownHostsContent ) . toMatch ( /github\.com ssh-rsa AAAAB3N/ )
} )
const configureAuth_writesSshKeyAndImplicitKnownHosts =
'writes SSH key and implicit known hosts'
it ( configureAuth_writesSshKeyAndImplicitKnownHosts , async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
` Skipped test " ${ configureAuth_writesSshKeyAndImplicitKnownHosts } ". Executable 'ssh' not found in the PATH. \ n `
)
return
}
// Arrange
await setup ( configureAuth_writesSshKeyAndImplicitKnownHosts )
expect ( settings . sshKey ) . toBeTruthy ( ) // sanity check
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
// Assert SSH key
const actualSshKeyPath = await getActualSshKeyPath ( )
expect ( actualSshKeyPath ) . toBeTruthy ( )
const actualSshKeyContent = (
await fs . promises . readFile ( actualSshKeyPath )
) . toString ( )
expect ( actualSshKeyContent ) . toBe ( settings . sshKey + '\n' )
if ( ! isWindows ) {
2020-03-12 18:42:38 +03:00
// Assert read/write for user, not group or others.
// Otherwise SSH client will error.
2020-03-11 22:55:17 +03:00
expect ( ( await fs . promises . stat ( actualSshKeyPath ) ) . mode & 0 o777 ) . toBe (
0 o600
)
}
// Assert known hosts
const actualSshKnownHostsPath = await getActualSshKnownHostsPath ( )
const actualSshKnownHostsContent = (
await fs . promises . readFile ( actualSshKnownHostsPath )
) . toString ( )
expect ( actualSshKnownHostsContent ) . toMatch ( /github\.com ssh-rsa AAAAB3N/ )
} )
const configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet =
'configureGlobalAuth configures URL insteadOf when SSH key not set'
it ( configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet , async ( ) = > {
// Arrange
await setup ( configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet )
settings . sshKey = ''
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
await authHelper . configureGlobalAuth ( )
// Assert temporary global config
expect ( git . env [ 'HOME' ] ) . toBeTruthy ( )
const configContent = (
await fs . promises . readFile ( path . join ( git . env [ 'HOME' ] , '.gitconfig' ) )
) . toString ( )
expect (
configContent . indexOf ( ` url.https://github.com/.insteadOf git@github.com ` )
) . toBeGreaterThanOrEqual ( 0 )
} )
2020-03-05 22:21:59 +03:00
const configureGlobalAuth_copiesGlobalGitConfig =
'configureGlobalAuth copies global git config'
it ( configureGlobalAuth_copiesGlobalGitConfig , async ( ) = > {
// Arrange
await setup ( configureGlobalAuth_copiesGlobalGitConfig )
await fs . promises . writeFile ( globalGitConfigPath , 'value-from-global-config' )
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
await authHelper . configureGlobalAuth ( )
// Assert original global config not altered
let configContent = (
await fs . promises . readFile ( globalGitConfigPath )
) . toString ( )
expect ( configContent ) . toBe ( 'value-from-global-config' )
// Assert temporary global config
expect ( git . env [ 'HOME' ] ) . toBeTruthy ( )
const basicCredential = Buffer . from (
` x-access-token: ${ settings . authToken } ` ,
'utf8'
) . toString ( 'base64' )
configContent = (
await fs . promises . readFile ( path . join ( git . env [ 'HOME' ] , '.gitconfig' ) )
) . toString ( )
expect (
configContent . indexOf ( 'value-from-global-config' )
) . toBeGreaterThanOrEqual ( 0 )
expect (
configContent . indexOf (
` http.https://github.com/.extraheader AUTHORIZATION: basic ${ basicCredential } `
)
) . toBeGreaterThanOrEqual ( 0 )
} )
const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist =
'configureGlobalAuth creates new git config when global does not exist'
it (
configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist ,
async ( ) = > {
// Arrange
await setup (
configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist
)
await io . rmRF ( globalGitConfigPath )
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
// Act
await authHelper . configureAuth ( )
await authHelper . configureGlobalAuth ( )
// Assert original global config not recreated
try {
await fs . promises . stat ( globalGitConfigPath )
throw new Error (
` Did not expect file to exist: ' ${ globalGitConfigPath } ' `
)
} catch ( err ) {
2021-10-19 17:52:57 +03:00
if ( ( err as any ) ? . code !== 'ENOENT' ) {
2020-03-05 22:21:59 +03:00
throw err
}
}
// Assert temporary global config
expect ( git . env [ 'HOME' ] ) . toBeTruthy ( )
const basicCredential = Buffer . from (
` x-access-token: ${ settings . authToken } ` ,
'utf8'
) . toString ( 'base64' )
const configContent = (
await fs . promises . readFile ( path . join ( git . env [ 'HOME' ] , '.gitconfig' ) )
) . toString ( )
expect (
configContent . indexOf (
` http.https://github.com/.extraheader AUTHORIZATION: basic ${ basicCredential } `
)
) . toBeGreaterThanOrEqual ( 0 )
}
)
2020-03-12 18:42:38 +03:00
const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet =
'configureSubmoduleAuth configures submodules when persist credentials false and SSH key not set'
2020-03-11 22:55:17 +03:00
it (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet ,
2020-03-11 22:55:17 +03:00
async ( ) = > {
// Arrange
await setup (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet
2020-03-11 22:55:17 +03:00
)
2020-03-12 18:42:38 +03:00
settings . persistCredentials = false
2020-03-11 22:55:17 +03:00
settings . sshKey = ''
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
const mockSubmoduleForeach = git . submoduleForeach as jest . Mock < any , any >
mockSubmoduleForeach . mockClear ( ) // reset calls
// Act
await authHelper . configureSubmoduleAuth ( )
// Assert
2020-03-12 18:42:38 +03:00
expect ( mockSubmoduleForeach ) . toBeCalledTimes ( 1 )
expect ( mockSubmoduleForeach . mock . calls [ 0 ] [ 0 ] as string ) . toMatch (
2020-03-11 22:55:17 +03:00
/unset-all.*insteadOf/
)
}
)
2020-03-12 18:42:38 +03:00
const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet =
'configureSubmoduleAuth configures submodules when persist credentials false and SSH key set'
2020-03-11 22:55:17 +03:00
it (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet ,
2020-03-11 22:55:17 +03:00
async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
2020-03-12 18:42:38 +03:00
` Skipped test " ${ configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet } ". Executable 'ssh' not found in the PATH. \ n `
2020-03-11 22:55:17 +03:00
)
return
}
// Arrange
await setup (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet
2020-03-11 22:55:17 +03:00
)
2020-03-12 18:42:38 +03:00
settings . persistCredentials = false
2020-03-11 22:55:17 +03:00
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
const mockSubmoduleForeach = git . submoduleForeach as jest . Mock < any , any >
mockSubmoduleForeach . mockClear ( ) // reset calls
// Act
await authHelper . configureSubmoduleAuth ( )
// Assert
2020-03-12 18:42:38 +03:00
expect ( mockSubmoduleForeach ) . toHaveBeenCalledTimes ( 1 )
2020-03-11 22:55:17 +03:00
expect ( mockSubmoduleForeach . mock . calls [ 0 ] [ 0 ] ) . toMatch (
/unset-all.*insteadOf/
)
}
)
2020-03-12 18:42:38 +03:00
const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet =
'configureSubmoduleAuth configures submodules when persist credentials true and SSH key not set'
2020-03-05 22:21:59 +03:00
it (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet ,
2020-03-05 22:21:59 +03:00
async ( ) = > {
// Arrange
await setup (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet
2020-03-05 22:21:59 +03:00
)
2020-03-12 18:42:38 +03:00
settings . sshKey = ''
2020-03-05 22:21:59 +03:00
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
2020-03-11 22:55:17 +03:00
const mockSubmoduleForeach = git . submoduleForeach as jest . Mock < any , any >
mockSubmoduleForeach . mockClear ( ) // reset calls
// Act
await authHelper . configureSubmoduleAuth ( )
// Assert
2021-11-01 19:43:18 +03:00
expect ( mockSubmoduleForeach ) . toHaveBeenCalledTimes ( 4 )
2020-03-12 18:42:38 +03:00
expect ( mockSubmoduleForeach . mock . calls [ 0 ] [ 0 ] ) . toMatch (
2020-03-11 22:55:17 +03:00
/unset-all.*insteadOf/
)
2020-03-12 18:42:38 +03:00
expect ( mockSubmoduleForeach . mock . calls [ 1 ] [ 0 ] ) . toMatch ( /http.*extraheader/ )
2021-11-01 19:43:18 +03:00
expect ( mockSubmoduleForeach . mock . calls [ 2 ] [ 0 ] ) . toMatch (
/url.*insteadOf.*git@github.com:/
)
expect ( mockSubmoduleForeach . mock . calls [ 3 ] [ 0 ] ) . toMatch (
/url.*insteadOf.*org-123456@github.com:/
)
2020-03-11 22:55:17 +03:00
}
)
2020-03-12 18:42:38 +03:00
const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet =
'configureSubmoduleAuth configures submodules when persist credentials true and SSH key set'
2020-03-11 22:55:17 +03:00
it (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet ,
2020-03-11 22:55:17 +03:00
async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
2020-03-12 18:42:38 +03:00
` Skipped test " ${ configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet } ". Executable 'ssh' not found in the PATH. \ n `
2020-03-11 22:55:17 +03:00
)
return
}
// Arrange
await setup (
2020-03-12 18:42:38 +03:00
configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet
2020-03-11 22:55:17 +03:00
)
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
const mockSubmoduleForeach = git . submoduleForeach as jest . Mock < any , any >
mockSubmoduleForeach . mockClear ( ) // reset calls
2020-03-05 22:21:59 +03:00
// Act
await authHelper . configureSubmoduleAuth ( )
// Assert
2020-03-12 18:42:38 +03:00
expect ( mockSubmoduleForeach ) . toHaveBeenCalledTimes ( 3 )
2020-03-11 22:55:17 +03:00
expect ( mockSubmoduleForeach . mock . calls [ 0 ] [ 0 ] ) . toMatch (
/unset-all.*insteadOf/
)
expect ( mockSubmoduleForeach . mock . calls [ 1 ] [ 0 ] ) . toMatch ( /http.*extraheader/ )
2020-03-12 18:42:38 +03:00
expect ( mockSubmoduleForeach . mock . calls [ 2 ] [ 0 ] ) . toMatch ( /core\.sshCommand/ )
2020-03-05 22:21:59 +03:00
}
)
2020-03-11 22:55:17 +03:00
const removeAuth_removesSshCommand = 'removeAuth removes SSH command'
it ( removeAuth_removesSshCommand , async ( ) = > {
if ( ! sshPath ) {
process . stdout . write (
` Skipped test " ${ removeAuth_removesSshCommand } ". Executable 'ssh' not found in the PATH. \ n `
)
return
}
// Arrange
await setup ( removeAuth_removesSshCommand )
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
let gitConfigContent = (
await fs . promises . readFile ( localGitConfigPath )
) . toString ( )
expect ( gitConfigContent . indexOf ( 'core.sshCommand' ) ) . toBeGreaterThanOrEqual (
0
) // sanity check
const actualKeyPath = await getActualSshKeyPath ( )
expect ( actualKeyPath ) . toBeTruthy ( )
await fs . promises . stat ( actualKeyPath )
const actualKnownHostsPath = await getActualSshKnownHostsPath ( )
expect ( actualKnownHostsPath ) . toBeTruthy ( )
await fs . promises . stat ( actualKnownHostsPath )
// Act
await authHelper . removeAuth ( )
// Assert git config
gitConfigContent = (
await fs . promises . readFile ( localGitConfigPath )
) . toString ( )
expect ( gitConfigContent . indexOf ( 'core.sshCommand' ) ) . toBeLessThan ( 0 )
// Assert SSH key file
try {
await fs . promises . stat ( actualKeyPath )
throw new Error ( 'SSH key should have been deleted' )
} catch ( err ) {
2021-10-19 17:52:57 +03:00
if ( ( err as any ) ? . code !== 'ENOENT' ) {
2020-03-11 22:55:17 +03:00
throw err
}
}
// Assert known hosts file
try {
await fs . promises . stat ( actualKnownHostsPath )
throw new Error ( 'SSH known hosts should have been deleted' )
} catch ( err ) {
2021-10-19 17:52:57 +03:00
if ( ( err as any ) ? . code !== 'ENOENT' ) {
2020-03-11 22:55:17 +03:00
throw err
}
}
} )
2020-03-05 22:21:59 +03:00
const removeAuth_removesToken = 'removeAuth removes token'
it ( removeAuth_removesToken , async ( ) = > {
2020-03-02 19:33:30 +03:00
// Arrange
2020-03-05 22:21:59 +03:00
await setup ( removeAuth_removesToken )
2020-03-02 19:33:30 +03:00
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
let gitConfigContent = (
2020-03-05 22:21:59 +03:00
await fs . promises . readFile ( localGitConfigPath )
2020-03-02 19:33:30 +03:00
) . toString ( )
expect ( gitConfigContent . indexOf ( 'http.' ) ) . toBeGreaterThanOrEqual ( 0 ) // sanity check
// Act
await authHelper . removeAuth ( )
// Assert git config
2020-03-05 22:21:59 +03:00
gitConfigContent = (
await fs . promises . readFile ( localGitConfigPath )
) . toString ( )
2020-03-02 19:33:30 +03:00
expect ( gitConfigContent . indexOf ( 'http.' ) ) . toBeLessThan ( 0 )
} )
2020-03-05 22:21:59 +03:00
2022-04-14 21:13:20 +03:00
const removeGlobalConfig_removesOverride =
'removeGlobalConfig removes override'
it ( removeGlobalConfig_removesOverride , async ( ) = > {
2020-03-05 22:21:59 +03:00
// Arrange
2022-04-14 21:13:20 +03:00
await setup ( removeGlobalConfig_removesOverride )
2020-03-05 22:21:59 +03:00
const authHelper = gitAuthHelper . createAuthHelper ( git , settings )
await authHelper . configureAuth ( )
await authHelper . configureGlobalAuth ( )
const homeOverride = git . env [ 'HOME' ] // Sanity check
expect ( homeOverride ) . toBeTruthy ( )
await fs . promises . stat ( path . join ( git . env [ 'HOME' ] , '.gitconfig' ) )
// Act
2022-04-14 21:13:20 +03:00
await authHelper . removeGlobalConfig ( )
2020-03-05 22:21:59 +03:00
// Assert
expect ( git . env [ 'HOME' ] ) . toBeUndefined ( )
try {
await fs . promises . stat ( homeOverride )
throw new Error ( ` Should have been deleted ' ${ homeOverride } ' ` )
} catch ( err ) {
2021-10-19 17:52:57 +03:00
if ( ( err as any ) ? . code !== 'ENOENT' ) {
2020-03-05 22:21:59 +03:00
throw err
}
}
} )
2020-03-02 19:33:30 +03:00
} )
async function setup ( testName : string ) : Promise < void > {
testName = testName . replace ( /[^a-zA-Z0-9_]+/g , '-' )
// Directories
workspace = path . join ( testWorkspace , testName , 'workspace' )
runnerTemp = path . join ( testWorkspace , testName , 'runner-temp' )
2020-03-05 22:21:59 +03:00
tempHomedir = path . join ( testWorkspace , testName , 'home-dir' )
2020-03-02 19:33:30 +03:00
await fs . promises . mkdir ( workspace , { recursive : true } )
await fs . promises . mkdir ( runnerTemp , { recursive : true } )
2020-03-05 22:21:59 +03:00
await fs . promises . mkdir ( tempHomedir , { recursive : true } )
2020-03-02 19:33:30 +03:00
process . env [ 'RUNNER_TEMP' ] = runnerTemp
2020-03-05 22:21:59 +03:00
process . env [ 'HOME' ] = tempHomedir
2020-03-02 19:33:30 +03:00
// Create git config
2020-03-05 22:21:59 +03:00
globalGitConfigPath = path . join ( tempHomedir , '.gitconfig' )
await fs . promises . writeFile ( globalGitConfigPath , '' )
localGitConfigPath = path . join ( workspace , '.git' , 'config' )
await fs . promises . mkdir ( path . dirname ( localGitConfigPath ) , { recursive : true } )
await fs . promises . writeFile ( localGitConfigPath , '' )
2020-03-02 19:33:30 +03:00
git = {
branchDelete : jest.fn ( ) ,
branchExists : jest.fn ( ) ,
branchList : jest.fn ( ) ,
2024-02-21 15:56:19 +03:00
disableSparseCheckout : jest.fn ( ) ,
2023-06-09 16:08:21 +03:00
sparseCheckout : jest.fn ( ) ,
sparseCheckoutNonConeMode : jest.fn ( ) ,
2020-03-02 19:33:30 +03:00
checkout : jest.fn ( ) ,
checkoutDetach : jest.fn ( ) ,
2020-03-05 22:21:59 +03:00
config : jest.fn (
async ( key : string , value : string , globalConfig? : boolean ) = > {
const configPath = globalConfig
? path . join ( git . env [ 'HOME' ] || tempHomedir , '.gitconfig' )
: localGitConfigPath
await fs . promises . appendFile ( configPath , ` \ n ${ key } ${ value } ` )
}
) ,
2020-03-02 19:33:30 +03:00
configExists : jest.fn (
2020-03-05 22:21:59 +03:00
async ( key : string , globalConfig? : boolean ) : Promise < boolean > = > {
const configPath = globalConfig
? path . join ( git . env [ 'HOME' ] || tempHomedir , '.gitconfig' )
: localGitConfigPath
const content = await fs . promises . readFile ( configPath )
2020-03-02 19:33:30 +03:00
const lines = content
. toString ( )
. split ( '\n' )
. filter ( x = > x )
return lines . some ( x = > x . startsWith ( key ) )
}
) ,
2020-03-05 22:21:59 +03:00
env : { } ,
2020-03-02 19:33:30 +03:00
fetch : jest.fn ( ) ,
2020-06-18 17:20:33 +03:00
getDefaultBranch : jest.fn ( ) ,
2020-03-02 19:33:30 +03:00
getWorkingDirectory : jest.fn ( ( ) = > workspace ) ,
init : jest.fn ( ) ,
isDetached : jest.fn ( ) ,
lfsFetch : jest.fn ( ) ,
lfsInstall : jest.fn ( ) ,
log1 : jest.fn ( ) ,
remoteAdd : jest.fn ( ) ,
2020-03-05 22:21:59 +03:00
removeEnvironmentVariable : jest.fn ( ( name : string ) = > delete git . env [ name ] ) ,
2020-05-27 16:54:28 +03:00
revParse : jest.fn ( ) ,
2020-03-05 22:21:59 +03:00
setEnvironmentVariable : jest.fn ( ( name : string , value : string ) = > {
git . env [ name ] = value
} ) ,
2020-05-27 16:54:28 +03:00
shaExists : jest.fn ( ) ,
2020-03-05 22:21:59 +03:00
submoduleForeach : jest.fn ( async ( ) = > {
return ''
} ) ,
submoduleSync : jest.fn ( ) ,
2023-04-14 13:26:47 +03:00
submoduleStatus : jest.fn ( async ( ) = > {
return true
} ) ,
2020-03-05 22:21:59 +03:00
submoduleUpdate : jest.fn ( ) ,
2020-03-02 19:33:30 +03:00
tagExists : jest.fn ( ) ,
tryClean : jest.fn ( ) ,
tryConfigUnset : jest.fn (
2020-03-05 22:21:59 +03:00
async ( key : string , globalConfig? : boolean ) : Promise < boolean > = > {
const configPath = globalConfig
? path . join ( git . env [ 'HOME' ] || tempHomedir , '.gitconfig' )
: localGitConfigPath
let content = await fs . promises . readFile ( configPath )
2020-03-02 19:33:30 +03:00
let lines = content
. toString ( )
. split ( '\n' )
. filter ( x = > x )
. filter ( x = > ! x . startsWith ( key ) )
2020-03-05 22:21:59 +03:00
await fs . promises . writeFile ( configPath , lines . join ( '\n' ) )
2020-03-02 19:33:30 +03:00
return true
}
) ,
tryDisableAutomaticGarbageCollection : jest.fn ( ) ,
tryGetFetchUrl : jest.fn ( ) ,
2024-03-14 17:40:14 +03:00
tryReset : jest.fn ( ) ,
version : jest.fn ( )
2020-03-02 19:33:30 +03:00
}
settings = {
authToken : 'some auth token' ,
clean : true ,
commit : '' ,
2023-09-22 20:30:36 +03:00
filter : undefined ,
2023-06-09 16:08:21 +03:00
sparseCheckout : [ ] ,
sparseCheckoutConeMode : true ,
2020-03-02 19:33:30 +03:00
fetchDepth : 1 ,
2023-08-16 23:34:54 +03:00
fetchTags : false ,
2023-09-01 21:19:18 +03:00
showProgress : true ,
2020-03-02 19:33:30 +03:00
lfs : false ,
2020-03-05 22:21:59 +03:00
submodules : false ,
nestedSubmodules : false ,
2020-03-02 19:33:30 +03:00
persistCredentials : true ,
2020-07-14 16:23:30 +03:00
ref : 'refs/heads/main' ,
2020-03-02 19:33:30 +03:00
repositoryName : 'my-repo' ,
repositoryOwner : 'my-org' ,
2020-03-11 22:55:17 +03:00
repositoryPath : '' ,
sshKey : sshPath ? 'some ssh private key' : '' ,
sshKnownHosts : '' ,
2021-11-01 19:43:18 +03:00
sshStrict : true ,
2024-04-18 22:29:55 +03:00
sshUser : '' ,
2022-04-21 04:37:43 +03:00
workflowOrganizationId : 123456 ,
2022-09-26 19:34:52 +03:00
setSafeDirectory : true ,
githubServerUrl : githubServerUrl
2020-03-11 22:55:17 +03:00
}
}
async function getActualSshKeyPath ( ) : Promise < string > {
let actualTempFiles = ( await fs . promises . readdir ( runnerTemp ) )
. sort ( )
. map ( x = > path . join ( runnerTemp , x ) )
if ( actualTempFiles . length === 0 ) {
return ''
2020-03-02 19:33:30 +03:00
}
2020-03-11 22:55:17 +03:00
expect ( actualTempFiles ) . toHaveLength ( 2 )
expect ( actualTempFiles [ 0 ] . endsWith ( '_known_hosts' ) ) . toBeFalsy ( )
return actualTempFiles [ 0 ]
}
async function getActualSshKnownHostsPath ( ) : Promise < string > {
let actualTempFiles = ( await fs . promises . readdir ( runnerTemp ) )
. sort ( )
. map ( x = > path . join ( runnerTemp , x ) )
if ( actualTempFiles . length === 0 ) {
return ''
}
expect ( actualTempFiles ) . toHaveLength ( 2 )
expect ( actualTempFiles [ 1 ] . endsWith ( '_known_hosts' ) ) . toBeTruthy ( )
expect ( actualTempFiles [ 1 ] . startsWith ( actualTempFiles [ 0 ] ) ) . toBeTruthy ( )
return actualTempFiles [ 1 ]
2020-03-02 19:33:30 +03:00
}