| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- import * as exec from '@actions/exec'
- import * as fshelper from '../lib/fs-helper'
- import * as commandManager from '../lib/git-command-manager'
- let git: commandManager.IGitCommandManager
- let mockExec = jest.fn()
- describe('git-auth-helper tests', () => {
- beforeAll(async () => {})
- beforeEach(async () => {
- jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
- jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
- })
- afterEach(() => {
- jest.restoreAllMocks()
- })
- afterAll(() => {})
- it('branch list matches', async () => {
- mockExec.mockImplementation((path, args, options) => {
- console.log(args, options.listeners.stdout)
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('2.18'))
- return 0
- }
- if (args.includes('rev-parse')) {
- options.listeners.stdline(Buffer.from('refs/heads/foo'))
- options.listeners.stdline(Buffer.from('refs/heads/bar'))
- return 0
- }
- return 1
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- let branches = await git.branchList(false)
- expect(branches).toHaveLength(2)
- expect(branches.sort()).toEqual(['foo', 'bar'].sort())
- })
- it('ambiguous ref name output is captured', async () => {
- mockExec.mockImplementation((path, args, options) => {
- console.log(args, options.listeners.stdout)
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('2.18'))
- return 0
- }
- if (args.includes('rev-parse')) {
- options.listeners.stdline(Buffer.from('refs/heads/foo'))
- // If refs/tags/v1 and refs/heads/tags/v1 existed on this repository
- options.listeners.errline(
- Buffer.from("error: refname 'tags/v1' is ambiguous")
- )
- return 0
- }
- return 1
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- let branches = await git.branchList(false)
- expect(branches).toHaveLength(1)
- expect(branches.sort()).toEqual(['foo'].sort())
- })
- })
- describe('Test fetchDepth and fetchTags options', () => {
- beforeEach(async () => {
- jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
- jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
- mockExec.mockImplementation((path, args, options) => {
- console.log(args, options.listeners.stdout)
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('2.18'))
- }
- return 0
- })
- })
- afterEach(() => {
- jest.restoreAllMocks()
- })
- it('should call execGit with the correct arguments when fetchDepth is 0', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2']
- const options = {
- filter: 'filterValue',
- fetchDepth: 0
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--filter=filterValue',
- 'origin',
- 'refspec1',
- 'refspec2'
- ],
- expect.any(Object)
- )
- })
- it('should call execGit with the correct arguments when fetchDepth is 0 and refSpec includes tags', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2', '+refs/tags/*:refs/tags/*']
- const options = {
- filter: 'filterValue',
- fetchDepth: 0
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--filter=filterValue',
- 'origin',
- 'refspec1',
- 'refspec2',
- '+refs/tags/*:refs/tags/*'
- ],
- expect.any(Object)
- )
- })
- it('should call execGit with the correct arguments when fetchDepth is 1', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2']
- const options = {
- filter: 'filterValue',
- fetchDepth: 1
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--filter=filterValue',
- '--depth=1',
- 'origin',
- 'refspec1',
- 'refspec2'
- ],
- expect.any(Object)
- )
- })
- it('should call execGit with the correct arguments when fetchDepth is 1 and refSpec includes tags', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2', '+refs/tags/*:refs/tags/*']
- const options = {
- filter: 'filterValue',
- fetchDepth: 1
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--filter=filterValue',
- '--depth=1',
- 'origin',
- 'refspec1',
- 'refspec2',
- '+refs/tags/*:refs/tags/*'
- ],
- expect.any(Object)
- )
- })
- it('should call execGit with the correct arguments when showProgress is true', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2']
- const options = {
- filter: 'filterValue',
- showProgress: true
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--progress',
- '--filter=filterValue',
- 'origin',
- 'refspec1',
- 'refspec2'
- ],
- expect.any(Object)
- )
- })
- it('should call execGit with the correct arguments when fetchDepth is 42 and showProgress is true', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2']
- const options = {
- filter: 'filterValue',
- fetchDepth: 42,
- showProgress: true
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--progress',
- '--filter=filterValue',
- '--depth=42',
- 'origin',
- 'refspec1',
- 'refspec2'
- ],
- expect.any(Object)
- )
- })
- it('should call execGit with the correct arguments when showProgress is true and refSpec includes tags', async () => {
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- const refSpec = ['refspec1', 'refspec2', '+refs/tags/*:refs/tags/*']
- const options = {
- filter: 'filterValue',
- showProgress: true
- }
- await git.fetch(refSpec, options)
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- [
- '-c',
- 'protocol.version=2',
- 'fetch',
- '--no-tags',
- '--prune',
- '--no-recurse-submodules',
- '--progress',
- '--filter=filterValue',
- 'origin',
- 'refspec1',
- 'refspec2',
- '+refs/tags/*:refs/tags/*'
- ],
- expect.any(Object)
- )
- })
- })
- describe('repository initialization object format', () => {
- beforeEach(async () => {
- jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
- jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
- })
- afterEach(() => {
- jest.restoreAllMocks()
- })
- it('initializes SHA-256 repositories with the matching object format', async () => {
- mockExec.mockImplementation((path, args, options) => {
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('git version 2.50.1'))
- }
- return 0
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- git = await commandManager.createCommandManager('test', false, false)
- await git.init('sha256')
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- ['init', '--object-format=sha256', 'test'],
- expect.any(Object)
- )
- })
- it('initializes SHA-1 repositories with existing default arguments', async () => {
- mockExec.mockImplementation((path, args, options) => {
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('git version 2.50.1'))
- }
- return 0
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- git = await commandManager.createCommandManager('test', false, false)
- await git.init('sha1')
- expect(mockExec).toHaveBeenCalledWith(
- expect.any(String),
- ['init', 'test'],
- expect.any(Object)
- )
- })
- })
- describe('git user-agent with orchestration ID', () => {
- beforeEach(async () => {
- jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
- jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
- })
- afterEach(() => {
- jest.restoreAllMocks()
- // Clean up environment variable to prevent test pollution
- delete process.env['ACTIONS_ORCHESTRATION_ID']
- })
- it('should include orchestration ID in user-agent when ACTIONS_ORCHESTRATION_ID is set', async () => {
- const orchId = 'test-orch-id-12345'
- process.env['ACTIONS_ORCHESTRATION_ID'] = orchId
- let capturedEnv: any = null
- mockExec.mockImplementation((path, args, options) => {
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('2.18'))
- }
- // Capture env on any command
- capturedEnv = options.env
- return 0
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- // Call a git command to trigger env capture after user-agent is set
- await git.init()
- // Verify the user agent includes the orchestration ID
- expect(git).toBeDefined()
- expect(capturedEnv).toBeDefined()
- expect(capturedEnv['GIT_HTTP_USER_AGENT']).toBe(
- `git/2.18 (github-actions-checkout) actions_orchestration_id/${orchId}`
- )
- })
- it('should sanitize invalid characters in orchestration ID', async () => {
- const orchId = 'test (with) special/chars'
- process.env['ACTIONS_ORCHESTRATION_ID'] = orchId
- let capturedEnv: any = null
- mockExec.mockImplementation((path, args, options) => {
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('2.18'))
- }
- // Capture env on any command
- capturedEnv = options.env
- return 0
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- // Call a git command to trigger env capture after user-agent is set
- await git.init()
- // Verify the user agent has sanitized orchestration ID (spaces, parentheses, slash replaced)
- expect(git).toBeDefined()
- expect(capturedEnv).toBeDefined()
- expect(capturedEnv['GIT_HTTP_USER_AGENT']).toBe(
- 'git/2.18 (github-actions-checkout) actions_orchestration_id/test__with__special_chars'
- )
- })
- it('should not modify user-agent when ACTIONS_ORCHESTRATION_ID is not set', async () => {
- delete process.env['ACTIONS_ORCHESTRATION_ID']
- let capturedEnv: any = null
- mockExec.mockImplementation((path, args, options) => {
- if (args.includes('version')) {
- options.listeners.stdout(Buffer.from('2.18'))
- }
- // Capture env on any command
- capturedEnv = options.env
- return 0
- })
- jest.spyOn(exec, 'exec').mockImplementation(mockExec)
- const workingDirectory = 'test'
- const lfs = false
- const doSparseCheckout = false
- git = await commandManager.createCommandManager(
- workingDirectory,
- lfs,
- doSparseCheckout
- )
- // Call a git command to trigger env capture after user-agent is set
- await git.init()
- // Verify the user agent does NOT contain orchestration ID
- expect(git).toBeDefined()
- expect(capturedEnv).toBeDefined()
- expect(capturedEnv['GIT_HTTP_USER_AGENT']).toBe(
- 'git/2.18 (github-actions-checkout)'
- )
- })
- })
|