git-auth-helper.test.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import * as core from '@actions/core'
  2. import * as fs from 'fs'
  3. import * as gitAuthHelper from '../lib/git-auth-helper'
  4. import * as io from '@actions/io'
  5. import * as path from 'path'
  6. import {IGitCommandManager} from '../lib/git-command-manager'
  7. import {IGitSourceSettings} from '../lib/git-source-settings'
  8. const testWorkspace = path.join(__dirname, '_temp', 'git-auth-helper')
  9. const originalRunnerTemp = process.env['RUNNER_TEMP']
  10. let workspace: string
  11. let gitConfigPath: string
  12. let runnerTemp: string
  13. let git: IGitCommandManager
  14. let settings: IGitSourceSettings
  15. describe('git-auth-helper tests', () => {
  16. beforeAll(async () => {
  17. // Clear test workspace
  18. await io.rmRF(testWorkspace)
  19. })
  20. beforeEach(() => {
  21. // Mock setSecret
  22. jest.spyOn(core, 'setSecret').mockImplementation((secret: string) => {})
  23. })
  24. afterEach(() => {
  25. // Unregister mocks
  26. jest.restoreAllMocks()
  27. })
  28. afterAll(() => {
  29. // Restore RUNNER_TEMP
  30. delete process.env['RUNNER_TEMP']
  31. if (originalRunnerTemp) {
  32. process.env['RUNNER_TEMP'] = originalRunnerTemp
  33. }
  34. })
  35. const configuresAuthHeader = 'configures auth header'
  36. it(configuresAuthHeader, async () => {
  37. // Arrange
  38. await setup(configuresAuthHeader)
  39. expect(settings.authToken).toBeTruthy() // sanity check
  40. const authHelper = gitAuthHelper.createAuthHelper(git, settings)
  41. // Act
  42. await authHelper.configureAuth()
  43. // Assert config
  44. const configContent = (await fs.promises.readFile(gitConfigPath)).toString()
  45. const basicCredential = Buffer.from(
  46. `x-access-token:${settings.authToken}`,
  47. 'utf8'
  48. ).toString('base64')
  49. expect(
  50. configContent.indexOf(
  51. `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
  52. )
  53. ).toBeGreaterThanOrEqual(0)
  54. })
  55. const configuresAuthHeaderEvenWhenPersistCredentialsFalse =
  56. 'configures auth header even when persist credentials false'
  57. it(configuresAuthHeaderEvenWhenPersistCredentialsFalse, async () => {
  58. // Arrange
  59. await setup(configuresAuthHeaderEvenWhenPersistCredentialsFalse)
  60. expect(settings.authToken).toBeTruthy() // sanity check
  61. settings.persistCredentials = false
  62. const authHelper = gitAuthHelper.createAuthHelper(git, settings)
  63. // Act
  64. await authHelper.configureAuth()
  65. // Assert config
  66. const configContent = (await fs.promises.readFile(gitConfigPath)).toString()
  67. expect(
  68. configContent.indexOf(
  69. `http.https://github.com/.extraheader AUTHORIZATION`
  70. )
  71. ).toBeGreaterThanOrEqual(0)
  72. })
  73. const registersBasicCredentialAsSecret =
  74. 'registers basic credential as secret'
  75. it(registersBasicCredentialAsSecret, async () => {
  76. // Arrange
  77. await setup(registersBasicCredentialAsSecret)
  78. expect(settings.authToken).toBeTruthy() // sanity check
  79. const authHelper = gitAuthHelper.createAuthHelper(git, settings)
  80. // Act
  81. await authHelper.configureAuth()
  82. // Assert secret
  83. const setSecretSpy = core.setSecret as jest.Mock<any, any>
  84. expect(setSecretSpy).toHaveBeenCalledTimes(1)
  85. const expectedSecret = Buffer.from(
  86. `x-access-token:${settings.authToken}`,
  87. 'utf8'
  88. ).toString('base64')
  89. expect(setSecretSpy).toHaveBeenCalledWith(expectedSecret)
  90. })
  91. const removesToken = 'removes token'
  92. it(removesToken, async () => {
  93. // Arrange
  94. await setup(removesToken)
  95. const authHelper = gitAuthHelper.createAuthHelper(git, settings)
  96. await authHelper.configureAuth()
  97. let gitConfigContent = (
  98. await fs.promises.readFile(gitConfigPath)
  99. ).toString()
  100. expect(gitConfigContent.indexOf('http.')).toBeGreaterThanOrEqual(0) // sanity check
  101. // Act
  102. await authHelper.removeAuth()
  103. // Assert git config
  104. gitConfigContent = (await fs.promises.readFile(gitConfigPath)).toString()
  105. expect(gitConfigContent.indexOf('http.')).toBeLessThan(0)
  106. })
  107. })
  108. async function setup(testName: string): Promise<void> {
  109. testName = testName.replace(/[^a-zA-Z0-9_]+/g, '-')
  110. // Directories
  111. workspace = path.join(testWorkspace, testName, 'workspace')
  112. runnerTemp = path.join(testWorkspace, testName, 'runner-temp')
  113. await fs.promises.mkdir(workspace, {recursive: true})
  114. await fs.promises.mkdir(runnerTemp, {recursive: true})
  115. process.env['RUNNER_TEMP'] = runnerTemp
  116. // Create git config
  117. gitConfigPath = path.join(workspace, '.git', 'config')
  118. await fs.promises.mkdir(path.join(workspace, '.git'), {recursive: true})
  119. await fs.promises.writeFile(path.join(workspace, '.git', 'config'), '')
  120. git = {
  121. branchDelete: jest.fn(),
  122. branchExists: jest.fn(),
  123. branchList: jest.fn(),
  124. checkout: jest.fn(),
  125. checkoutDetach: jest.fn(),
  126. config: jest.fn(async (key: string, value: string) => {
  127. await fs.promises.appendFile(gitConfigPath, `\n${key} ${value}`)
  128. }),
  129. configExists: jest.fn(
  130. async (key: string): Promise<boolean> => {
  131. const content = await fs.promises.readFile(gitConfigPath)
  132. const lines = content
  133. .toString()
  134. .split('\n')
  135. .filter(x => x)
  136. return lines.some(x => x.startsWith(key))
  137. }
  138. ),
  139. fetch: jest.fn(),
  140. getWorkingDirectory: jest.fn(() => workspace),
  141. init: jest.fn(),
  142. isDetached: jest.fn(),
  143. lfsFetch: jest.fn(),
  144. lfsInstall: jest.fn(),
  145. log1: jest.fn(),
  146. remoteAdd: jest.fn(),
  147. setEnvironmentVariable: jest.fn(),
  148. tagExists: jest.fn(),
  149. tryClean: jest.fn(),
  150. tryConfigUnset: jest.fn(
  151. async (key: string): Promise<boolean> => {
  152. let content = await fs.promises.readFile(gitConfigPath)
  153. let lines = content
  154. .toString()
  155. .split('\n')
  156. .filter(x => x)
  157. .filter(x => !x.startsWith(key))
  158. await fs.promises.writeFile(gitConfigPath, lines.join('\n'))
  159. return true
  160. }
  161. ),
  162. tryDisableAutomaticGarbageCollection: jest.fn(),
  163. tryGetFetchUrl: jest.fn(),
  164. tryReset: jest.fn()
  165. }
  166. settings = {
  167. authToken: 'some auth token',
  168. clean: true,
  169. commit: '',
  170. fetchDepth: 1,
  171. lfs: false,
  172. persistCredentials: true,
  173. ref: 'refs/heads/master',
  174. repositoryName: 'my-repo',
  175. repositoryOwner: 'my-org',
  176. repositoryPath: ''
  177. }
  178. }