Skip to content

Commit 6052d9b

Browse files
committed
ci(all-green): drop the cross-run lcov merge for Datadog coverage uploads
datadog-ci coverage upload recursively discovers every report file under a given path by default, so uploading each sibling workflow's already per-run-merged lcov file directly (one datadog-ci invocation over coverage-upload/) makes the extra merge into a single final lcov file redundant, mirroring the same simplification already applied to junit uploads. Generated by Claude Code.
1 parent c13168b commit 6052d9b

3 files changed

Lines changed: 12 additions & 94 deletions

File tree

scripts/group-coverage.mjs

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import istanbulLibCoverage from 'istanbul-lib-coverage'
3131

3232
const INPUT_DIR = 'coverage-results'
3333
const OUTPUT_DIR = 'coverage-upload'
34-
const FINAL_OUTPUT_DIR = 'coverage-upload-final'
3534
const ARTIFACT_PREFIX = 'coverage-'
3635

3736
const REPORTS = new Map([
@@ -283,50 +282,4 @@ function mergeRunCoverage (runId, inputDir = INPUT_DIR, outputDir = OUTPUT_DIR)
283282
return { lcovDir, jsonDir }
284283
}
285284

286-
/**
287-
* Recursively collect every already-per-run-merged `lcov.info` file under `coverage-upload/<run-id>/lcov/`.
288-
*
289-
* @param {string} dir
290-
* @param {string[]} out
291-
* @returns {string[]}
292-
*/
293-
function collectMergedLcovFiles (dir, out = []) {
294-
let entries
295-
try {
296-
entries = readdirSync(dir, { withFileTypes: true })
297-
} catch {
298-
return out
299-
}
300-
for (const entry of entries) {
301-
const full = join(dir, entry.name)
302-
if (entry.isDirectory()) {
303-
collectMergedLcovFiles(full, out)
304-
} else if (entry.name === 'lcov.info') {
305-
out.push(full)
306-
}
307-
}
308-
return out
309-
}
310-
311-
/**
312-
* Merge every sibling workflow's already-per-run-merged lcov file into one final lcov file, for a
313-
* single Datadog coverage upload covering the whole commit instead of one upload per workflow run.
314-
* Unlike Codecov, whose per-workflow flag keeps its upload scoped to one run at a time (see
315-
* `upload-coverage.mjs`), Datadog's coverage flag is the same for every run, so there's no reason
316-
* to pay for a separate upload call per workflow.
317-
*
318-
* @param {string} [inputDir]
319-
* @param {string} [outputDir]
320-
* @returns {string|null} Directory containing the merged `lcov.info`, or null if no run produced one.
321-
*/
322-
function mergeAllRunsCoverage (inputDir = OUTPUT_DIR, outputDir = FINAL_OUTPUT_DIR) {
323-
const reportPaths = collectMergedLcovFiles(inputDir)
324-
if (reportPaths.length === 0) return null
325-
326-
const lcovDir = join(outputDir, 'lcov')
327-
mkdirSync(lcovDir, { recursive: true })
328-
writeFileSync(join(lcovDir, 'lcov.info'), mergeLcov(reportPaths))
329-
return lcovDir
330-
}
331-
332-
export { mergeAllRunsCoverage, mergeCoverageJson, mergeLcov, mergeRunCoverage, planCoverageGroups }
285+
export { OUTPUT_DIR, mergeCoverageJson, mergeLcov, mergeRunCoverage, planCoverageGroups }

scripts/group-coverage.spec.mjs

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import { join } from 'node:path'
55

66
import { afterEach, beforeEach, describe, it } from 'mocha'
77

8-
import {
9-
mergeAllRunsCoverage, mergeCoverageJson, mergeLcov, mergeRunCoverage, planCoverageGroups,
10-
} from './group-coverage.mjs'
8+
import { mergeCoverageJson, mergeLcov, mergeRunCoverage, planCoverageGroups } from './group-coverage.mjs'
119

1210
/**
1311
* One cell's discovered report set: one `lcov` entry per Node.js version the cell ran.
@@ -233,39 +231,4 @@ describe('group-coverage', () => {
233231
assert.equal(existsSync(join(dir, 'coverage-upload', '42')), false)
234232
})
235233
})
236-
237-
describe('mergeAllRunsCoverage', () => {
238-
let dir
239-
240-
beforeEach(() => {
241-
dir = mkdtempSync(join(tmpdir(), 'group-coverage-all-runs-'))
242-
})
243-
244-
afterEach(() => {
245-
rmSync(dir, { force: true, recursive: true })
246-
})
247-
248-
it('sums DA hit counts across every run\'s already-merged lcov file', () => {
249-
const input = join(dir, 'coverage-upload')
250-
const output = join(dir, 'coverage-upload-final')
251-
mkdirSync(join(input, '1', 'lcov'), { recursive: true })
252-
mkdirSync(join(input, '2', 'lcov'), { recursive: true })
253-
writeFileSync(join(input, '1', 'lcov', 'lcov.info'), 'SF:shared.js\nDA:1,1\nLF:1\nLH:1\nend_of_record\n')
254-
writeFileSync(join(input, '2', 'lcov', 'lcov.info'), 'SF:shared.js\nDA:1,2\nLF:1\nLH:1\nend_of_record\n')
255-
256-
const lcovDir = mergeAllRunsCoverage(input, output)
257-
258-
assert.equal(lcovDir, join(output, 'lcov'))
259-
assert.equal(
260-
readFileSync(join(lcovDir, 'lcov.info'), 'utf8'),
261-
'SF:shared.js\nDA:1,3\nLF:1\nLH:1\nend_of_record\n'
262-
)
263-
})
264-
265-
it('returns null when no run produced an lcov file', () => {
266-
const input = join(dir, 'coverage-upload')
267-
mkdirSync(input, { recursive: true })
268-
assert.equal(mergeAllRunsCoverage(input, join(dir, 'coverage-upload-final')), null)
269-
})
270-
})
271234
})

scripts/upload-coverage.mjs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { mergeAllRunsCoverage, mergeRunCoverage } from './group-coverage.mjs'
1+
import { existsSync } from 'node:fs'
2+
import { OUTPUT_DIR, mergeRunCoverage } from './group-coverage.mjs'
23
import { logUploads, runUpload, runUploadWithRetry } from './run-upload.mjs'
34

45
// Codecov validates flags against `^[\w\.\-]{1,45}$` and silently drops any that fail.
@@ -108,18 +109,19 @@ export async function uploadCoverage (run, options) {
108109
}
109110

110111
/**
111-
* Merge every sibling workflow's already-per-run-merged lcov file into one and upload it to Datadog
112-
* in a single call, instead of uploading each workflow run's coverage separately — Datadog's
113-
* coverage flag doesn't vary per run, so nothing needs the per-run separation Codecov's flags
114-
* require (see `uploadCoverage`).
112+
* Upload every sibling workflow's already-per-run-merged lcov file to Datadog in a single call,
113+
* instead of uploading each workflow run's coverage separately — Datadog's coverage flag doesn't
114+
* vary per run, so nothing needs the per-run separation Codecov's flags require (see
115+
* `uploadCoverage`). `datadog-ci coverage upload` recursively discovers every report file under a
116+
* given path by default, so there's no need to merge every run's lcov file into one document first,
117+
* the way junit upload used to (see `upload-junit.mjs`).
115118
*
116119
* @returns {Promise<import('./run-upload.mjs').UploadResult[]>}
117120
*/
118121
export async function uploadAllCoverageToDatadog () {
119-
const lcovDir = mergeAllRunsCoverage()
120-
if (!lcovDir) return []
122+
if (!existsSync(OUTPUT_DIR)) return []
121123

122-
const result = await runUpload('datadog-ci', ['coverage', 'upload', lcovDir, '--flags', 'coverage'])
124+
const result = await runUpload('datadog-ci', ['coverage', 'upload', OUTPUT_DIR, '--flags', 'coverage'])
123125
return [result]
124126
}
125127

0 commit comments

Comments
 (0)