Repository: codecov/uploader
Pull request #726 (2022-04-21 13:36:23)

Release 0.2.0
Please note the minor version bump here. I think this is necessary given the new features (`xcode` and `coveragepy`)

## What's Changed
### Features

* add coveragepy xml support ([8353edb](https://github.com/codecov/uploader/commit/8353edbd82e9dd2b9eea607beaa701f3ecef9300))
* add xcode support ([c5e1c70](https://github.com/codecov/uploader/commit/c5e1c70051523d6bb015cbd2e337a4f1df58ef60))


### Bug Fixes

* add more readable number ([d15ccef](https://github.com/codecov/uploader/commit/d15ccef55d84094abfc986bac7b3b53b1263acae))
* add tests for coveragepy ([de90c56](https://github.com/codecov/uploader/commit/de90c56614de8eea5d46aee25f106598cccd534d))
* automagic xml ([626b76b](https://github.com/codecov/uploader/commit/626b76b76caa03ddfc6adf9310d3a22ac04619c4))
* bump package.json ([e5aedde](https://github.com/codecov/uploader/commit/e5aeddefc7f50d2d17ef3e859d021d6d7aca7420))
* increase spawnsync buffer ([a758b90](https://github.com/codecov/uploader/commit/a758b905f41d47c4ff453312384943dbd0b1ff5e))
* refactor logging and catching ([f782e4f](https://github.com/codecov/uploader/commit/f782e4fc8ba98c499ad27748a5bfc306f56404cd))
* resolve comments ([2bea407](https://github.com/codecov/uploader/commit/2bea407585348ef97350de84bb027e4838096a68))
* update tests with buffer arg ([af8bea4](https://github.com/codecov/uploader/commit/af8bea413a2b01253b8dc8bc7825a3d873043594))
* update types for xcode ([a5c363e](https://github.com/codecov/uploader/commit/a5c363ee707290419869a3c3ade1ebabb5aa25a9))

**Full Changelog**: https://github.com/codecov/uploader/compare/v0.1.22...v0.2.0


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index adec1ba..f14bcb0 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -439,7 +439,7 @@ jobs:
             - release_tag
   release:
     docker:
-      - image: google/cloud-sdk:380.0.0-slim@sha256:1cd61926f514ce46ba533f55df3dfdffa2ee4f9794cd56d4701d4febeb6018aa
+      - image: google/cloud-sdk:381.0.0-slim@sha256:ea7b1824492df16b411489045f3d59bff365f9ac2c9c80f238e1115fd502c0e3
     steps:
       - attach_workspace:
           at: .
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index d7e9125..0f2babf 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -38,7 +38,7 @@ jobs:
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3
+      uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748 # tag=v3
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
diff --git a/.gitignore b/.gitignore
index cc09507..9fc97b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,3 +70,4 @@ codecov.exe
 .DS_Store
 .idea/*
 .dccache
+.coverage
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d9f9b3e..12819a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,27 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+### [0.2.0](https://github.com/codecov/uploader/compare/v0.1.21...v0.2.0) (2022-04-21)
+
+
+### Features
+
+* add coveragepy xml support ([8353edb](https://github.com/codecov/uploader/commit/8353edbd82e9dd2b9eea607beaa701f3ecef9300))
+* add xcode support ([c5e1c70](https://github.com/codecov/uploader/commit/c5e1c70051523d6bb015cbd2e337a4f1df58ef60))
+
+
+### Bug Fixes
+
+* add more readable number ([d15ccef](https://github.com/codecov/uploader/commit/d15ccef55d84094abfc986bac7b3b53b1263acae))
+* add tests for coveragepy ([de90c56](https://github.com/codecov/uploader/commit/de90c56614de8eea5d46aee25f106598cccd534d))
+* automagic xml ([626b76b](https://github.com/codecov/uploader/commit/626b76b76caa03ddfc6adf9310d3a22ac04619c4))
+* bump package.json ([e5aedde](https://github.com/codecov/uploader/commit/e5aeddefc7f50d2d17ef3e859d021d6d7aca7420))
+* increase spawnsync buffer ([a758b90](https://github.com/codecov/uploader/commit/a758b905f41d47c4ff453312384943dbd0b1ff5e))
+* refactor logging and catching ([f782e4f](https://github.com/codecov/uploader/commit/f782e4fc8ba98c499ad27748a5bfc306f56404cd))
+* resolve comments ([2bea407](https://github.com/codecov/uploader/commit/2bea407585348ef97350de84bb027e4838096a68))
+* update tests with buffer arg ([af8bea4](https://github.com/codecov/uploader/commit/af8bea413a2b01253b8dc8bc7825a3d873043594))
+* update types for xcode ([a5c363e](https://github.com/codecov/uploader/commit/a5c363ee707290419869a3c3ade1ebabb5aa25a9))
+
 ### [0.1.22](https://github.com/codecov/uploader/compare/v0.1.21...v0.1.22) (2022-04-12)
 
 
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 220e53b..47c61f8 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -1,12 +1,12 @@
 {
   "name": "@codecov/uploader",
-  "version": "0.1.22",
+  "version": "0.2.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "@codecov/uploader",
-      "version": "0.1.22",
+      "version": "0.2.0",
       "license": "ISC",
       "dependencies": {
         "fast-glob": "3.2.11",
diff --git a/package.json b/package.json
index 770f1bb..fdba896 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@codecov/uploader",
-  "version": "0.1.22",
+  "version": "0.2.0",
   "description": "Codecov Report Uploader",
   "private": true,
   "bin": {
diff --git a/src/ci_providers/provider_azurepipelines.ts b/src/ci_providers/provider_azurepipelines.ts
index 3f48e65..85355ab 100644
--- a/src/ci_providers/provider_azurepipelines.ts
+++ b/src/ci_providers/provider_azurepipelines.ts
@@ -66,7 +66,7 @@ function _getSHA(inputs: UploaderInputs): string {
     if (mergeCommitRegex.exec(mergeCommitMessage)) {
       const mergeCommit = mergeCommitMessage.split(' ')[1]
       info(`    Fixing merge commit SHA ${commit} -> ${mergeCommit}`)
-      commit = mergeCommit
+      commit = mergeCommit || ''
     }
   }
 
diff --git a/src/ci_providers/provider_circleci.ts b/src/ci_providers/provider_circleci.ts
index 282ba89..3aae069 100644
--- a/src/ci_providers/provider_circleci.ts
+++ b/src/ci_providers/provider_circleci.ts
@@ -43,7 +43,7 @@ function _getSlug(inputs: UploaderInputs): string {
   }
 
   if (isSetAndNotEmpty(envs.CIRCLE_REPOSITORY_URL)) {
-    return `${envs.CIRCLE_REPOSITORY_URL?.split(':')[1].split('.git')[0]}`
+    return `${envs.CIRCLE_REPOSITORY_URL?.split(':')[1]?.split('.git')[0]}`
   }
   return slug
 }
diff --git a/src/helpers/cli.ts b/src/helpers/cli.ts
index b77d589..a67c6b2 100644
--- a/src/helpers/cli.ts
+++ b/src/helpers/cli.ts
@@ -185,6 +185,19 @@ const args: ICLIArgument[] = [
     type: 'string',
     description: 'Extra arguments to pass to gcov',
   },
+  {
+    alias: 'xc',
+    name: 'xcode',
+    type: 'boolean',
+    default: false,
+    description: 'Run with xcode support',
+  },
+  {
+    alias: 'xp',
+    name: 'xcodeArchivePath',
+    type: 'string',
+    description: 'Specify the xcode archive path. Likely specified as the -resultBundlePath and should end in .xcresult',
+  },
 ]
 
 export interface IYargsObject {
diff --git a/src/helpers/coveragepy.ts b/src/helpers/coveragepy.ts
new file mode 100644
index 0000000..fd507e4
--- /dev/null
+++ b/src/helpers/coveragepy.ts
@@ -0,0 +1,11 @@
+import { isProgramInstalled, runExternalProgram } from "./util"
+import { info } from './logger'
+
+export async function generateCoveragePyFile(): Promise<string> {
+    if (!isProgramInstalled('coverage')) {
+        throw new Error('coveragepy is not installed')
+    }
+
+    info('Running coverage xml...')
+    return runExternalProgram('coverage', ['xml']);
+}
diff --git a/src/helpers/files.ts b/src/helpers/files.ts
index 4395670..b2ac57e 100644
--- a/src/helpers/files.ts
+++ b/src/helpers/files.ts
@@ -217,7 +217,7 @@ export function fetchGitRoot(): string {
     return (
       runExternalProgram('git', ['rev-parse', '--show-toplevel'])) || process.cwd()
   } catch (error) {
-    throw new Error('Error fetching git root. Please try using the -R flag.')
+    throw new Error(`Error fetching git root. Please try using the -R flag. ${error}`)
   }
 }
 
@@ -259,7 +259,7 @@ export function getAllFiles(
   if (args.networkPrefix) {
     files = files.map(file => String(args.networkPrefix) + file)
   }
-  
+
   return files
 }
 
@@ -348,7 +348,7 @@ export function cleanCoverageFilePaths(projectRoot: string, paths: string[]): st
 
   if (coverageFilePaths.length === 0) {
     logError(`None of the following appear to exist as files: ${paths.toString()}`)
-    throw new Error('Error while cleaning paths. No paths matched existing files!')  
+    throw new Error('Error while cleaning paths. No paths matched existing files!')
   }
 
   return coverageFilePaths
diff --git a/src/helpers/git.ts b/src/helpers/git.ts
index 9c58164..8ee9db4 100644
--- a/src/helpers/git.ts
+++ b/src/helpers/git.ts
@@ -9,14 +9,14 @@ export function parseSlug(slug: string): string {
 
   if (slug.match('http')) {
     // Type is http(s)
-    const phaseOne = slug.split('//')[1].replace('.git', '')
-    const phaseTwo = phaseOne.split('/')
+    const phaseOne = slug.split('//')[1]?.replace('.git', '') || ''
+    const phaseTwo = phaseOne?.split('/') || ''
     const cleanSlug = `${phaseTwo[1]}/${phaseTwo[2]}`
     return cleanSlug
   } else if (slug.match('@')) {
     // Type is git
-    const cleanSlug = slug.split(':')[1].replace('.git', '')
-    return cleanSlug
+    const cleanSlug = slug.split(':')[1]?.replace('.git', '')
+    return cleanSlug || ''
   }
   throw new Error(`Unable to parse slug URL: ${slug}`)
 }
diff --git a/src/helpers/token.ts b/src/helpers/token.ts
index 8fd31bf..f20f508 100644
--- a/src/helpers/token.ts
+++ b/src/helpers/token.ts
@@ -1,7 +1,7 @@
 import fs from 'fs'
 import yaml from 'js-yaml'
 import path from 'path'
-import { UploaderArgs, UploaderInputs } from '../types'
+import { UploaderInputs } from '../types'
 import { DEFAULT_UPLOAD_HOST } from './constansts'
 import { info, logError, UploadLogger } from './logger'
 import { validateToken } from './validate'
@@ -17,7 +17,7 @@ export function getToken(inputs: UploaderInputs, projectRoot: string): string {
   const options = [
     [args.token, 'arguments'],
     [envs.CODECOV_TOKEN, 'environment variables'],
-    [getTokenFromYaml(projectRoot, args), 'Codecov yaml config'],
+    [getTokenFromYaml(projectRoot), 'Codecov yaml config'],
   ]
 
   for (const [token, source] of options) {
@@ -65,7 +65,6 @@ function yamlParse(input: object | string | number): ICodecovYAML {
 
 export function getTokenFromYaml(
   projectRoot: string,
-  args: UploaderArgs,
 ): string {
   const dirNames = ['', '.github', 'dev']
 
diff --git a/src/helpers/util.ts b/src/helpers/util.ts
index 0e9919b..d5d8cdf 100644
--- a/src/helpers/util.ts
+++ b/src/helpers/util.ts
@@ -1,5 +1,7 @@
 import childprocess from 'child_process'
 
+export const SPAWNPROCESSBUFFERSIZE = 1_048_576 * 10 // 10 MiB
+
 export function isProgramInstalled(programName: string): boolean {
   return !childprocess.spawnSync(programName).error
 }
@@ -8,7 +10,11 @@ export function runExternalProgram(
   programName: string,
   optionalArguments: string[] = [],
 ): string {
-  const result = childprocess.spawnSync(programName, optionalArguments)
+  const result = childprocess.spawnSync(
+    programName,
+    optionalArguments,
+    { maxBuffer: SPAWNPROCESSBUFFERSIZE },
+  )
   if (result.error) {
     throw new Error(`Error running external program: ${result.error}`)
   }
diff --git a/src/helpers/web.ts b/src/helpers/web.ts
index 4481bbb..2727832 100644
--- a/src/helpers/web.ts
+++ b/src/helpers/web.ts
@@ -53,7 +53,7 @@ export function getPackage(source: string): string {
 
 
 export async function uploadToCodecovPUT(
-  putAndResultUrlPair: PostResults, 
+  putAndResultUrlPair: PostResults,
   uploadFile: string | Buffer,
   args: UploaderArgs
 ): Promise<PutResults> {
@@ -133,6 +133,11 @@ export function parsePOSTResults(putAndResultUrlPair: string): PostResults {
     )
   }
 
+  if (matches[0] === undefined || matches[1] === undefined) {
+    throw new Error(
+      `Invalid URLs received when parsing results from POST: ${matches[0]},${matches[1]}`
+    )
+  }
   const resultURL = new URL(matches[0].trimEnd())
   const putURL = new URL(matches[1])
    // This match may have trailing 0x0A and 0x0D that must be trimmed
@@ -215,5 +220,5 @@ export function generateRequestHeadersPUT(
       }
 
     }
-  
+
 }
diff --git a/src/helpers/xcode.ts b/src/helpers/xcode.ts
new file mode 100644
index 0000000..5188ce4
--- /dev/null
+++ b/src/helpers/xcode.ts
@@ -0,0 +1,63 @@
+import fs from 'fs/promises'
+
+import { info, UploadLogger } from '../helpers/logger'
+import {
+  XcodeCoverageFileReport,
+  XcodeCoverageReport,
+} from '../types'
+import { isProgramInstalled, runExternalProgram } from "./util"
+
+export async function generateXcodeCoverageFiles(archivePath: string): Promise<string> {
+  if (!isProgramInstalled('xcrun')) {
+      throw new Error('xcrun is not installed, cannot process files')
+  }
+  info('Running xcode coversion...')
+
+  const coverage: XcodeCoverageReport = {}
+  const report = { coverage: coverage }
+
+  getFileList(archivePath).forEach(repoFilePath => {
+    UploadLogger.verbose(`Converting ${repoFilePath}...`)
+    const coverageInfo = getCoverageInfo(archivePath, repoFilePath)
+    const coverageJson = convertCoverage(coverageInfo)
+    report.coverage[repoFilePath] = coverageJson
+  })
+
+  let pathFilename = archivePath.split('/').pop()
+  if (pathFilename) {
+    pathFilename = pathFilename.split('.xcresult')[0]
+  }
+  const filename = `./coverage-report-${pathFilename}.json`
+  UploadLogger.verbose(`Writing coverage to ${filename}`)
+  await fs.writeFile(filename, JSON.stringify(report))
+  return filename
+}
+
+function getFileList(archivePath: string): string[] {
+  const fileList = runExternalProgram('xcrun', ['xccov', 'view', '--file-list', '--archive', archivePath]);
+  return fileList.split('\n').filter(i => i !== '')
+}
+
+function getCoverageInfo(archivePath: string, filePath: string): string {
+  return runExternalProgram('xcrun', ['xccov', 'view', '--archive', archivePath, '--file', filePath])
+}
+
+function convertCoverage(coverageInfo: string): XcodeCoverageFileReport {
+  const coverageInfoArr = coverageInfo.split('\n')
+  const obj: XcodeCoverageFileReport = {}
+  coverageInfoArr.forEach(line => {
+    const [lineNum, lineInfo] = line.split(':')
+    if (lineNum && Number.isInteger(Number(lineNum))) {
+      const lineHits = lineInfo?.trimStart().split(' ')[0]?.trim()
+      if (typeof lineHits !== 'string') {
+        return
+      }
+      if (lineHits === '*') {
+        obj[String(lineNum.trim())] = null
+      } else {
+        obj[String(lineNum.trim())] = lineHits
+      }
+    }
+  })
+  return obj
+}
diff --git a/src/index.ts b/src/index.ts
index 050dbab..53517d5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -22,7 +22,9 @@ import {
   readCoverageFile,
   removeFile,
 } from './helpers/files'
+import { generateCoveragePyFile } from './helpers/coveragepy'
 import { generateGcovCoverageFiles } from './helpers/gcov'
+import { generateXcodeCoverageFiles } from './helpers/xcode'
 import { argAsArray } from './helpers/util'
 
 /**
@@ -154,7 +156,7 @@ export async function main(
   // #region == Step 5: select coverage files (search or specify)
 
   let requestedPaths: string[] = []
-  
+
   // Look for files
 
   if (args.gcov) {
@@ -165,7 +167,23 @@ export async function main(
     const gcovLogs = await generateGcovCoverageFiles(projectRoot, gcovInclude, gcovIgnore, gcovArgs)
     UploadLogger.verbose(`${gcovLogs}`)
   }
-  
+
+  if (args.xcode) {
+    if (!args.xcodeArchivePath) {
+      throw new Error('Please specify xcodeArchivePath to run the Codecov uploader with xcode support')
+    } else {
+      const xcodeArchivePath: string = args.xcodeArchivePath
+      const xcodeLogs = await generateXcodeCoverageFiles(xcodeArchivePath)
+      UploadLogger.verbose(`${xcodeLogs}`)
+    }
+  }
+
+  try {
+    await generateCoveragePyFile()
+  } catch (error) {
+    UploadLogger.verbose(`Skipping coveragepy conversion: ${error}`)
+  }
+
   let coverageFilePaths: string[] = []
   requestedPaths = argAsArray(args.file)
 
@@ -191,9 +209,9 @@ export async function main(
 
     let coverageFilePathsAfterFilter = coverageFilePaths
 
-    if (coverageFilePaths.length > 0) { 
+    if (coverageFilePaths.length > 0) {
       coverageFilePathsAfterFilter = filterFilesAgainstBlockList(coverageFilePaths, getBlocklist())
-    } 
+    }
 
 
 
@@ -301,7 +319,7 @@ export async function main(
   if (buildParams.slug !== '' && !buildParams.slug?.match(/\//)) {
     logError(`Slug must follow the format of "<owner>/<repo>" or be blank. We detected "${buildParams.slug}"`)
   }
-  
+
   const query = webHelpers.generateQuery(buildParams)
 
   if (args.dryRun) {
diff --git a/src/types.ts b/src/types.ts
index 90799e5..9dad4f9 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,35 +1,37 @@
 import { Agent } from "https";
 
 export interface UploaderArgs {
-  build?: string // Specify the build number manually
   branch?: string // Specify the branch manually
+  build?: string // Specify the build number manually
+  changelog?: string // Displays the changelog and exits
+  clean?: string // Move discovered coverage reports to the trash
   dir?: string // Directory to search for coverage reports.
+  dryRun?: string // Don't upload files to Codecov
   env?: string // Specify environment variables to be included with this build
-  sha?: string // Specify the commit SHA mannually
+  feature?: string // Toggle features
   file?: string | string[] // Target file(s) to upload
   flags: string | string[] // Flag the upload to group coverage metrics
+  gcov?: string // Run with gcov support
+  gcovArgs?:  string | string[] // Extra arguments to pass to gcov
+  gcovIgnore?:  string | string[] // Paths to ignore during gcov gathering
+  gcovInclude?:  string | string[] // Paths to include during gcov gathering
   name?: string // Custom defined name of the upload. Visible in Codecov UI
   networkFilter?: string // Specify a prefix on the files listed in the network section of the Codecov report. Useful for upload-specific path fixing
   networkPrefix?: string // Specify a prefix on files listed in the network section of the Codecov report. Useful to help resolve path fixing
+  nonZero?: string // Should errors exit with a non-zero (default: false)
   parent?: string // The commit SHA of the parent for which you are uploading coverage.
   pr?: string // Specify the pull request number mannually
-  token?: string // Codecov upload token
-  tag?: string // Specify the git tag
-  verbose?: string // Run with verbose logging
   rootDir?: string // Specify the project root directory when not in a git repo
-  nonZero?: string // Should errors exit with a non-zero (default: false)
-  dryRun?: string // Don't upload files to Codecov
+  sha?: string // Specify the commit SHA mannually
   slug: string // Specify the slug manually
-  url?: string // Change the upload host (Enterprise use)
-  clean?: string // Move discovered coverage reports to the trash
-  feature?: string // Toggle features
-  upstream: string // Upstream proxy to connect to
   source?: string // Track wrappers of the uploader
-  changelog?: string // Displays the changelog and exits
-  gcov?: string // Run with gcov support
-  gcovIgnore?:  string | string[] // Paths to ignore during gcov gathering
-  gcovInclude?:  string | string[] // Paths to include during gcov gathering
-  gcovArgs?:  string | string[] // Extra arguments to pass to gcov
+  tag?: string // Specify the git tag
+  token?: string // Codecov upload token
+  upstream: string // Upstream proxy to connect to
+  url?: string // Change the upload host (Enterprise use)
+  verbose?: string // Run with verbose logging
+  xcode?: string // Run with xcode support
+  xcodeArchivePath?: string // Specify the xcode archive path. Likely specified as the -resultBundlePath and should end in .xcresult
 }
 
 export type UploaderEnvs = NodeJS.Dict<string>
@@ -70,7 +72,7 @@ export interface IRequestHeaders {
     agent?: Agent
     body?: string | Buffer,
     headers: Record<string, string>
-  } 
+  }
 }
 
 export interface PostResults {
@@ -81,4 +83,7 @@ export interface PostResults {
 export interface PutResults {
   status: string
   resultURL: URL
-}
\ No newline at end of file
+}
+
+export type XcodeCoverageFileReport = Record<string, string | null>
+export type XcodeCoverageReport = Record<string, XcodeCoverageFileReport>
diff --git a/tsconfig.json b/tsconfig.json
index 9e53fb3..cf45c4e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,7 +11,8 @@
     "moduleResolution": "node",
     "esModuleInterop": true,
     "resolveJsonModule": true,
-    "skipLibCheck": true
+    "skipLibCheck": true,
+    "noUncheckedIndexedAccess": true
   },
   "exclude": ["dist/*", "test/*"]
 }


Test patch:
diff --git a/test/fixtures/xcode/UI/View1.swift b/test/fixtures/xcode/UI/View1.swift
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/xcode/UI/View2.swift b/test/fixtures/xcode/UI/View2.swift
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/xcode/test.xcresult/Info.plist b/test/fixtures/xcode/test.xcresult/Info.plist
new file mode 100644
index 0000000..e69de29
diff --git a/test/helpers/coveragepy.test.ts b/test/helpers/coveragepy.test.ts
new file mode 100644
index 0000000..884d0e6
--- /dev/null
+++ b/test/helpers/coveragepy.test.ts
@@ -0,0 +1,31 @@
+import td from 'testdouble'
+import childProcess from 'child_process'
+import { generateCoveragePyFile } from '../../src/helpers/coveragepy'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
+
+describe('generateCoveragePyFile()', () => {
+    afterEach(() => {
+        td.reset()
+    })
+
+    it('should run when coveragepy is asked for', async () => {
+        const spawnSync = td.replace(childProcess, 'spawnSync')
+        td.when(spawnSync('coverage')).thenReturn({
+            stdout: 'coverage installed',
+            error: null
+        })
+        td.when(spawnSync('coverage', td.matchers.contains('xml'), { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
+            stdout: 'xml',
+            error: null
+        })
+
+        expect(await generateCoveragePyFile()).toBe('xml')
+    })
+
+    it('should return a log when coveragepy is not installed', async () => {
+        const spawnSync = td.replace(childProcess, 'spawnSync')
+        td.when(spawnSync('coverage')).thenReturn({ error: "command not found: coverage" })
+
+        await expect(generateCoveragePyFile()).rejects.toThrowError(/coveragepy is not installed/)
+    })
+})
diff --git a/test/helpers/files.test.ts b/test/helpers/files.test.ts
index 3e9ddd0..e59c88d 100644
--- a/test/helpers/files.test.ts
+++ b/test/helpers/files.test.ts
@@ -3,6 +3,7 @@ import fs from 'fs'
 import childProcess from 'child_process'
 import * as fileHelpers from '../../src/helpers/files'
 import { getBlocklist } from '../../src/helpers/files'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import mock from 'mock-fs'
 
 describe('File Helpers', () => {
@@ -28,7 +29,7 @@ describe('File Helpers', () => {
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(cwd()).thenReturn({ stdout: 'fish' })
     td.when(
-      spawnSync('git', ['rev-parse', '--show-toplevel']),
+      spawnSync('git', ['rev-parse', '--show-toplevel'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'gitRoot' })
 
     expect(fileHelpers.fetchGitRoot()).toBe('gitRoot')
diff --git a/test/helpers/gcov.test.ts b/test/helpers/gcov.test.ts
index 23ce823..6d3d568 100644
--- a/test/helpers/gcov.test.ts
+++ b/test/helpers/gcov.test.ts
@@ -2,6 +2,7 @@
 import td from 'testdouble'
 import childProcess from 'child_process'
 import { generateGcovCoverageFiles } from '../../src/helpers/gcov'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 
 describe('generateGcovCoverageFiles()', () => {
     afterEach(() => {
@@ -15,7 +16,7 @@ describe('generateGcovCoverageFiles()', () => {
             stdout: 'gcov installed',
             error: null
         })
-        td.when(spawnSync('gcov', td.matchers.contains('test/fixtures/gcov/main.gcno'))).thenReturn({
+        td.when(spawnSync('gcov', td.matchers.contains('test/fixtures/gcov/main.gcno'), { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
             stdout: output,
             error: null
         })
@@ -29,7 +30,7 @@ describe('generateGcovCoverageFiles()', () => {
             stdout: 'gcov installed',
             error: null
         })
-        td.when(spawnSync('gcov', td.matchers.contains('NEWGCOVARG'))).thenReturn({
+        td.when(spawnSync('gcov', td.matchers.contains('NEWGCOVARG'), { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
             stdout: 'Matched',
         })
 
diff --git a/test/helpers/token.test.ts b/test/helpers/token.test.ts
index 7342cfd..086d1dd 100644
--- a/test/helpers/token.test.ts
+++ b/test/helpers/token.test.ts
@@ -22,36 +22,18 @@ describe('Get tokens', () => {
 
   describe('From yaml', () => {
     it('Returns empty with no yaml file', () => {
-      const args: UploaderArgs = {
-        ...createEmptyArgs(),
-        ...{
-          verbose: 'true',
-        },
-      }
-      expect(tokenHelpers.getTokenFromYaml('.', args)).toBe('')
+      expect(tokenHelpers.getTokenFromYaml('.')).toBe('')
     })
 
     it('Returns the correct token from file', () => {
-      const args: UploaderArgs = {
-        ...createEmptyArgs(),
-        ...{
-          verbose: 'true',
-        },
-      }
-      expect(tokenHelpers.getTokenFromYaml(fixturesDir, args)).toBe('faketoken')
+      expect(tokenHelpers.getTokenFromYaml(fixturesDir)).toBe('faketoken')
     })
 
     it('Returns deprecation error from codecov_token', () => {
-      const args: UploaderArgs = {
-        ...createEmptyArgs(),
-        ...{
-          verbose: 'true',
-        },
-      }
       jest.spyOn(console, 'error').mockImplementation(() => {
         // Intentionally empty
       })
-      expect(tokenHelpers.getTokenFromYaml(invalidFixturesDir, args)).toBe('')
+      expect(tokenHelpers.getTokenFromYaml(invalidFixturesDir)).toBe('')
 
       expect(console.error).toHaveBeenCalledWith(
         expect.stringContaining("'codecov_token' is a deprecated field"),
diff --git a/test/helpers/util.test.ts b/test/helpers/util.test.ts
index b1ac811..60b1b52 100644
--- a/test/helpers/util.test.ts
+++ b/test/helpers/util.test.ts
@@ -1,6 +1,10 @@
 import childProcess from 'child_process'
 import td from 'testdouble'
-import { isProgramInstalled , runExternalProgram} from '../../src/helpers/util'
+import {
+    isProgramInstalled,
+    runExternalProgram,
+    SPAWNPROCESSBUFFERSIZE,
+} from '../../src/helpers/util'
 
 describe('isProgramInstalled()', () => {
     afterEach(() => {
@@ -24,7 +28,7 @@ describe('runExternalProgram()', () => {
 
     it('should throw an error when program is not found', () => {
         const spawnSync = td.replace(childProcess, 'spawnSync')
-        td.when(spawnSync('ls', ['-geewhiz'])).thenReturn({
+        td.when(spawnSync('ls', ['-geewhiz'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
           error: 'Huh?',
         })
         expect(() => runExternalProgram('ls', ['-geewhiz'])).toThrowError(/Huh\?/)
@@ -33,7 +37,7 @@ describe('runExternalProgram()', () => {
 
     it('should return stdout on success', () => {
         const spawnSync = td.replace(childProcess, 'spawnSync')
-        td.when(spawnSync('ls', ['-geewhiz'])).thenReturn({
+        td.when(spawnSync('ls', ['-geewhiz'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
           stdout: 'I am output',
         })
         expect(runExternalProgram('ls', ['-geewhiz'])).toEqual("I am output")
@@ -42,16 +46,16 @@ describe('runExternalProgram()', () => {
 
     it('should return a trimmed string with no newlines', () => {
         const spawnSync = td.replace(childProcess, 'spawnSync')
-        td.when(spawnSync('ls', ['-geewhiz'])).thenReturn({
+        td.when(spawnSync('ls', ['-geewhiz'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
           stdout: `
-          
-          
+
+
           I am output
-          
-          
+
+
           `,
         })
         expect(runExternalProgram('ls', ['-geewhiz'])).toEqual("I am output")
 
     })
-})
\ No newline at end of file
+})
diff --git a/test/helpers/xcode.test.ts b/test/helpers/xcode.test.ts
new file mode 100644
index 0000000..9c6b2ef
--- /dev/null
+++ b/test/helpers/xcode.test.ts
@@ -0,0 +1,35 @@
+import td from 'testdouble'
+import childProcess from 'child_process'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
+import { generateXcodeCoverageFiles } from '../../src/helpers/xcode'
+
+describe('generateXcodeCoverageFiles()', () => {
+    afterEach(() => {
+        td.reset()
+    })
+
+    it('should find all files in fixtures', async () => {
+        const spawnSync = td.replace(childProcess, 'spawnSync')
+        td.when(spawnSync('xcrun')).thenReturn({
+            stdout: 'xcrun installed',
+            error: null
+        })
+        td.when(spawnSync('xcrun', td.matchers.contains('--file-list'), { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
+            stdout: '../fixtures/xcode/UI/View1.swift',
+            error: null
+        })
+        td.when(spawnSync('xcrun', td.matchers.contains('--file'), { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
+            stdout: '  1: *\n  2: 0',
+            error: null
+        })
+
+        expect(await generateXcodeCoverageFiles('../fixtures/xcode/test.xcresult')).toBe('./coverage-report-test.json')
+    })
+
+    it('should return an error when xcode is not installed', async () => {
+        const spawnSync = td.replace(childProcess, 'spawnSync')
+        td.when(spawnSync('xcrun')).thenReturn({ error: "Command 'xcrun' not found" })
+
+        await expect(generateXcodeCoverageFiles('')).rejects.toThrowError(/xcrun is not installed/)
+    })
+})
diff --git a/test/index.test.ts b/test/index.test.ts
index 7c280cd..0cfe689 100644
--- a/test/index.test.ts
+++ b/test/index.test.ts
@@ -2,10 +2,12 @@ import Module from 'module'
 
 import * as app from '../src'
 
-import { version } from '../package.json'
-import nock from 'nock'
+import childProcess from 'child_process'
 import fs from 'fs'
+import nock from 'nock'
+import td from 'testdouble'
 import { UploadLogger } from '../src/helpers/logger'
+import { version } from '../package.json'
 
 // Backup the env
 const realEnv = { ...process.env }
@@ -30,6 +32,7 @@ describe('Uploader Core', () => {
   afterEach(() => {
     process.env = env
     jest.restoreAllMocks()
+    td.reset()
   })
 
   it('Can return version', () => {
diff --git a/test/providers/provider_azurepipelines.test.ts b/test/providers/provider_azurepipelines.test.ts
index 7f06111..a5ef95a 100644
--- a/test/providers/provider_azurepipelines.test.ts
+++ b/test/providers/provider_azurepipelines.test.ts
@@ -2,6 +2,7 @@ import td from 'testdouble'
 import childProcess from 'child_process'
 
 import * as providerAzurepipelines from '../../src/ci_providers//provider_azurepipelines'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -53,7 +54,7 @@ describe('Azure Pipelines CI Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
 
     const params = providerAzurepipelines.getServiceParams(inputs)
@@ -162,7 +163,7 @@ describe('Azure Pipelines CI Params', () => {
 
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
     const params = providerAzurepipelines.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
diff --git a/test/providers/provider_bitbucket.test.ts b/test/providers/provider_bitbucket.test.ts
index d9021a6..8da9f8c 100644
--- a/test/providers/provider_bitbucket.test.ts
+++ b/test/providers/provider_bitbucket.test.ts
@@ -1,6 +1,7 @@
 import childProcess from 'child_process'
 import td from 'testdouble'
 import * as providerBitbucket from '../../src/ci_providers//provider_bitbucket'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -132,7 +133,7 @@ describe('Bitbucket Params', () => {
     }
 
     const execFileSync = td.replace(childProcess, 'spawnSync')
-    td.when(execFileSync('git', ['rev-parse', 'testingsha12'])).thenReturn(
+    td.when(execFileSync('git', ['rev-parse', 'testingsha12'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn(
       { stdout: 'newtestsha'},
     )
     const params = providerBitbucket.getServiceParams(inputs)
diff --git a/test/providers/provider_bitrise.test.ts b/test/providers/provider_bitrise.test.ts
index 397640c..b4a6093 100644
--- a/test/providers/provider_bitrise.test.ts
+++ b/test/providers/provider_bitrise.test.ts
@@ -1,5 +1,6 @@
 import td from 'testdouble'
 import childProcess from 'child_process'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -65,7 +66,7 @@ describe('Bitrise Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
 
     const params = providerBitrise.getServiceParams(inputs)
@@ -97,7 +98,7 @@ describe('Bitrise Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
     const params = providerBitrise.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -128,7 +129,7 @@ describe('Bitrise Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
     const params = providerBitrise.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -169,7 +170,7 @@ describe('Bitrise Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
     const params = providerBitrise.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
diff --git a/test/providers/provider_githubactions.test.ts b/test/providers/provider_githubactions.test.ts
index 4072f5c..9f67786 100644
--- a/test/providers/provider_githubactions.test.ts
+++ b/test/providers/provider_githubactions.test.ts
@@ -2,6 +2,7 @@ import td from 'testdouble'
 import childProcess from 'child_process'
 
 import * as providerGitHubactions from '../../src/ci_providers//provider_githubactions'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -92,7 +93,7 @@ describe('GitHub Actions Params', () => {
 
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['show', '--no-patch', '--format=%P']),
+      spawnSync('git', ['show', '--no-patch', '--format=%P'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({
       stdout: 'testingsha',
     })
@@ -127,7 +128,7 @@ describe('GitHub Actions Params', () => {
 
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['show', '--no-patch', '--format=%P']),
+      spawnSync('git', ['show', '--no-patch', '--format=%P'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({
       stdout:
         'testingsha123456789012345678901234567890 testingmergecommitsha2345678901234567890',
@@ -166,7 +167,7 @@ describe('GitHub Actions Params', () => {
 
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['show', '--no-patch', '--format=%P']),
+      spawnSync('git', ['show', '--no-patch', '--format=%P'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'testsha' })
     const params = providerGitHubactions.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -199,7 +200,7 @@ describe('GitHub Actions Params', () => {
 
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['show', '--no-patch', '--format=%P']),
+      spawnSync('git', ['show', '--no-patch', '--format=%P'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
     const params = providerGitHubactions.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
diff --git a/test/providers/provider_gitlabci.test.ts b/test/providers/provider_gitlabci.test.ts
index 7bf846c..489668e 100644
--- a/test/providers/provider_gitlabci.test.ts
+++ b/test/providers/provider_gitlabci.test.ts
@@ -2,6 +2,7 @@ import td from 'testdouble'
 import childProcess from 'child_process'
 
 import * as providerGitLabci from '../../src/ci_providers//provider_gitlabci'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -51,7 +52,7 @@ describe('GitLabCI Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
     const params = providerGitLabci.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -135,7 +136,7 @@ describe('GitLabCI Params', () => {
       inputs.environment.CI_BUILD_REPO = ''
       const spawnSync = td.replace(childProcess, 'spawnSync')
       td.when(
-        spawnSync('git', ['config', '--get', 'remote.origin.url']),
+        spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({ stdout: 'https://gitlab.com/testOrg/testRepo.git' })
 
       const params = providerGitLabci.getServiceParams(inputs)
@@ -146,7 +147,7 @@ describe('GitLabCI Params', () => {
       inputs.environment.CI_BUILD_REPO = ''
       const spawnSync = td.replace(childProcess, 'spawnSync')
       td.when(
-        spawnSync('git', ['config', '--get', 'remote.origin.url']),
+        spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({ stdout: 'git@gitlab.com:/' })
 
       const params = providerGitLabci.getServiceParams(inputs)
@@ -157,7 +158,7 @@ describe('GitLabCI Params', () => {
       inputs.environment.CI_BUILD_REPO = ''
       const spawnSync = td.replace(childProcess, 'spawnSync')
       td.when(
-        spawnSync('git', ['config', '--get', 'remote.origin.url']),
+        spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({ stdout: '' })
 
       const params = providerGitLabci.getServiceParams(inputs)
diff --git a/test/providers/provider_herokuci.test.ts b/test/providers/provider_herokuci.test.ts
index ffa4a61..f0c8f0b 100644
--- a/test/providers/provider_herokuci.test.ts
+++ b/test/providers/provider_herokuci.test.ts
@@ -1,5 +1,6 @@
 import td from 'testdouble'
 import childProcess from 'child_process'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -51,7 +52,7 @@ describe('HerokuCI Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
     const params = providerHerokuci.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -80,7 +81,7 @@ describe('HerokuCI Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
     const params = providerHerokuci.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
diff --git a/test/providers/provider_jenkinsci.test.ts b/test/providers/provider_jenkinsci.test.ts
index 4e465a8..2afd0db 100644
--- a/test/providers/provider_jenkinsci.test.ts
+++ b/test/providers/provider_jenkinsci.test.ts
@@ -2,6 +2,7 @@ import td from 'testdouble'
 import childProcess from 'child_process'
 
 import * as providerJenkinsci from '../../src/ci_providers//provider_jenkinsci'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -60,7 +61,7 @@ describe('Jenkins CI Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
     const params = providerJenkinsci.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -80,7 +81,7 @@ describe('Jenkins CI Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
 
     const params = providerJenkinsci.getServiceParams(inputs)
diff --git a/test/providers/provider_local.test.ts b/test/providers/provider_local.test.ts
index 0fd8a01..d8d9963 100644
--- a/test/providers/provider_local.test.ts
+++ b/test/providers/provider_local.test.ts
@@ -2,6 +2,7 @@ import td from 'testdouble'
 import childProcess from 'child_process'
 
 import * as providerLocal from '../../src/ci_providers//provider_local'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -91,7 +92,7 @@ describe('Local Params', () => {
       providerLocal.getServiceParams(inputs)
     }).toThrow()
 
-    td.when(spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'])).thenReturn(
+    td.when(spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn(
       {
         stdout: 'main',
       },
@@ -100,7 +101,7 @@ describe('Local Params', () => {
       providerLocal.getServiceParams(inputs)
     }).toThrow()
 
-    td.when(spawnSync('git', ['rev-parse', 'HEAD'])).thenReturn({
+    td.when(spawnSync('git', ['rev-parse', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
       stdout: 'testSHA',
     })
     expect(() => {
@@ -117,16 +118,16 @@ describe('Local Params', () => {
     it('can get the slug from a git url', () => {
       const spawnSync = td.replace(childProcess, 'spawnSync')
       td.when(
-        spawnSync('git', ['config', '--get', 'remote.origin.url']),
+        spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({
         stdout: 'git@github.com:testOrg/testRepo.git',
       })
       td.when(
-        spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
+        spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({
         stdout: 'main',
       })
-      td.when(spawnSync('git', ['rev-parse', 'HEAD'])).thenReturn({
+      td.when(spawnSync('git', ['rev-parse', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
         stdout: 'testSHA',
       })
       expect(providerLocal.getServiceParams(inputs).slug).toBe(
@@ -137,16 +138,16 @@ describe('Local Params', () => {
     it('can get the slug from an http(s) url', () => {
       const spawnSync = td.replace(childProcess, 'spawnSync')
       td.when(
-        spawnSync('git', ['config', '--get', 'remote.origin.url']),
+        spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({
         stdout: 'notaurl',
       })
       td.when(
-        spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
+        spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({
         stdout: 'main',
       })
-      td.when(spawnSync('git', ['rev-parse', 'HEAD'])).thenReturn({
+      td.when(spawnSync('git', ['rev-parse', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
         stdout: 'testSHA',
       })
       expect(() => {
@@ -157,16 +158,16 @@ describe('Local Params', () => {
     it('errors on a malformed slug', () => {
       const spawnSync = td.replace(childProcess, 'spawnSync')
       td.when(
-        spawnSync('git', ['config', '--get', 'remote.origin.url']),
+        spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({
         stdout: 'http://github.com/testOrg/testRepo.git',
       })
       td.when(
-        spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
+        spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
       ).thenReturn({
         stdout: 'main',
       })
-      td.when(spawnSync('git', ['rev-parse', 'HEAD'])).thenReturn({
+      td.when(spawnSync('git', ['rev-parse', 'HEAD'], { maxBuffer: SPAWNPROCESSBUFFERSIZE })).thenReturn({
         stdout: 'testSHA',
       })
       expect(providerLocal.getServiceParams(inputs).slug).toBe(
diff --git a/test/providers/provider_teamcity.test.ts b/test/providers/provider_teamcity.test.ts
index 97ac3b0..297b336 100644
--- a/test/providers/provider_teamcity.test.ts
+++ b/test/providers/provider_teamcity.test.ts
@@ -2,6 +2,7 @@ import td from 'testdouble'
 import childProcess from 'child_process'
 
 import * as providerTeamCity from '../../src/ci_providers/provider_teamcity'
+import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 import { IServiceParams, UploaderInputs } from '../../src/types'
 import { createEmptyArgs } from '../test_helpers'
 
@@ -56,7 +57,7 @@ describe('TeamCity Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
     const params = providerTeamCity.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -85,7 +86,7 @@ describe('TeamCity Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
     const params = providerTeamCity.getServiceParams(inputs)
     expect(params).toMatchObject(expected)
@@ -113,7 +114,7 @@ describe('TeamCity Params', () => {
     }
     const spawnSync = td.replace(childProcess, 'spawnSync')
     td.when(
-      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+      spawnSync('git', ['config', '--get', 'remote.origin.url'], { maxBuffer: SPAWNPROCESSBUFFERSIZE }),
     ).thenReturn({ stdout: '' })
     const expected: IServiceParams = {
       branch: 'branch',