Repository: codecov/uploader
Pull request #480 (2021-11-01 13:39:56)

Release 0.1.9


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5d80523..1b8e733 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -443,7 +443,7 @@ jobs:
             - release_tag
   release:
     docker:
-      - image: google/cloud-sdk:361.0.0-slim
+      - image: google/cloud-sdk:362.0.0-slim
     steps:
       - attach_workspace:
           # Must be absolute path or relative path from working_directory
@@ -462,6 +462,9 @@ jobs:
     machine: true
     steps:
       - checkout
+      - attach_workspace:
+          # Must be absolute path or relative path from working_directory
+          at: .
       - run:
           name: Clone Autotest and Start Acceptance Testing Containers
           command: |
@@ -484,6 +487,8 @@ workflows:
           context:
             - 'DockerHub Push Context'
             - 'Github Checkout'
+          requires:
+            - build-alpine
       - build-linux-and-osx
       - build-alpine:
           requires:
diff --git a/.github/settings.yml b/.github/settings.yml
index 52e7a81..f3a55b5 100644
--- a/.github/settings.yml
+++ b/.github/settings.yml
@@ -5,7 +5,3 @@ repository:
   
   # The name of the repository
   name: uploader
-
-collaborators:
-- username: drazisil
-- username: notanewuser
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76562d2..a17f3f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,20 @@
 
 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.1.9](https://github.com/codecov/uploader/compare/v0.1.8...v0.1.9) (2021-11-01)
+
+### Features
+
+- add herokuci provider ([fdabd2e](https://github.com/codecov/uploader/commit/fdabd2ee3fc94a0d03565017bf54e18010b9daf6))
+- add network filter ([3bbc222](https://github.com/codecov/uploader/commit/3bbc22247f76d6ea33e6061fad22857c222a2ac0))
+- add network prefix ([4d5ee16](https://github.com/codecov/uploader/commit/4d5ee16bc0d96bca7b477017ba664f602b80b11f))
+- ignore `*.egg-info` ([54060a8](https://github.com/codecov/uploader/commit/54060a86a52bbeb6763454f4284fe290cb8760ef))
+
+### Bug Fixes
+
+- enable `dot` ([549894c](https://github.com/codecov/uploader/commit/549894ce2a2a0f2a3b93f4e88861d419f7b2a0be))
+- use correct variable for args so verbose logs show ([e8455ef](https://github.com/codecov/uploader/commit/e8455ef3cf717eeedceb2c43221a29f64264b077))
+
 ### [0.1.8](https://github.com/codecov/uploader/compare/v0.1.7...v0.1.8) (2021-10-21)
 
 ### Features
diff --git a/Makefile b/Makefile
index ba1cfdf..22c36b2 100644
--- a/Makefile
+++ b/Makefile
@@ -32,4 +32,4 @@ build_alpine:
 .PHONY: run-standards-comparison
 run-standards-comparison:
 	docker pull codecov/autotest:standards-latest > /dev/null 2>&1
-	docker run --network autotest_codecov -e HOST_URL=http://web.local:5000 codecov/autotest:standards-latest
+	docker run --network autotest_codecov -e HOST_URL=http://web.local:5000 -e IS_UPLOADER=true -it -v "$(PWD)/out:/usr/app/out" codecov/autotest:standards-latest
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index b34219d..aa12abc 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -1,12 +1,12 @@
 {
   "name": "codecov",
-  "version": "0.1.8",
+  "version": "0.1.9",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "codecov",
-      "version": "0.1.8",
+      "version": "0.1.9",
       "license": "ISC",
       "dependencies": {
         "fast-glob": "3.2.7",
diff --git a/package.json b/package.json
index 7d6ceb7..5a8250c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "codecov",
-  "version": "0.1.8",
+  "version": "0.1.9",
   "description": "Codecov Report Uploader",
   "private": true,
   "bin": "dist/bin/codecov.js",
diff --git a/src/ci_providers/index.ts b/src/ci_providers/index.ts
index d5a547e..797b99c 100644
--- a/src/ci_providers/index.ts
+++ b/src/ci_providers/index.ts
@@ -10,6 +10,7 @@ import * as providerCodeBuild from './provider_codebuild'
 import * as providerDrone from './provider_drone'
 import * as providerGitHubactions from './provider_githubactions'
 import * as providerGitLabci from './provider_gitlabci'
+import * as providerHerokuci from './provider_herokuci'
 import * as providerJenkinsci from './provider_jenkinsci'
 import * as providerLocal from './provider_local'
 import * as providerTeamCity from './provider_teamcity'
@@ -28,6 +29,7 @@ const providerList: IProvider[] = [
   providerDrone,
   providerGitHubactions,
   providerGitLabci,
+  providerHerokuci,
   providerJenkinsci,
   providerTeamCity,
   providerTravisci,
diff --git a/src/ci_providers/provider_appveyorci.ts b/src/ci_providers/provider_appveyorci.ts
index 53a8575..88cb4dd 100644
--- a/src/ci_providers/provider_appveyorci.ts
+++ b/src/ci_providers/provider_appveyorci.ts
@@ -52,7 +52,7 @@ function _getService() {
   return 'appveyor'
 }
 
-export function getServiceName() {
+export function getServiceName(): string {
   return 'Appveyor CI'
 }
 
diff --git a/src/ci_providers/provider_buildkite.ts b/src/ci_providers/provider_buildkite.ts
index 67f57fd..a2d79f2 100644
--- a/src/ci_providers/provider_buildkite.ts
+++ b/src/ci_providers/provider_buildkite.ts
@@ -101,8 +101,8 @@ function _getSHA(inputs: UploaderInputs): string {
  */
 function _getSlug(inputs: UploaderInputs): string {
   const { args, environment: envs } = inputs
-  if (args.slug || envs.BUILDKITE_PROJECT_SLUG) {
-    return args.slug || envs.BUILDKITE_PROJECT_SLUG || ''
+  if (args.slug || envs.BUILDKITE_PIPELINE_SLUG) {
+    return args.slug || envs.BUILDKITE_PIPELINE_SLUG || ''
   }
   throw new Error('Unable to detect slug, please set manually with the -r flag')
 }
@@ -125,7 +125,7 @@ export function getServiceParams(inputs: UploaderInputs): IServiceParams {
   }
 }
 
-export function getEnvVarNames() {
+export function getEnvVarNames(): string[] {
   return [
     'BUILDKITE',
     'BUILDKITE_BRANCH',
diff --git a/src/ci_providers/provider_herokuci.ts b/src/ci_providers/provider_herokuci.ts
new file mode 100644
index 0000000..09a4e5d
--- /dev/null
+++ b/src/ci_providers/provider_herokuci.ts
@@ -0,0 +1,69 @@
+import { parseSlugFromRemoteAddr } from '../helpers/git'
+import { IServiceParams, UploaderEnvs, UploaderInputs } from '../types'
+
+export function detect(envs: UploaderEnvs): boolean {
+  return Boolean(envs.CI) && envs.HEROKU_TEST_RUN_BRANCH != ''
+}
+
+function _getBuild(inputs: UploaderInputs): string {
+  const { args, environment: envs} = inputs
+  return args.build || envs.HEROKU_TEST_RUN_ID || ''
+}
+
+function _getBuildURL(): string {
+  return ''
+}
+
+function _getBranch(inputs: UploaderInputs): string {
+  const { args, environment: envs} = inputs
+  return args.branch || envs.HEROKU_TEST_RUN_BRANCH || ''
+}
+
+function _getJob() {
+  return ''
+}
+
+function _getPR(inputs: UploaderInputs): string {
+  const { args } = inputs
+  return args.pr || ''
+}
+
+function _getService(): string {
+  return 'heroku'
+}
+
+export function getServiceName(): string {
+  return 'Heroku CI'
+}
+
+function _getSHA(inputs: UploaderInputs): string {
+  const { args, environment: envs} = inputs
+  return args.sha || envs.HEROKU_TEST_RUN_COMMIT_VERSION || ''
+}
+
+function _getSlug(inputs: UploaderInputs): string {
+  const { args } = inputs
+  return args.slug || parseSlugFromRemoteAddr('') || ''
+}
+
+export function getServiceParams(inputs: UploaderInputs): IServiceParams {
+  return {
+    branch: _getBranch(inputs),
+    build: _getBuild(inputs),
+    buildURL: _getBuildURL(),
+    commit: _getSHA(inputs),
+    job: _getJob(),
+    pr: _getPR(inputs),
+    service: _getService(),
+    slug: _getSlug(inputs),
+  }
+}
+
+export function getEnvVarNames(): string[] {
+  return [
+    'CI',
+    'HEROKU_TEST_RUN_BRANCH',
+    'HEROKU_TEST_RUN_COMMIT_VERSION',
+    'HEROKU_TEST_RUN_ID',
+  ]
+}
diff --git a/src/ci_providers/provider_template.js b/src/ci_providers/provider_template.ts
similarity index 77%
rename from src/ci_providers/provider_template.js
rename to src/ci_providers/provider_template.ts
index c5feecf..95acfde 100644
--- a/src/ci_providers/provider_template.js
+++ b/src/ci_providers/provider_template.ts
@@ -1,3 +1,5 @@
+import { IServiceParams, UploaderEnvs, UploaderInputs } from '../types'
+
 /**
  * Detects if this CI provider is being used
  *
@@ -5,8 +7,8 @@
  * @returns boolean
  */
 
-// eslint-disable-next-line no-unused-vars
-function detect(envs) {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export function detect(envs: UploaderEnvs): boolean {
   return false
 }
 
@@ -16,7 +18,7 @@ function detect(envs) {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {string}
  */
-function _getBuild(inputs) {
+function _getBuild(inputs: UploaderInputs): string {
   const { args } = inputs
   return args.build || ''
 }
@@ -27,8 +29,8 @@ function _getBuild(inputs) {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {string}
  */
-// eslint-disable-next-line no-unused-vars
-function _getBuildURL(inputs) {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function _getBuildURL(inputs: UploaderInputs): string {
   return ''
 }
 
@@ -38,7 +40,7 @@ function _getBuildURL(inputs) {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {string}
  */
-function _getBranch(inputs) {
+function _getBranch(inputs: UploaderInputs): string {
   const { args } = inputs
   try {
     return args.branch || ''
@@ -55,8 +57,8 @@ function _getBranch(inputs) {
  * @param {*} envs an object of enviromental variable key/value pairs
  * @returns {string}
  */
-// eslint-disable-next-line no-unused-vars
-function _getJob(envs) {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function _getJob(envs: UploaderEnvs): string {
   return ''
 }
 
@@ -66,8 +68,8 @@ function _getJob(envs) {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {string}
  */
-// eslint-disable-next-line no-unused-vars
-function _getPR(inputs) {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function _getPR(inputs: UploaderInputs): string {
   const { args } = inputs
   try {
     return args.pr || ''
@@ -81,7 +83,7 @@ function _getPR(inputs) {
  *
  * @returns {string}
  */
-function _getService() {
+function _getService(): string {
   return ''
 }
 
@@ -90,7 +92,7 @@ function _getService() {
  *
  * @returns
  */
-function getServiceName() {
+export function getServiceName(): string {
   return ''
 }
 /**
@@ -99,7 +101,7 @@ function getServiceName() {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {string}
  */
-function _getSHA(inputs) {
+function _getSHA(inputs: UploaderInputs): string {
   const { args } = inputs
   try {
     return args.sha || ''
@@ -115,7 +117,7 @@ function _getSHA(inputs) {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {string}
  */
-function _getSlug(inputs) {
+function _getSlug(inputs: UploaderInputs): string {
   const { args } = inputs
   try {
     return args.slug || ''
@@ -129,13 +131,13 @@ function _getSlug(inputs) {
  * @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
  * @returns {{ branch: string, build: string, buildURL: string, commit: string, job: string, pr: string, service: string, slug: string }}
  */
-function getServiceParams(inputs) {
+export function getServiceParams(inputs: UploaderInputs): IServiceParams {
   return {
     branch: _getBranch(inputs),
     build: _getBuild(inputs),
     buildURL: _getBuildURL(inputs),
     commit: _getSHA(inputs),
-    job: _getJob(inputs.envs),
+    job: _getJob(inputs.environment),
     pr: _getPR(inputs),
     service: _getService(),
     slug: _getSlug(inputs),
diff --git a/src/helpers/cli.ts b/src/helpers/cli.ts
index f3da199..2d08b58 100644
--- a/src/helpers/cli.ts
+++ b/src/helpers/cli.ts
@@ -122,6 +122,18 @@ const args: ICLIArgument[] = [
     default: false,
     description: 'Move discovered coverage reports to the trash',
   },
+  {
+    alias: 'i',
+    name: 'networkFiler',
+    type: 'string',
+    description: 'Specify a filter on the files listed in the network section of the Codecov report. Useful for upload-specific path fixing',
+  },
+  {
+    alias: 'k',
+    name: 'networkPrefix',
+    type: 'string',
+    description: 'Specify a prefix on files listed in the network section of the Codecov report. Useful to help resolve path fixing',
+  },
   {
     alias: 'X',
     name: 'feature',
diff --git a/src/helpers/files.ts b/src/helpers/files.ts
index 2e7394f..70bafcb 100644
--- a/src/helpers/files.ts
+++ b/src/helpers/files.ts
@@ -204,6 +204,7 @@ export async function getCoverageFiles(
     return parts.join(EMPTY_STRING)
   }), {
     cwd: projectRoot,
+    dot: true,
     ignore: [...manualBlacklist(), ...globBlacklist()],
   })
 }
@@ -240,13 +241,26 @@ export function getAllFiles(
     error,
   } = spawnSync('git', ['-C', dirPath, 'ls-files'], { encoding: 'utf8' })
 
-  return error instanceof Error || status !== 0
-    ? glob
+  let files = []
+  if (error instanceof Error || status !== 0) {
+    files = glob
       .sync(['**/*', '**/.[!.]*'], {
         cwd: dirPath,
         ignore: manualBlacklist().map(globstar),
       })
-    : stdout.split(/[\r\n]+/)
+  } else {
+    files = stdout.split(/[\r\n]+/)
+  }
+
+  if (args.networkFilter) {
+    files = files.filter(file => file.startsWith(String(args.networkFilter)))
+  }
+
+  if (args.networkPrefix) {
+    files = files.map(file => String(args.networkPrefix) + file)
+  }
+  
+  return files
 }
 
 /**
diff --git a/src/helpers/web.ts b/src/helpers/web.ts
index 29bc1d5..5c459ab 100644
--- a/src/helpers/web.ts
+++ b/src/helpers/web.ts
@@ -25,7 +25,7 @@ export function populateBuildParams(
   if (typeof args.flags === 'object') {
     flags = [...args.flags]
   } else {
-    flags = (args.flags || '').split(',')
+    flags = String(args.flags || '').split(',')
   }
   serviceParams.flags = flags
     .filter(flag => validateHelpers.validateFlags(flag))
diff --git a/src/index.ts b/src/index.ts
index 53ced18..865a6fe 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -57,6 +57,8 @@ function dryRun(
  * @param {string} args.file Target file(s) to upload
  * @param {string} args.flags Flag the upload to group coverage metrics
  * @param {string} args.name Custom defined name of the upload. Visible in Codecov UI
+ * @param {string} args.networkFilter Specify a filter on the files listed in the network section of the Codecov report. Useful for upload-specific path fixing
+ * @param {string} args.networkPrefix Specify a prefix on files listed in the network section of the Codecov report. Useful to help resolve path fixing
  * @param {string} args.parent The commit SHA of the parent for which you are uploading coverage.
  * @param {string} args.pr Specify the pull request number mannually
  * @param {string} args.token Codecov upload token
diff --git a/src/types.ts b/src/types.ts
index 5a04bf2..eb4d207 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -5,8 +5,10 @@ export interface UploaderArgs {
   env?: string // Specify environment variables to be included with this build
   sha?: string // Specify the commit SHA mannually
   file?: string | string[] // Target file(s) to upload
-  flags?: string | string[] // Flag the upload to group coverage metrics
+  flags: string | string[] // Flag the upload to group coverage metrics
   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
   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


Test patch:
diff --git a/test/helpers/files.test.ts b/test/helpers/files.test.ts
index 9d65428..939eaa0 100644
--- a/test/helpers/files.test.ts
+++ b/test/helpers/files.test.ts
@@ -56,6 +56,34 @@ describe('File Helpers', () => {
     ).toBe(files.join('\n'))
   })
 
+  it('can get a file listing with a file filter', async () => {
+    const files = ['npm-shrinkwrap.json', 'package.json', 'package-lock.json', 'src/file.js']
+    td.replace(childProcess, 'spawnSync', () => {
+      return {
+        stdout: files.join('\n'),
+        status: 0,
+        error: undefined,
+      }
+    })
+    expect(
+      await fileHelpers.getFileListing('.', { flags: '', networkFilter: 'package', verbose: 'true' }),
+    ).toBe(['package.json', 'package-lock.json'].join('\n'))
+  })
+
+  it('can get a file listing with a dir filter', async () => {
+    const files = ['npm-shrinkwrap.json', 'package.json', 'src/file.js']
+    td.replace(childProcess, 'spawnSync', () => {
+      return {
+        stdout: files.join('\n'),
+        status: 0,
+        error: undefined,
+      }
+    })
+    expect(
+      await fileHelpers.getFileListing('.', { flags: '', networkFilter: 'src/', verbose: 'true' }),
+    ).toBe(['src/file.js'].join('\n'))
+  })
+
   it('can get a file listing when git is unavailable', async () => {
     td.replace(childProcess, 'spawnSync', () => {
       return { stdout: '', status: null, error: new Error() }
@@ -65,6 +93,52 @@ describe('File Helpers', () => {
     ).toMatch('npm-shrinkwrap.json')
   })
 
+  it('can get a file listing with a file filter and prefix', async () => {
+    const files = ['npm-shrinkwrap.json', 'package.json', 'package-lock.json', 'src/file.js']
+    td.replace(childProcess, 'spawnSync', () => {
+      return {
+        stdout: files.join('\n'),
+        status: 0,
+        error: undefined,
+      }
+    })
+    expect(
+      await fileHelpers.getFileListing('.', { flags: '', networkFilter: 'package', networkPrefix: 'build/', verbose: 'true' }),
+    ).toBe(['build/package.json', 'build/package-lock.json'].join('\n'))
+  })
+
+  it('can get a file listing with a dir filter and prefix', async () => {
+    const files = ['npm-shrinkwrap.json', 'package.json', 'src/file.js']
+    td.replace(childProcess, 'spawnSync', () => {
+      return {
+        stdout: files.join('\n'),
+        status: 0,
+        error: undefined,
+      }
+    })
+    expect(
+      await fileHelpers.getFileListing('.', { flags: '', networkFilter: 'src/', networkPrefix: 'build/', verbose: 'true' }),
+    ).toBe(['build/src/file.js'].join('\n'))
+  })
+
+  it('can get a file listing when git is unavailable with a filter', async () => {
+    td.replace(childProcess, 'spawnSync', () => {
+      return { stdout: '', status: null, error: new Error() }
+    })
+    expect(
+      await fileHelpers.getFileListing('.', { flags: '', networkFilter: 'npm', verbose: 'true' }),
+    ).toMatch('npm-shrinkwrap.json')
+  })
+
+  it('can get a file listing when git is unavailable with a filter without matches', async () => {
+    td.replace(childProcess, 'spawnSync', () => {
+      return { stdout: '', status: null, error: new Error() }
+    })
+    expect(
+      await fileHelpers.getFileListing('.', { flags: '', networkFilter: 'src', verbose: 'true' }),
+    ).toMatch('')
+  })
+
   describe('Coverage report handling', () => {
     it('can generate report file header', () => {
       expect(fileHelpers.fileHeader('test-coverage-file.xml')).toBe(
diff --git a/test/helpers/provider.test.ts b/test/helpers/provider.test.ts
index c6967aa..a08a858 100644
--- a/test/helpers/provider.test.ts
+++ b/test/helpers/provider.test.ts
@@ -14,6 +14,7 @@ describe('detectProvider()', () => {
       args: {
         sha: '1234566',
         slug: 'fakeOrg/fakeRepo',
+        flags: ''
       },
       environment: {},
     }
@@ -28,6 +29,7 @@ describe('detectProvider()', () => {
     const inputs: UploaderInputs = {
       args: {
         sha: '1234566',
+        flags: ''
       },
       environment: {},
     }
@@ -44,7 +46,9 @@ describe('detectProvider()', () => {
       error: 'Git is not installed!',
     })
     const inputs: UploaderInputs = {
-      args: {},
+      args: {
+        flags: ''
+      },
       environment: {},
     }
     expect(()  => detectProvider(inputs)).toThrowError(/Unable to detect SHA and slug, please specify them manually/)
@@ -62,7 +66,9 @@ describe('walkProviders()', () => {
       error: 'Git is not installed!',
     })
     const inputs: UploaderInputs = {
-      args: {},
+      args: {
+        flags: ''
+      },
       environment: {},
     }
     expect(()  => walkProviders(inputs)).toThrowError(/Unable to detect provider./)
@@ -71,7 +77,9 @@ describe('walkProviders()', () => {
 
   it('will return serviceParams if able to detect', () => {
     const inputs: UploaderInputs = {
-      args: {},
+      args: {
+        flags: ''
+      },
       environment: {
         CI: 'true',
         CIRCLECI: 'true',
diff --git a/test/helpers/token.test.ts b/test/helpers/token.test.ts
index f04c264..47dd125 100644
--- a/test/helpers/token.test.ts
+++ b/test/helpers/token.test.ts
@@ -90,7 +90,8 @@ describe('Get tokens', () => {
     const inputs: UploaderInputs = {
       args: {
         url: 'dummy.local',
-        token: 'goodToken'
+        token: 'goodToken',
+        flags: ''
       },
       environment: {
         CODECOV_TOKEN: 'badToken'
@@ -103,6 +104,7 @@ describe('Get tokens', () => {
     const inputs: UploaderInputs = {
       args: {
         url: 'dummy.local',
+        flags: ''
       },
       environment: {
         CODECOV_TOKEN: 'goodT----oken'
@@ -114,7 +116,8 @@ describe('Get tokens', () => {
   it('should fail validation when an invalid token is passed and host is not changed', () => {
     const inputs: UploaderInputs = {
       args: {
-        url: DEFAULT_UPLOAD_HOST
+        url: DEFAULT_UPLOAD_HOST,
+        flags: ''
       },
       environment: {
         CODECOV_TOKEN: 'bad------Token'
diff --git a/test/providers/index.test.ts b/test/providers/index.test.ts
index dd32ffe..7a7f2b4 100644
--- a/test/providers/index.test.ts
+++ b/test/providers/index.test.ts
@@ -29,7 +29,8 @@ describe('CI Providers', () => {
       const inputs: UploaderInputs = {
         args: {
           sha: '123',
-          slug: 'testOrg/testRepo'
+          slug: 'testOrg/testRepo',
+          flags: ''
         },
         environment: {}
       }
diff --git a/test/providers/provider_appveyorci.test.ts b/test/providers/provider_appveyorci.test.ts
index 1e92e81..5ef825c 100644
--- a/test/providers/provider_appveyorci.test.ts
+++ b/test/providers/provider_appveyorci.test.ts
@@ -42,7 +42,9 @@ describe('AppveyorCI Params', () => {
 
     it('does run with AppveyorCI env variable', () => {
       const inputs : UploaderInputs= {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {
           CI: 'true',
           APPVEYOR: 'true',
diff --git a/test/providers/provider_bitbucket.test.ts b/test/providers/provider_bitbucket.test.ts
index c0ef410..9178c5f 100644
--- a/test/providers/provider_bitbucket.test.ts
+++ b/test/providers/provider_bitbucket.test.ts
@@ -29,7 +29,9 @@ describe('Bitbucket Params', () => {
 
     it('does not run without Bitbucket env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {
           BITBUCKET_BUILD_NUMBER: '1',
           CI: 'true',
diff --git a/test/providers/provider_buildkite.test.ts b/test/providers/provider_buildkite.test.ts
index f57af22..1d8a01b 100644
--- a/test/providers/provider_buildkite.test.ts
+++ b/test/providers/provider_buildkite.test.ts
@@ -19,7 +19,9 @@ describe('Buildkite Params', () => {
 
     it('does not run without Buildkite env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {
           BUILDKITE: 'true',
         },
@@ -41,7 +43,7 @@ describe('Buildkite Params', () => {
         BUILDKITE: 'true',
         BUILDKITE_BUILD_NUMBER: '1',
         BUILDKITE_JOB_ID: '3',
-        BUILDKITE_PROJECT_SLUG: 'testRepo',
+        BUILDKITE_PIPELINE_SLUG: 'testRepo',
         BUILDKITE_BRANCH: 'main',
         BUILDKITE_COMMIT: 'testingsha',
         BUILDKITE_BUILD_URL: 'https://buildkite.com/testOrg/testRepo',
diff --git a/test/providers/provider_circleci.test.ts b/test/providers/provider_circleci.test.ts
index cce23bd..778bd8e 100644
--- a/test/providers/provider_circleci.test.ts
+++ b/test/providers/provider_circleci.test.ts
@@ -11,7 +11,9 @@ describe('CircleCI Params', () => {
   describe('detect()', () => {
     it('does not run without CircleCI env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {},
       }
       const detected = providerCircleci.detect(inputs.environment)
@@ -20,7 +22,9 @@ describe('CircleCI Params', () => {
 
     it('does run with CircleCI env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {
           CI: 'true',
           CIRCLECI: 'true',
diff --git a/test/providers/provider_cirrus.test.ts b/test/providers/provider_cirrus.test.ts
index 1fb1434..466e866 100644
--- a/test/providers/provider_cirrus.test.ts
+++ b/test/providers/provider_cirrus.test.ts
@@ -10,8 +10,10 @@ describe('Cirrus Params', () => {
 
   describe('detect()', () => {
     it('does not run without Cirrus env variable', () => {
-      const inputs = {
-        args: {},
+      const inputs: UploaderInputs = {
+        args: {
+          flags: ''
+        },
         environment: {},
       }
       const detected = providerCirrus.detect(inputs.environment)
diff --git a/test/providers/provider_herokuci.test.ts b/test/providers/provider_herokuci.test.ts
new file mode 100644
index 0000000..5336ee9
--- /dev/null
+++ b/test/providers/provider_herokuci.test.ts
@@ -0,0 +1,122 @@
+import td from 'testdouble'
+import childProcess from 'child_process'
+import { IServiceParams, UploaderInputs } from '../../src/types'
+
+const providerHerokuci = require('../../src/ci_providers//provider_herokuci')
+
+describe('HerokuCI Params', () => {
+  afterEach(() => {
+    td.reset()
+  })
+
+  describe('detect()', () => {
+    it('does not run without HerokuCI env variable', () => {
+      const inputs: UploaderInputs = {
+        args: {
+          flags: ''
+        },
+        environment: {},
+      }
+      const detected = providerHerokuci.detect(inputs.environment)
+      expect(detected).toBeFalsy()
+    })
+
+    it('does run with Herokuci env variable', () => {
+      const inputs: UploaderInputs= {
+        args: {
+          flags: ''
+        },
+        environment: {
+          CI: 'true',
+          HEROKU_TEST_RUN_BRANCH: 'test',
+        },
+      }
+      const detected = providerHerokuci.detect(inputs.environment)
+      expect(detected).toBeTruthy()
+    })
+  })
+
+  // This should test that the provider outputs proper default values
+  it('gets the correct params on no env variables', () => {
+    const inputs: UploaderInputs = {
+      args: { tag: '', url: '', source: '', flags: '' },
+      environment: {},
+    }
+    const expected: IServiceParams = {
+      branch: '',
+      build: '',
+      buildURL: '',
+      commit: '',
+      job: '',
+      pr: '',
+      service: 'heroku',
+      slug: '',
+    }
+    const spawnSync = td.replace(childProcess, 'spawnSync')
+    td.when(
+      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+    ).thenReturn({ stdout: '' })
+    const params = providerHerokuci.getServiceParams(inputs)
+    expect(params).toMatchObject(expected)
+  })
+
+  // This should test that the provider outputs proper parameters when a push event is created
+  it('gets the correct params on push', () => {
+    const inputs: UploaderInputs = {
+      args: { tag: '', url: '', source: '', flags: '' },
+      environment: {
+        CI: 'true',
+        HEROKU_TEST_RUN_BRANCH: 'testBranch',
+        HEROKU_TEST_RUN_COMMIT_VERSION: 'testSha',
+        HEROKU_TEST_RUN_ID: '2',
+      },
+    }
+    const expected: IServiceParams = {
+      branch: 'testBranch',
+      build: '2',
+      buildURL: '',
+      commit: 'testSha',
+      job: '',
+      pr: '',
+      service: 'heroku',
+      slug: 'testOrg/testRepo',
+    }
+    const spawnSync = td.replace(childProcess, 'spawnSync')
+    td.when(
+      spawnSync('git', ['config', '--get', 'remote.origin.url']),
+    ).thenReturn({ stdout: 'https://github.com/testOrg/testRepo.git' })
+    const params = providerHerokuci.getServiceParams(inputs)
+    expect(params).toMatchObject(expected)
+  })
+
+  // This should test that the provider outputs proper parameters when given overrides
+  it('gets the correct params on overrides', () => {
+    const inputs: UploaderInputs = {
+      args: {
+        branch: 'branch',
+        build: '3',
+        pr: '2',
+        sha: 'testsha',
+        slug: 'testOrg/testRepo',
+        tag: '',
+        url: '',
+        source: '',
+        flags: '',
+      },
+      environment: {},
+    }
+    const expected: IServiceParams = {
+      branch: 'branch',
+      build: '3',
+      buildURL: '',
+      commit: 'testsha',
+      job: '',
+      pr: '2',
+      service: 'heroku',
+      slug: 'testOrg/testRepo',
+    }
+    const params = providerHerokuci.getServiceParams(inputs)
+    expect(expected).toBeTruthy()
+    expect(params).toMatchObject(expected)
+  })
+})
diff --git a/test/providers/provider_teamcity.test.ts b/test/providers/provider_teamcity.test.ts
index c2bba26..b263342 100644
--- a/test/providers/provider_teamcity.test.ts
+++ b/test/providers/provider_teamcity.test.ts
@@ -12,7 +12,9 @@ describe('TeamCity Params', () => {
   describe('detect()', () => {
     it('does not run without TeamCity env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {},
       }
       const detected = providerTeamCity.detect(inputs.environment)
@@ -25,6 +27,7 @@ describe('TeamCity Params', () => {
           tag: '',
           url: '',
           source: '',
+          flags: ''
         },
         environment: {
           CI: 'true',
diff --git a/test/providers/provider_template.test.ts b/test/providers/provider_template.test.ts
index 1ab2d0f..d519a56 100644
--- a/test/providers/provider_template.test.ts
+++ b/test/providers/provider_template.test.ts
@@ -15,7 +15,9 @@ describe('<Ci> Params', () => {
   describe('detect()', () => {
     it('does not run without <Ci> env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {},
       }
       /*
@@ -26,7 +28,9 @@ describe('<Ci> Params', () => {
 
     it('does not run without <Ci> env variable', () => {
       const inputs: UploaderInputs= {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {},
       }
       /*
diff --git a/test/providers/provider_travisci.test.ts b/test/providers/provider_travisci.test.ts
index 7e75ff6..f9de5dc 100644
--- a/test/providers/provider_travisci.test.ts
+++ b/test/providers/provider_travisci.test.ts
@@ -37,7 +37,9 @@ describe('TravisCI Params', () => {
 
     it('does run with TravisCI env variable', () => {
       const inputs: UploaderInputs = {
-        args: {},
+        args: {
+          flags: ''
+        },
         environment: {
           CI: 'true',
           TRAVIS: 'true',