Skip to content

Commit 90dd79c

Browse files
Copilotneilime
andcommitted
Use @actions/exec instead of child_process and add auto-detection
- Replace child_process with @actions/exec package - Use exec.getExecOutput for better error handling - Use node:path instead of path - Add auto-detection for lint report files (eslint-report.json, checkstyle.xml, etc.) - Add auto-detection for coverage files (cobertura-coverage.xml, lcov.info, etc.) - Update documentation to reflect auto-detection capabilities Co-authored-by: neilime <[email protected]>
1 parent ef0509d commit 90dd79c

File tree

3 files changed

+132
-53
lines changed

3 files changed

+132
-53
lines changed

actions/build/action.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,8 @@ runs:
110110
WORKING_DIRECTORY: ${{ inputs.working-directory }}
111111
with:
112112
script: |
113-
const { exec } = require('child_process');
114-
const { promisify } = require('util');
115-
const execAsync = promisify(exec);
116-
const path = require('path');
113+
const path = require('node:path');
114+
const exec = require('@actions/exec');
117115
118116
const buildCommands = process.env.BUILD_COMMANDS || '';
119117
const runScriptCommand = process.env.RUN_SCRIPT_COMMAND;
@@ -127,16 +125,14 @@ runs:
127125
core.info(`\n🏗️ Running build command: ${command}`);
128126
129127
try {
130-
const { stdout, stderr } = await execAsync(`${runScriptCommand} ${command}`, {
128+
const result = await exec.getExecOutput(runScriptCommand, [command], {
131129
cwd: path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory)
132130
});
133131
134-
if (stdout) core.info(stdout);
135-
if (stderr) core.warning(stderr);
132+
if (result.stdout) core.info(result.stdout);
133+
if (result.stderr) core.warning(result.stderr);
136134
} catch (error) {
137-
if (error.stdout) core.info(error.stdout);
138-
if (error.stderr) core.error(error.stderr);
139-
core.setFailed(`Build command "${command}" failed with exit code ${error.code || 1}`);
135+
core.setFailed(`Build command "${command}" failed: ${error.message}`);
140136
throw error;
141137
}
142138
}

