mirror of https://github.com/actions/checkout.git
Compare commits
2 Commits
8b396d5a81
...
9b6f4a6bf2
Author | SHA1 | Date |
---|---|---|
![]() |
9b6f4a6bf2 | |
![]() |
cb17bfb94d |
|
@ -706,7 +706,7 @@ describe('git-auth-helper tests', () => {
|
||||||
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
||||||
await authHelper.configureAuth()
|
await authHelper.configureAuth()
|
||||||
|
|
||||||
// Sanity check - verify includeIf entries exist in local config
|
// Verify includeIf entries exist in local config
|
||||||
let localConfigContent = (
|
let localConfigContent = (
|
||||||
await fs.promises.readFile(localGitConfigPath)
|
await fs.promises.readFile(localGitConfigPath)
|
||||||
).toString()
|
).toString()
|
||||||
|
@ -714,26 +714,192 @@ describe('git-auth-helper tests', () => {
|
||||||
localConfigContent.indexOf('includeIf.gitdir:')
|
localConfigContent.indexOf('includeIf.gitdir:')
|
||||||
).toBeGreaterThanOrEqual(0)
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
// Sanity check - verify credentials file exists
|
// Verify both host and container includeIf entries are present
|
||||||
|
const hostGitDir = path.join(workspace, '.git').replace(/\\/g, '/')
|
||||||
|
expect(
|
||||||
|
localConfigContent.indexOf(`includeIf.gitdir:${hostGitDir}.path`)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
localConfigContent.indexOf('includeIf.gitdir:/github/workspace/.git.path')
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Verify credentials file exists
|
||||||
let credentialsFiles = (await fs.promises.readdir(runnerTemp)).filter(
|
let credentialsFiles = (await fs.promises.readdir(runnerTemp)).filter(
|
||||||
f => f.startsWith('git-credentials-') && f.endsWith('.config')
|
f => f.startsWith('git-credentials-') && f.endsWith('.config')
|
||||||
)
|
)
|
||||||
expect(credentialsFiles.length).toBe(1)
|
expect(credentialsFiles.length).toBe(1)
|
||||||
|
const credentialsFilePath = path.join(runnerTemp, credentialsFiles[0])
|
||||||
|
|
||||||
|
// Verify credentials file contains the auth token
|
||||||
|
let credentialsContent = (
|
||||||
|
await fs.promises.readFile(credentialsFilePath)
|
||||||
|
).toString()
|
||||||
|
const basicCredential = Buffer.from(
|
||||||
|
`x-access-token:${settings.authToken}`,
|
||||||
|
'utf8'
|
||||||
|
).toString('base64')
|
||||||
|
expect(
|
||||||
|
credentialsContent.indexOf(
|
||||||
|
`http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
|
||||||
|
)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Verify the includeIf entries point to the credentials file
|
||||||
|
const containerCredentialsPath = path.posix.join(
|
||||||
|
'/github/runner_temp',
|
||||||
|
path.basename(credentialsFilePath)
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
localConfigContent.indexOf(credentialsFilePath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
localConfigContent.indexOf(containerCredentialsPath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authHelper.removeAuth()
|
await authHelper.removeAuth()
|
||||||
|
|
||||||
// Assert includeIf entries removed from local git config
|
// Assert all includeIf entries removed from local git config
|
||||||
localConfigContent = (
|
localConfigContent = (
|
||||||
await fs.promises.readFile(localGitConfigPath)
|
await fs.promises.readFile(localGitConfigPath)
|
||||||
).toString()
|
).toString()
|
||||||
expect(localConfigContent.indexOf('includeIf.gitdir:')).toBeLessThan(0)
|
expect(localConfigContent.indexOf('includeIf.gitdir:')).toBeLessThan(0)
|
||||||
|
expect(
|
||||||
|
localConfigContent.indexOf(`includeIf.gitdir:${hostGitDir}.path`)
|
||||||
|
).toBeLessThan(0)
|
||||||
|
expect(
|
||||||
|
localConfigContent.indexOf('includeIf.gitdir:/github/workspace/.git.path')
|
||||||
|
).toBeLessThan(0)
|
||||||
|
expect(localConfigContent.indexOf(credentialsFilePath)).toBeLessThan(0)
|
||||||
|
expect(localConfigContent.indexOf(containerCredentialsPath)).toBeLessThan(0)
|
||||||
|
|
||||||
// Assert credentials config file deleted
|
// Assert credentials config file deleted
|
||||||
credentialsFiles = (await fs.promises.readdir(runnerTemp)).filter(
|
credentialsFiles = (await fs.promises.readdir(runnerTemp)).filter(
|
||||||
f => f.startsWith('git-credentials-') && f.endsWith('.config')
|
f => f.startsWith('git-credentials-') && f.endsWith('.config')
|
||||||
)
|
)
|
||||||
expect(credentialsFiles.length).toBe(0)
|
expect(credentialsFiles.length).toBe(0)
|
||||||
|
|
||||||
|
// Verify credentials file no longer exists on disk
|
||||||
|
try {
|
||||||
|
await fs.promises.stat(credentialsFilePath)
|
||||||
|
throw new Error('Credentials file should have been deleted')
|
||||||
|
} catch (err) {
|
||||||
|
if ((err as any)?.code !== 'ENOENT') {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const removeAuth_removesTokenFromSubmodules =
|
||||||
|
'removeAuth removes token from submodules'
|
||||||
|
it(removeAuth_removesTokenFromSubmodules, async () => {
|
||||||
|
// Arrange
|
||||||
|
await setup(removeAuth_removesTokenFromSubmodules)
|
||||||
|
|
||||||
|
// Create fake submodule config paths
|
||||||
|
const submodule1Dir = path.join(workspace, '.git', 'modules', 'submodule-1')
|
||||||
|
const submodule2Dir = path.join(workspace, '.git', 'modules', 'submodule-2')
|
||||||
|
const submodule1ConfigPath = path.join(submodule1Dir, 'config')
|
||||||
|
const submodule2ConfigPath = path.join(submodule2Dir, 'config')
|
||||||
|
|
||||||
|
await fs.promises.mkdir(submodule1Dir, {recursive: true})
|
||||||
|
await fs.promises.mkdir(submodule2Dir, {recursive: true})
|
||||||
|
await fs.promises.writeFile(submodule1ConfigPath, '')
|
||||||
|
await fs.promises.writeFile(submodule2ConfigPath, '')
|
||||||
|
|
||||||
|
// Mock getSubmoduleConfigPaths to return our fake submodules (for both configure and remove)
|
||||||
|
const mockGetSubmoduleConfigPaths =
|
||||||
|
git.getSubmoduleConfigPaths as jest.Mock<any, any>
|
||||||
|
mockGetSubmoduleConfigPaths.mockResolvedValue([
|
||||||
|
submodule1ConfigPath,
|
||||||
|
submodule2ConfigPath
|
||||||
|
])
|
||||||
|
|
||||||
|
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
||||||
|
await authHelper.configureAuth()
|
||||||
|
await authHelper.configureSubmoduleAuth()
|
||||||
|
|
||||||
|
// Verify credentials file exists
|
||||||
|
let credentialsFiles = (await fs.promises.readdir(runnerTemp)).filter(
|
||||||
|
f => f.startsWith('git-credentials-') && f.endsWith('.config')
|
||||||
|
)
|
||||||
|
expect(credentialsFiles.length).toBe(1)
|
||||||
|
const credentialsFilePath = path.join(runnerTemp, credentialsFiles[0])
|
||||||
|
|
||||||
|
// Verify submodule 1 config has includeIf entries
|
||||||
|
let submodule1Content = (
|
||||||
|
await fs.promises.readFile(submodule1ConfigPath)
|
||||||
|
).toString()
|
||||||
|
const submodule1GitDir = submodule1Dir.replace(/\\/g, '/')
|
||||||
|
expect(
|
||||||
|
submodule1Content.indexOf(`includeIf.gitdir:${submodule1GitDir}.path`)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
submodule1Content.indexOf(credentialsFilePath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Verify submodule 2 config has includeIf entries
|
||||||
|
let submodule2Content = (
|
||||||
|
await fs.promises.readFile(submodule2ConfigPath)
|
||||||
|
).toString()
|
||||||
|
const submodule2GitDir = submodule2Dir.replace(/\\/g, '/')
|
||||||
|
expect(
|
||||||
|
submodule2Content.indexOf(`includeIf.gitdir:${submodule2GitDir}.path`)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
submodule2Content.indexOf(credentialsFilePath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Verify both host and container paths are in each submodule config
|
||||||
|
const containerCredentialsPath = path.posix.join(
|
||||||
|
'/github/runner_temp',
|
||||||
|
path.basename(credentialsFilePath)
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
submodule1Content.indexOf(containerCredentialsPath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
submodule2Content.indexOf(containerCredentialsPath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Act - ensure mock persists for removeAuth
|
||||||
|
mockGetSubmoduleConfigPaths.mockResolvedValue([
|
||||||
|
submodule1ConfigPath,
|
||||||
|
submodule2ConfigPath
|
||||||
|
])
|
||||||
|
await authHelper.removeAuth()
|
||||||
|
|
||||||
|
// Assert submodule 1 includeIf entries removed
|
||||||
|
submodule1Content = (
|
||||||
|
await fs.promises.readFile(submodule1ConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(submodule1Content.indexOf('includeIf.gitdir:')).toBeLessThan(0)
|
||||||
|
expect(submodule1Content.indexOf(credentialsFilePath)).toBeLessThan(0)
|
||||||
|
expect(submodule1Content.indexOf(containerCredentialsPath)).toBeLessThan(0)
|
||||||
|
|
||||||
|
// Assert submodule 2 includeIf entries removed
|
||||||
|
submodule2Content = (
|
||||||
|
await fs.promises.readFile(submodule2ConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(submodule2Content.indexOf('includeIf.gitdir:')).toBeLessThan(0)
|
||||||
|
expect(submodule2Content.indexOf(credentialsFilePath)).toBeLessThan(0)
|
||||||
|
expect(submodule2Content.indexOf(containerCredentialsPath)).toBeLessThan(0)
|
||||||
|
|
||||||
|
// Assert credentials config file deleted
|
||||||
|
credentialsFiles = (await fs.promises.readdir(runnerTemp)).filter(
|
||||||
|
f => f.startsWith('git-credentials-') && f.endsWith('.config')
|
||||||
|
)
|
||||||
|
expect(credentialsFiles.length).toBe(0)
|
||||||
|
|
||||||
|
// Verify credentials file no longer exists on disk
|
||||||
|
try {
|
||||||
|
await fs.promises.stat(credentialsFilePath)
|
||||||
|
throw new Error('Credentials file should have been deleted')
|
||||||
|
} catch (err) {
|
||||||
|
if ((err as any)?.code !== 'ENOENT') {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const removeGlobalConfig_removesOverride =
|
const removeGlobalConfig_removesOverride =
|
||||||
|
@ -917,29 +1083,38 @@ async function setup(testName: string): Promise<void> {
|
||||||
async (
|
async (
|
||||||
key: string,
|
key: string,
|
||||||
value: string,
|
value: string,
|
||||||
globalConfig?: boolean
|
globalConfig?: boolean,
|
||||||
|
configPath?: string
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
const configPath = globalConfig
|
const targetConfigPath =
|
||||||
? path.join(git.env['HOME'] || tempHomedir, '.gitconfig')
|
configPath ||
|
||||||
: localGitConfigPath
|
(globalConfig
|
||||||
let content = await fs.promises.readFile(configPath)
|
? path.join(git.env['HOME'] || tempHomedir, '.gitconfig')
|
||||||
|
: localGitConfigPath)
|
||||||
|
let content = await fs.promises.readFile(targetConfigPath)
|
||||||
let lines = content
|
let lines = content
|
||||||
.toString()
|
.toString()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter(x => x)
|
.filter(x => x)
|
||||||
.filter(x => !(x.startsWith(key) && x.includes(value)))
|
.filter(x => !(x.startsWith(key) && x.includes(value)))
|
||||||
await fs.promises.writeFile(configPath, lines.join('\n'))
|
await fs.promises.writeFile(targetConfigPath, lines.join('\n'))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
tryDisableAutomaticGarbageCollection: jest.fn(),
|
tryDisableAutomaticGarbageCollection: jest.fn(),
|
||||||
tryGetFetchUrl: jest.fn(),
|
tryGetFetchUrl: jest.fn(),
|
||||||
tryGetConfigValues: jest.fn(
|
tryGetConfigValues: jest.fn(
|
||||||
async (key: string, globalConfig?: boolean): Promise<string[]> => {
|
async (
|
||||||
const configPath = globalConfig
|
key: string,
|
||||||
? path.join(git.env['HOME'] || tempHomedir, '.gitconfig')
|
globalConfig?: boolean,
|
||||||
: localGitConfigPath
|
configPath?: string
|
||||||
const content = await fs.promises.readFile(configPath)
|
): Promise<string[]> => {
|
||||||
|
const targetConfigPath =
|
||||||
|
configPath ||
|
||||||
|
(globalConfig
|
||||||
|
? path.join(git.env['HOME'] || tempHomedir, '.gitconfig')
|
||||||
|
: localGitConfigPath)
|
||||||
|
const content = await fs.promises.readFile(targetConfigPath)
|
||||||
const lines = content
|
const lines = content
|
||||||
.toString()
|
.toString()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
|
@ -949,11 +1124,17 @@ async function setup(testName: string): Promise<void> {
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
tryGetConfigKeys: jest.fn(
|
tryGetConfigKeys: jest.fn(
|
||||||
async (pattern: string, globalConfig?: boolean): Promise<string[]> => {
|
async (
|
||||||
const configPath = globalConfig
|
pattern: string,
|
||||||
? path.join(git.env['HOME'] || tempHomedir, '.gitconfig')
|
globalConfig?: boolean,
|
||||||
: localGitConfigPath
|
configPath?: string
|
||||||
const content = await fs.promises.readFile(configPath)
|
): Promise<string[]> => {
|
||||||
|
const targetConfigPath =
|
||||||
|
configPath ||
|
||||||
|
(globalConfig
|
||||||
|
? path.join(git.env['HOME'] || tempHomedir, '.gitconfig')
|
||||||
|
: localGitConfigPath)
|
||||||
|
const content = await fs.promises.readFile(targetConfigPath)
|
||||||
const lines = content
|
const lines = content
|
||||||
.toString()
|
.toString()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
|
|
Loading…
Reference in New Issue