From 9b503434d1983a42deebbcec348529eec0e539f0 Mon Sep 17 00:00:00 2001 From: Martin Fillafer Date: Mon, 27 Mar 2023 10:44:43 +0200 Subject: [PATCH] feat: add directory mapping to map between Docker image and local path --- __tests__/integration.test.ts | 5 +++-- action.yml | 5 +++++ dist/index.js | 17 +++++++++++++---- src/main.ts | 5 ++++- src/parsers/pytest-junit/pytest-junit-parser.ts | 11 +++++++++-- src/test-parser.ts | 1 + 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/__tests__/integration.test.ts b/__tests__/integration.test.ts index d419022..a9b709e 100644 --- a/__tests__/integration.test.ts +++ b/__tests__/integration.test.ts @@ -11,6 +11,7 @@ const input: Record = { 'max-annotations': '10', 'fail-on-error': 'true', 'only-summary': 'false', + 'directory-mapping': 'mnt/extra-addons:mypath', token: '***' } @@ -56,7 +57,7 @@ describe('integration test', () => { }) jest .spyOn(LocalFileProvider.prototype, 'listTrackedFiles') - .mockResolvedValue(['addons/product_changes/tests/first_test.py']) + .mockResolvedValue(['mypath/product_changes/tests/first_test.py']) await import('../src/main') // trick to wait for the pending "main" Promise @@ -68,7 +69,7 @@ describe('integration test', () => { output: expect.objectContaining({ annotations: [ expect.objectContaining({ - path: 'addons/product_changes/tests/first_test.py' + path: 'mypath/product_changes/tests/first_test.py' }) ] }) diff --git a/action.yml b/action.yml index 37c1637..b41fcbc 100644 --- a/action.yml +++ b/action.yml @@ -68,6 +68,11 @@ inputs: Detailed listing of test suites and test cases will be skipped. default: 'false' required: false + directory-mapping: + description: | + Map part of the file paths to something else, so they match the paths of the repository. + This is needed when you use run your code in a container with a different path than the source code repository. + required: false token: description: GitHub Access Token required: false diff --git a/dist/index.js b/dist/index.js index 6867c51..add68ac 100644 --- a/dist/index.js +++ b/dist/index.js @@ -297,6 +297,7 @@ class TestReporter { this.workDirInput = core.getInput('working-directory', { required: false }); this.onlySummary = core.getInput('only-summary', { required: false }) === 'true'; this.token = core.getInput('token', { required: true }); + this.directoryMapping = core.getInput('directory-mapping', { required: true }); this.context = (0, github_utils_1.getCheckRunContext)(); this.octokit = github.getOctokit(this.token); if (this.listSuites !== 'all' && this.listSuites !== 'failed') { @@ -329,12 +330,14 @@ class TestReporter { const parseErrors = this.maxAnnotations > 0; const trackedFiles = parseErrors ? yield inputProvider.listTrackedFiles() : []; const workDir = this.artifact ? undefined : (0, path_utils_1.normalizeDirPath)(process.cwd(), true); + const [from, to] = this.directoryMapping.split(':'); if (parseErrors) core.info(`Found ${trackedFiles.length} files tracked by GitHub`); const options = { workDir, trackedFiles, - parseErrors + parseErrors, + directoryMapping: { from, to } }; core.info(`Using test report parser '${this.reporter}'`); const parser = this.getParser(this.reporter, options); @@ -1495,25 +1498,31 @@ class PytestJunitParser { const line = Number.parseInt(pos); if (path && Number.isFinite(line)) { return { - path: this.getAbsolutePath(path), + path: this.applyDirectoryMapping(this.getAbsolutePath(path)), line, message: lines[1] }; } return undefined; } + applyDirectoryMapping(path) { + if (this.options.directoryMapping && this.options.directoryMapping.from) { + return path.replace(this.options.directoryMapping.from, this.options.directoryMapping.to); + } + return path; + } getRelativePath(path) { path = (0, path_utils_1.normalizeFilePath)(path); const workDir = this.getWorkDir(path); if (workDir !== undefined && path.startsWith(workDir)) { - path = path.substring(workDir.length + 1); + path = path.substring(workDir.length); } return path; } getAbsolutePath(path) { const relativePath = this.getRelativePath(path); for (const file of this.options.trackedFiles) { - if (file.endsWith(relativePath)) { + if (relativePath.endsWith(file)) { return file; } } diff --git a/src/main.ts b/src/main.ts index 2e03d83..be3c65b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -44,6 +44,7 @@ class TestReporter { readonly workDirInput = core.getInput('working-directory', {required: false}) readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true' readonly token = core.getInput('token', {required: true}) + readonly directoryMapping = core.getInput('directory-mapping', {required: true}) readonly octokit: InstanceType readonly context = getCheckRunContext() @@ -94,13 +95,15 @@ class TestReporter { const parseErrors = this.maxAnnotations > 0 const trackedFiles = parseErrors ? await inputProvider.listTrackedFiles() : [] const workDir = this.artifact ? undefined : normalizeDirPath(process.cwd(), true) + const [from, to] = this.directoryMapping.split(':') if (parseErrors) core.info(`Found ${trackedFiles.length} files tracked by GitHub`) const options: ParseOptions = { workDir, trackedFiles, - parseErrors + parseErrors, + directoryMapping: {from, to} } core.info(`Using test report parser '${this.reporter}'`) diff --git a/src/parsers/pytest-junit/pytest-junit-parser.ts b/src/parsers/pytest-junit/pytest-junit-parser.ts index 980986b..3e78ceb 100644 --- a/src/parsers/pytest-junit/pytest-junit-parser.ts +++ b/src/parsers/pytest-junit/pytest-junit-parser.ts @@ -103,7 +103,7 @@ export class PytestJunitParser implements TestParser { if (path && Number.isFinite(line)) { return { - path: this.getAbsolutePath(path), + path: this.applyDirectoryMapping(this.getAbsolutePath(path)), line, message: lines[1] } @@ -112,11 +112,18 @@ export class PytestJunitParser implements TestParser { return undefined } + private applyDirectoryMapping(path: string): string { + if (this.options.directoryMapping && this.options.directoryMapping.from) { + return path.replace(this.options.directoryMapping.from, this.options.directoryMapping.to) + } + return path + } + private getRelativePath(path: string): string { path = normalizeFilePath(path) const workDir = this.getWorkDir(path) if (workDir !== undefined && path.startsWith(workDir)) { - path = path.substring(workDir.length + 1) + path = path.substring(workDir.length) } return path } diff --git a/src/test-parser.ts b/src/test-parser.ts index f134561..032f940 100644 --- a/src/test-parser.ts +++ b/src/test-parser.ts @@ -4,6 +4,7 @@ export interface ParseOptions { parseErrors: boolean workDir?: string trackedFiles: string[] + directoryMapping?: {from: string; to: string} } export interface TestParser {