actions/lint/action.yml

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ inputs:
2020
description: |
2121
Path to lint report file to process as GitHub annotations.
2222
Supports ESLint JSON and Checkstyle XML formats.
23-
If not specified, no report processing is done.
23+
If not specified, auto-detection will be attempted for common paths:
24+
- eslint-report.json, eslint.json
25+
- checkstyle-result.xml, checkstyle.xml
2426
required: false
2527
default: ""
2628
report-format:
@@ -67,10 +69,8 @@ runs:
6769
FAIL_ON_ERROR: ${{ inputs.fail-on-error }}
6870
with:
6971
script: |
70-
const { exec } = require('child_process');
71-
const { promisify } = require('util');
72-
const execAsync = promisify(exec);
73-
const path = require('path');
72+
const path = require('node:path');
73+
const exec = require('@actions/exec');
7474
7575
const workingDirectory = process.env.WORKING_DIRECTORY || '.';
7676
const runScriptCommand = process.env.RUN_SCRIPT_COMMAND;
@@ -79,42 +79,87 @@ runs:
7979
core.info('👕 Running lint...');
8080
8181
try {
82-
const { stdout, stderr } = await execAsync(`${runScriptCommand} lint`, {
83-
cwd: path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory)
82+
const result = await exec.getExecOutput(runScriptCommand, ['lint'], {
83+
cwd: path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory),
84+
ignoreReturnCode: true
8485
});
8586
86-
if (stdout) core.info(stdout);
87-
if (stderr) core.warning(stderr);
87+
if (result.stdout) core.info(result.stdout);
88+
if (result.stderr) core.warning(result.stderr);
8889
89-
core.setOutput('lint-exit-code', 0);
90-
} catch (error) {
91-
core.setOutput('lint-exit-code', error.code || 1);
92-
93-
if (error.stdout) core.info(error.stdout);
94-
if (error.stderr) core.error(error.stderr);
90+
core.setOutput('lint-exit-code', result.exitCode);
9591
96-
if (failOnError) {
97-
core.setFailed(`Linting failed with exit code ${error.code || 1}`);
98-
} else {
99-
core.warning(`Linting failed with exit code ${error.code || 1}`);
92+
if (result.exitCode !== 0 && failOnError) {
93+
core.setFailed(`Linting failed with exit code ${result.exitCode}`);
94+
} else if (result.exitCode !== 0) {
95+
core.warning(`Linting failed with exit code ${result.exitCode}`);
10096
}
97+
} catch (error) {
98+
core.setOutput('lint-exit-code', 1);
99+
core.setFailed(`Linting error: ${error.message}`);
101100
}
102101
# jscpd:ignore-end
102+
# Auto-detect report file if not specified
103+
- id: detect-report-file
104+
if: always() && inputs.report-file == ''
105+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
106+
env:
107+
WORKING_DIRECTORY: ${{ inputs.working-directory }}
108+
with:
109+
script: |
110+
const fs = require('node:fs');
111+
const path = require('node:path');
112+
113+
const workingDirectory = process.env.WORKING_DIRECTORY || '.';
114+
const workDir = path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory);
115+
116+
// Common lint report file paths
117+
const commonPaths = [
118+
'eslint-report.json',
119+
'eslint.json',
120+
'.eslint-report.json',
121+
'checkstyle-result.xml',
122+
'checkstyle.xml',
123+
'lint-results.xml',
124+
'reports/eslint-report.json',
125+
'reports/checkstyle.xml'
126+
];
127+
128+
for (const filePath of commonPaths) {
129+
const fullPath = path.join(workDir, filePath);
130+
if (fs.existsSync(fullPath)) {
131+
core.info(`Auto-detected lint report file: ${filePath}`);
132+
core.setOutput('report-file', filePath);
133+
134+
// Auto-detect format from extension
135+
if (filePath.endsWith('.json')) {
136+
core.setOutput('report-format', 'eslint');
137+
} else if (filePath.endsWith('.xml')) {
138+
core.setOutput('report-format', 'checkstyle');
139+
}
140+
return;
141+
}
142+
}
143+
144+
core.info('No lint report file auto-detected');
145+
core.setOutput('report-file', '');
146+
core.setOutput('report-format', '');
147+
103148
# Process ESLint report
104149
- name: 📊 Annotate ESLint results
105-
if: always() && inputs.report-file != '' && (inputs.report-format == 'eslint' || inputs.report-format == '')
150+
if: always() && (inputs.report-file != '' || steps.detect-report-file.outputs.report-file != '') && (inputs.report-format == 'eslint' || steps.detect-report-file.outputs.report-format == 'eslint' || (inputs.report-format == '' && steps.detect-report-file.outputs.report-format == ''))
106151
uses: ataylorme/eslint-annotate-action@d57a1193d4c59cbfbf2f1529e82e2f8e0da1498d # v3.0.0
107152
with:
108-
report-json: ${{ inputs.working-directory }}/${{ inputs.report-file }}
153+
report-json: ${{ inputs.working-directory }}/${{ inputs.report-file != '' && inputs.report-file || steps.detect-report-file.outputs.report-file }}
109154
fail-on-error: false
110155
fail-on-warning: false
111156

112157
# Process Checkstyle report
113158
- name: 📊 Annotate Checkstyle results
114-
if: always() && inputs.report-file != '' && inputs.report-format == 'checkstyle'
159+
if: always() && (inputs.report-file != '' || steps.detect-report-file.outputs.report-file != '') && (inputs.report-format == 'checkstyle' || steps.detect-report-file.outputs.report-format == 'checkstyle')
115160
uses: lcollins/checkstyle-github-action@8e0abb97e71a72c2cf9d6f0619e38002cb6e36c9 # v2.0.0
116161
with:
117-
path: ${{ inputs.working-directory }}/${{ inputs.report-file }}
162+
path: ${{ inputs.working-directory }}/${{ inputs.report-file != '' && inputs.report-file || steps.detect-report-file.outputs.report-file }}
118163

119164
- shell: bash
120165
if: always() && steps.run-lint.outputs.lint-exit-code != '0' && inputs.fail-on-error == 'true'

