Repository: codecov/uploader
Pull request #750 (2022-05-05 03:51:53)

Fix coveragepy autorun
Right now, the automatic `coverage xml` is breaking for repositories that already run `coverage xml`

See https://community.codecov.com/t/files-not-found-with-uploader-v0-2-0/3601/1



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12819a9..fe7a20d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 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)
 
 
diff --git a/src/helpers/coveragepy.ts b/src/helpers/coveragepy.ts
index fd507e4..dc24073 100644
--- a/src/helpers/coveragepy.ts
+++ b/src/helpers/coveragepy.ts
@@ -1,9 +1,23 @@
+import glob from 'fast-glob'
+
 import { isProgramInstalled, runExternalProgram } from "./util"
 import { info } from './logger'
 
-export async function generateCoveragePyFile(): Promise<string> {
+export async function generateCoveragePyFile(projectRoot: string, overrideFiles: string[]): Promise<string> {
     if (!isProgramInstalled('coverage')) {
-        throw new Error('coveragepy is not installed')
+        return 'coveragepy is not installed'
+    }
+
+    if (overrideFiles.length > 0) {
+        return `Skipping coveragepy, files already specified`
+    }
+
+    const dotCoverage = await glob(
+        ['.coverage', '.coverage.*'],
+        {cwd: projectRoot, dot: true, onlyFiles: true},
+    )
+    if (dotCoverage.length == 0) {
+        return 'Skipping coveragepy, no .coverage file found.'
     }
 
     info('Running coverage xml...')
diff --git a/src/index.ts b/src/index.ts
index e5f6a3f..07fb486 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -179,15 +179,16 @@ export async function main(
     }
   }
 
+  let coverageFilePaths: string[] = []
+  requestedPaths = argAsArray(args.file)
+
   try {
-    await generateCoveragePyFile()
+    const coveragePyLogs = await generateCoveragePyFile(projectRoot, requestedPaths)
+    UploadLogger.verbose(`${coveragePyLogs}`)
   } catch (error) {
     UploadLogger.verbose(`Skipping coveragepy conversion: ${error}`)
   }
 
-  let coverageFilePaths: string[] = []
-  requestedPaths = argAsArray(args.file)
-
   coverageFilePaths = requestedPaths
 
   if (!args.feature || args.feature.split(',').includes('search') === false) {


Test patch:
diff --git a/test/fixtures/coveragepy/.coverage.test b/test/fixtures/coveragepy/.coverage.test
new file mode 100644
index 0000000..2691857
--- /dev/null
+++ b/test/fixtures/coveragepy/.coverage.test
@@ -0,0 +1,1 @@
+testfile
diff --git a/test/helpers/coveragepy.test.ts b/test/helpers/coveragepy.test.ts
index 884d0e6..050549b 100644
--- a/test/helpers/coveragepy.test.ts
+++ b/test/helpers/coveragepy.test.ts
@@ -1,6 +1,8 @@
-import td from 'testdouble'
+import path from 'path'
 import childProcess from 'child_process'
+import td from 'testdouble'
 import { generateCoveragePyFile } from '../../src/helpers/coveragepy'
+import * as fileHelpers from '../../src/helpers/files'
 import { SPAWNPROCESSBUFFERSIZE } from '../../src/helpers/util'
 
 describe('generateCoveragePyFile()', () => {
@@ -9,6 +11,11 @@ describe('generateCoveragePyFile()', () => {
     })
 
     it('should run when coveragepy is asked for', async () => {
+        const fixturesCoveragePyDir = path.join(
+            fileHelpers.fetchGitRoot(),
+            'test/fixtures/coveragepy',
+        )
+
         const spawnSync = td.replace(childProcess, 'spawnSync')
         td.when(spawnSync('coverage')).thenReturn({
             stdout: 'coverage installed',
@@ -19,13 +26,40 @@ describe('generateCoveragePyFile()', () => {
             error: null
         })
 
-        expect(await generateCoveragePyFile()).toBe('xml')
+        expect(await generateCoveragePyFile(fixturesCoveragePyDir, [])).toBe('xml')
+    })
+
+    it('should return if a file is provided', async () => {
+        const spawnSync = td.replace(childProcess, 'spawnSync')
+        td.when(spawnSync('coverage')).thenReturn({
+            stdout: 'coverage installed',
+            error: null
+        })
+
+        const projectRoot = process.cwd()
+        expect(await generateCoveragePyFile(projectRoot, ['fakefile'])).toBe('Skipping coveragepy, files already specified')
     })
 
     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/)
+        const projectRoot = process.cwd()
+        expect(await generateCoveragePyFile(projectRoot, [])).toBe('coveragepy is not installed')
+    })
+
+    it('should return a log when there are no dotcoverage files', async () => {
+        const fixturesYamlDir = path.join(
+            fileHelpers.fetchGitRoot(),
+            'test/fixtures/yaml',
+        )
+
+        const spawnSync = td.replace(childProcess, 'spawnSync')
+        td.when(spawnSync('coverage')).thenReturn({
+            stdout: 'coverage installed',
+            error: null
+        })
+
+        expect(await generateCoveragePyFile(fixturesYamlDir, [])).toBe('Skipping coveragepy, no .coverage file found.')
     })
 })