actions/test/action.yml

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ inputs:
2929
Path to coverage files for reporting.
3030
Supports multiple formats (Cobertura, OpenCover, lcov, etc.).
3131
Can be a single file or multiple files separated by semicolons.
32+
If not specified, auto-detection will be attempted for common paths:
33+
- coverage/cobertura-coverage.xml, coverage/coverage.xml
34+
- coverage/lcov.info
35+
- coverage/clover.xml
3236
required: false
33-
default: "coverage/cobertura-coverage.xml"
37+
default: ""
3438
codecov-token:
3539
description: |
3640
Codecov token for private repositories.
@@ -84,10 +88,8 @@ runs:
8488
FAIL_ON_ERROR: ${{ inputs.fail-on-error }}
8589
with:
8690
script: |
87-
const { exec } = require('child_process');
88-
const { promisify } = require('util');
89-
const execAsync = promisify(exec);
90-
const path = require('path');
91+
const path = require('node:path');
92+
const exec = require('@actions/exec');
9193
9294
const workingDirectory = process.env.WORKING_DIRECTORY || '.';
9395
const runScriptCommand = process.env.RUN_SCRIPT_COMMAND;
@@ -96,26 +98,25 @@ runs:
9698
core.info('🧪 Running tests...');
9799
98100
try {
99-
const { stdout, stderr } = await execAsync(`${runScriptCommand} test:ci`, {
101+
const result = await exec.getExecOutput(runScriptCommand, ['test:ci'], {
100102
cwd: path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory),
101-
env: { ...process.env, CI: 'true' }
103+
env: { ...process.env, CI: 'true' },
104+
ignoreReturnCode: true
102105
});
103106
104-
if (stdout) core.info(stdout);
105-
if (stderr) core.warning(stderr);
106-
107-
core.setOutput('test-exit-code', 0);
108-
} catch (error) {
109-
core.setOutput('test-exit-code', error.code || 1);
107+
if (result.stdout) core.info(result.stdout);
108+
if (result.stderr) core.warning(result.stderr);
110109
111-
if (error.stdout) core.info(error.stdout);
112-
if (error.stderr) core.error(error.stderr);
110+
core.setOutput('test-exit-code', result.exitCode);
113111
114-
if (failOnError) {
115-
core.setFailed(`Tests failed with exit code ${error.code || 1}`);
116-
} else {
117-
core.warning(`Tests failed with exit code ${error.code || 1}`);
112+
if (result.exitCode !== 0 && failOnError) {
113+
core.setFailed(`Tests failed with exit code ${result.exitCode}`);
114+
} else if (result.exitCode !== 0) {
115+
core.warning(`Tests failed with exit code ${result.exitCode}`);
118116
}
117+
} catch (error) {
118+
core.setOutput('test-exit-code', 1);
119+
core.setFailed(`Test execution error: ${error.message}`);
119120
}
120121
# jscpd:ignore-end
121122
# Install dependencies for codecov in container mode
@@ -134,6 +135,43 @@ runs:
134135
fi
135136
done
136137
138+
# Auto-detect coverage files if not specified
139+
- id: detect-coverage-files
140+
if: always() && inputs.coverage == 'github' && inputs.coverage-files == ''
141+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
142+
env:
143+
WORKING_DIRECTORY: ${{ inputs.working-directory }}
144+
with:
145+
script: |
146+
const fs = require('node:fs');
147+
const path = require('node:path');
148+
149+
const workingDirectory = process.env.WORKING_DIRECTORY || '.';
150+
const workDir = path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory);
151+
152+
// Common coverage file paths
153+
const commonPaths = [
154+
'coverage/cobertura-coverage.xml',
155+
'coverage/coverage.xml',
156+
'coverage/lcov.info',
157+
'coverage/clover.xml',
158+
'coverage/coverage-final.json',
159+
'test-results/coverage.xml',
160+
'test-results/cobertura-coverage.xml'
161+
];
162+
163+
for (const filePath of commonPaths) {
164+
const fullPath = path.join(workDir, filePath);
165+
if (fs.existsSync(fullPath)) {
166+
core.info(`Auto-detected coverage file: ${filePath}`);
167+
core.setOutput('coverage-files', filePath);
168+
return;
169+
}
170+
}
171+
172+
core.warning('No coverage file auto-detected');
173+
core.setOutput('coverage-files', 'coverage/cobertura-coverage.xml');
174+
137175
# Upload to Codecov
138176
- name: 📊 Upload coverage to Codecov
139177
if: always() && inputs.coverage == 'codecov'
@@ -150,7 +188,7 @@ runs:
150188
if: always() && inputs.coverage == 'github' && github.event_name == 'pull_request'
151189
uses: danielpalme/ReportGenerator-GitHub-Action@d78d7a99ab2e53f4fa9e37c558feb9cd6a7a1c70 # v5.4.3
152190
with:
153-
reports: ${{ inputs.coverage-files }}
191+
reports: ${{ inputs.coverage-files != '' && inputs.coverage-files || steps.detect-coverage-files.outputs.coverage-files }}
154192
targetdir: coveragereport
155193
reporttypes: MarkdownSummaryGithub
156194
sourcedirs: ${{ inputs.working-directory }}

0 commit comments

Comments
 (0)