diff --git a/.github/linters/actionlint.yml b/.github/linters/actionlint.yml
index f516136..c7ba559 100644
--- a/.github/linters/actionlint.yml
+++ b/.github/linters/actionlint.yml
@@ -8,3 +8,4 @@ paths:
- '"env" section must be mapping node but got scalar node'
- '"ports" section must be sequence node but got scalar node'
- '"volumes" section must be sequence node but got scalar node'
+ - '"runs-on" section is alias node but mapping node is expected'
diff --git a/.github/workflows/__test-workflow-continuous-integration.yml b/.github/workflows/__test-workflow-continuous-integration.yml
index d26cd59..014f15a 100644
--- a/.github/workflows/__test-workflow-continuous-integration.yml
+++ b/.github/workflows/__test-workflow-continuous-integration.yml
@@ -11,6 +11,7 @@ jobs:
uses: ./.github/workflows/continuous-integration.yml
permissions:
contents: read
+ packages: read
pull-requests: write
security-events: write
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
@@ -41,6 +42,7 @@ jobs:
uses: ./.github/workflows/continuous-integration.yml
permissions:
contents: read
+ packages: read
pull-requests: write
security-events: write
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
@@ -82,6 +84,7 @@ jobs:
needs: arrange-with-container
permissions:
contents: read
+ packages: read
pull-requests: write
security-events: write
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
@@ -116,6 +119,7 @@ jobs:
needs: arrange-with-container
permissions:
contents: read
+ packages: read
pull-requests: write
security-events: write
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
diff --git a/.github/workflows/continuous-integration.md b/.github/workflows/continuous-integration.md
index 0fb99cd..1395033 100644
--- a/.github/workflows/continuous-integration.md
+++ b/.github/workflows/continuous-integration.md
@@ -3,7 +3,7 @@
# GitHub Reusable Workflow: Node.js Continuous Integration
-

+
---
@@ -34,6 +34,7 @@ Workflow to performs continuous integration steps agains a Node.js project:
- **`contents`**: `read`
- **`id-token`**: `write`
+- **`packages`**: `read`
- **`pull-requests`**: `write`
- **`security-events`**: `write`
@@ -52,7 +53,7 @@ on:
permissions: {}
jobs:
continuous-integration:
- uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@ce2bb8274a37c1219be2bcae2a1b2528c2c72957 # 0.19.0
+ uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@2b8788166256f66b42262e273b4be22a3fc162e8 # copilot/configure-lint-and-test-commands
permissions: {}
secrets:
# Secrets to be used during the build step.
@@ -67,6 +68,10 @@ jobs:
# Used when the container image is hosted in a private registry.
# See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container#defining-credentials-for-a-container-registry.
container-password: ""
+
+ # GitHub token to use for authentication.
+ # Defaults to `GITHUB_TOKEN` if not provided.
+ github-token: ""
with:
# JSON array of runner(s) to use.
# See https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job.
@@ -113,11 +118,16 @@ jobs:
# Default: `true`
lint: "true"
- # Code QL analysis language. See .
+ # Code QL analysis language.
+ # See https://github.com/github/codeql-action.
+ #
# Default: `typescript`
code-ql: typescript
- # Enable dependency review scan. See .
+ # Enable dependency review scan.
+ # Works with public repositories and private repositories with a GitHub Advanced Security license.
+ # See https://github.com/actions/dependency-review-action.
+ #
# Default: `true`
dependency-review: true
@@ -136,11 +146,13 @@ jobs:
# Accepts either a string (container image name) or a JSON object with container options.
#
# String format (simple):
+ #
# ```yml
# container: "node:18"
# ```
#
# JSON object format (advanced):
+ #
# ```json
# {
# "image": "node:18",
@@ -156,9 +168,16 @@ jobs:
# }
# ```
#
- # Supported properties: image (required), env (object), options (string), ports (array), volumes (array), credentials (object with username).
+ # Supported properties:
#
- # See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container
+ # - `image` (required)
+ # - `env` (object)
+ # - `options` (string)
+ # - `ports` (array)
+ # - `volumes` (array)
+ # - `credentials` (object with `username`).
+ #
+ # See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container.
#
# When specified, steps will execute inside this container instead of checking out code.
# The container should have the project code and dependencies pre-installed.
@@ -191,8 +210,11 @@ jobs:
| **`lint`** | Whether to enable linting. | **false** | **string** | `true` |
| | Set to `null` or empty to disable. | | | |
| | Accepts a JSON object for lint options. See [lint action](../actions/lint/README.md). | | | |
-| **`code-ql`** | Code QL analysis language. See . | **false** | **string** | `typescript` |
-| **`dependency-review`** | Enable dependency review scan. See . | **false** | **boolean** | `true` |
+| **`code-ql`** | Code QL analysis language. | **false** | **string** | `typescript` |
+| | See . | | | |
+| **`dependency-review`** | Enable dependency review scan. | **false** | **boolean** | `true` |
+| | Works with public repositories and private repositories with a GitHub Advanced Security license. | | | |
+| | See . | | | |
| **`test`** | Whether to enable testing. | **false** | **string** | `true` |
| | Set to `null` or empty to disable. | | | |
| | Accepts a JSON object for test options. See [test action](../actions/test/README.md). | | | |
@@ -201,12 +223,21 @@ jobs:
| | Accepts either a string (container image name) or a JSON object with container options. | | | |
| | | | | |
| | String format (simple): | | | |
+| | | | | |
| | container: "node:18"
| | | |
| | JSON object format (advanced): | | | |
+| | | | | |
| | {
"image": "node:18",
"env": {
"NODE_ENV": "production"
},
"options": "--cpus 2",
"ports": [8080, 3000],
"volumes": ["/tmp:/tmp", "/cache:/cache"],
"credentials": {
"username": "myusername"
}
} | | | |
-| | Supported properties: image (required), env (object), options (string), ports (array), volumes (array), credentials (object with username). | | | |
+| | Supported properties: | | | |
+| | | | | |
+| | - `image` (required) | | | |
+| | - `env` (object) | | | |
+| | - `options` (string) | | | |
+| | - `ports` (array) | | | |
+| | - `volumes` (array) | | | |
+| | - `credentials` (object with `username`). | | | |
| | | | | |
-| | See | | | |
+| | See . | | | |
| | | | | |
| | When specified, steps will execute inside this container instead of checking out code. | | | |
| | The container should have the project code and dependencies pre-installed. | | | |
@@ -287,6 +318,8 @@ When specified, steps will execute inside this container instead of checking out
| **`container-password`** | Password for container registry authentication, if required. | **false** |
| | Used when the container image is hosted in a private registry. | |
| | See . | |
+| **`github-token`** | GitHub token to use for authentication. | **false** |
+| | Defaults to `GITHUB_TOKEN` if not provided. | |
@@ -317,7 +350,7 @@ on:
jobs:
continuous-integration:
- uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@ce2bb8274a37c1219be2bcae2a1b2528c2c72957 # 0.19.0
+ uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@2b8788166256f66b42262e273b4be22a3fc162e8 # copilot/configure-lint-and-test-commands
permissions:
id-token: write
security-events: write
@@ -383,7 +416,7 @@ jobs:
# Run CI checks inside the Docker container
continuous-integration:
needs: build-image
- uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@ce2bb8274a37c1219be2bcae2a1b2528c2c72957 # 0.19.0
+ uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@2b8788166256f66b42262e273b4be22a3fc162e8 # copilot/configure-lint-and-test-commands
permissions:
id-token: write
security-events: write
@@ -413,7 +446,7 @@ on:
jobs:
continuous-integration:
- uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@ce2bb8274a37c1219be2bcae2a1b2528c2c72957 # 0.19.0
+ uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@2b8788166256f66b42262e273b4be22a3fc162e8 # copilot/configure-lint-and-test-commands
permissions:
id-token: write
security-events: write
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 1c95f75..d1e65d8 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -60,12 +60,17 @@ on:
required: false
default: "true"
code-ql:
- description: "Code QL analysis language. See ."
+ description: |
+ Code QL analysis language.
+ See https://github.com/github/codeql-action.
type: string
required: false
default: "typescript"
dependency-review:
- description: "Enable dependency review scan. See ."
+ description: |
+ Enable dependency review scan.
+ Works with public repositories and private repositories with a GitHub Advanced Security license.
+ See https://github.com/actions/dependency-review-action.
type: boolean
required: false
default: true
@@ -88,11 +93,13 @@ on:
Accepts either a string (container image name) or a JSON object with container options.
String format (simple):
+
```yml
container: "node:18"
```
JSON object format (advanced):
+
```json
{
"image": "node:18",
@@ -108,9 +115,16 @@ on:
}
```
- Supported properties: image (required), env (object), options (string), ports (array), volumes (array), credentials (object with username).
+ Supported properties:
- See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container
+ - `image` (required)
+ - `env` (object)
+ - `options` (string)
+ - `ports` (array)
+ - `volumes` (array)
+ - `credentials` (object with `username`).
+
+ See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container.
When specified, steps will execute inside this container instead of checking out code.
The container should have the project code and dependencies pre-installed.
@@ -133,6 +147,11 @@ on:
Used when the container image is hosted in a private registry.
See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container#defining-credentials-for-a-container-registry.
required: false
+ github-token:
+ description: |
+ GitHub token to use for authentication.
+ Defaults to `GITHUB_TOKEN` if not provided.
+ required: false
outputs:
build-artifact-id:
description: "ID of the build artifact) uploaded during the build step."
@@ -143,7 +162,7 @@ permissions: {}
jobs:
prepare:
name: ๐ฆ Prepare configuration
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
+ runs-on: &ci-runner ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
permissions: {}
outputs:
container-image: ${{ steps.parse.outputs.container-image }}
@@ -177,8 +196,8 @@ jobs:
try {
const parsedContainer = JSON.parse(containerInput);
core.debug(`Parsed container input as JSON: ${JSON.stringify(parsedContainer)}`);
- container = {
- ...container,
+ container = {
+ ...container,
...parsedContainer,
options: `${container.options} ${parsedContainer.options || ''}`.trim()
};
@@ -228,7 +247,7 @@ jobs:
if: inputs.checks == true && inputs.code-ql != ''
permissions:
security-events: write
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
+ runs-on: *ci-runner
steps:
- uses: hoverkraft-tech/ci-github-common/actions/checkout@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
- uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
@@ -241,32 +260,35 @@ jobs:
if: github.event_name == 'pull_request' && inputs.checks == true && inputs.dependency-review
permissions:
contents: read
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
+ runs-on: *ci-runner
steps:
- uses: hoverkraft-tech/ci-github-common/actions/checkout@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
- uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2
setup:
name: โ๏ธ Setup
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
- needs: prepare
- container: &container-setup
+ runs-on: *ci-runner
+ needs:
+ - prepare
+ permissions:
+ contents: read
+ packages: read
+ # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
+ id-token: write
+ container: &ci-container
image: ${{ needs.prepare.outputs.container-image || '' }}
env: ${{ fromJSON(needs.prepare.outputs.container-env || '{}') }}
options: ${{ needs.prepare.outputs.container-options || ' ' }}
ports: ${{ fromJSON(needs.prepare.outputs.container-ports || '[]') }}
volumes: ${{ fromJSON(needs.prepare.outputs.container-volumes || '[]') }}
credentials: ${{ fromJSON(needs.prepare.outputs.container-username && format('{{"username":{0},"password":{1}}}',toJSON(needs.prepare.outputs.container-username),toJSON(secrets.container-password)) || '{}') }}
- permissions:
- contents: read
- # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
- id-token: write
outputs:
build-env: ${{ steps.build-variables.outputs.env }}
build-commands: ${{ steps.build-variables.outputs.commands }}
build-artifact: ${{ steps.build-variables.outputs.artifact }}
steps:
- - if: needs.prepare.outputs.container-image == null
+ - name: Checkout repository
+ if: inputs.container == ''
uses: hoverkraft-tech/ci-github-common/actions/checkout@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
- id: build-variables
@@ -369,21 +391,21 @@ jobs:
core.setOutput('env', JSON.stringify(env));
lint:
- name: ๐ Lint
if: inputs.checks == true && inputs.lint
+ name: ๐ Lint
+ runs-on: *ci-runner
+ container: *ci-container
needs:
- prepare
- setup
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
- container: *container-setup
- # jscpd:ignore-start
permissions:
contents: read
+ packages: read
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
id-token: write
steps:
- uses: hoverkraft-tech/ci-github-common/actions/checkout@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
- if: needs.prepare.outputs.container-image == null
+ if: inputs.container == ''
- id: oidc
uses: ChristopherHX/oidc@73eee1ff03fdfce10eda179f617131532209edbd # v3
@@ -397,7 +419,7 @@ jobs:
- run: |
if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi
if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi
- # jscpd:ignore-end
+
- id: preparel-lint-options
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
@@ -417,29 +439,35 @@ jobs:
}
}
- - uses: ./self-workflow/actions/lint
+ core.setOutput('command', lintOptions.command || 'lint:ci');
+ core.setOutput('report-file', lintOptions['report-file'] || '');
+
+ - name: Run lint
+ uses: ./self-workflow/actions/lint
with:
working-directory: ${{ inputs.working-directory }}
- container: ${{ needs.prepare.outputs.container-image && 'true' || 'false' }}
+ container: ${{ inputs.container != '' && 'true' || 'false' }}
+ command: ${{ steps.preparel-lint-options.outputs.command }}
+ report-file: ${{ steps.preparel-lint-options.outputs.report-file }}
build:
- name: ๐๏ธ Build
if: inputs.checks == true
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
- container: *container-setup
- # jscpd:ignore-start
+ name: ๐๏ธ Build
+ runs-on: *ci-runner
+ container: *ci-container
needs:
- prepare
- setup
permissions:
contents: read
+ packages: read
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
id-token: write
outputs:
artifact-id: ${{ steps.build.outputs.artifact-id }}
steps:
- uses: hoverkraft-tech/ci-github-common/actions/checkout@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
- if: needs.setup.outputs.build-commands && needs.prepare.outputs.container-image == null
+ if: needs.setup.outputs.build-commands && inputs.container == ''
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
- id: oidc
@@ -457,23 +485,23 @@ jobs:
run: |
if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi
if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi
- # jscpd:ignore-end
+
- id: build
if: needs.setup.outputs.build-commands
uses: ./self-workflow/actions/build
with:
+ container: ${{ inputs.container != '' && 'true' || 'false' }}
working-directory: ${{ inputs.working-directory }}
+ build-secrets: ${{ secrets.build-secrets }}
build-commands: ${{ needs.setup.outputs.build-commands }}
build-env: ${{ needs.setup.outputs.build-env }}
- build-secrets: ${{ secrets.build-secrets }}
build-artifact: ${{ needs.setup.outputs.build-artifact }}
- container: ${{ needs.prepare.outputs.container-image && 'true' || 'false' }}
test:
- name: ๐งช Test
if: inputs.checks == true && inputs.test
- runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
- container: *container-setup
+ name: ๐งช Test
+ runs-on: *ci-runner
+ container: *ci-container
needs:
- prepare
- setup
@@ -481,13 +509,14 @@ jobs:
permissions:
contents: read
pull-requests: write
+ packages: read
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
id-token: write
steps:
- uses: hoverkraft-tech/ci-github-common/actions/checkout@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
- if: needs.prepare.outputs.container-image == null
+ if: inputs.container == ''
- - if: needs.build.outputs.artifact-id && needs.prepare.outputs.container-image == null
+ - if: needs.build.outputs.artifact-id && inputs.container == ''
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
artifact-ids: ${{ needs.build.outputs.artifact-id }}
@@ -530,13 +559,15 @@ jobs:
testOptions.coverage = 'github';
}
core.setOutput('coverage', testOptions.coverage );
-
core.setOutput('coverage-files', testOptions['coverage-files'] || '');
+ core.setOutput('command', testOptions.command || 'test:ci');
- - uses: ./self-workflow/actions/test
+ - name: Run tests
+ uses: ./self-workflow/actions/test
with:
working-directory: ${{ inputs.working-directory }}
- container: ${{ needs.prepare.outputs.container-image && 'true' || 'false' }}
+ container: ${{ inputs.container != '' && 'true' || 'false' }}
+ command: ${{ steps.prepare-test-options.outputs.command }}
coverage: ${{ steps.prepare-test-options.outputs.coverage }}
coverage-files: ${{ steps.prepare-test-options.outputs.coverage-files }}
- github-token: ${{ github.token }}
+ github-token: ${{ secrets.github-token || github.token }}
diff --git a/README.md b/README.md
index f071b42..d7c7848 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,8 @@ _Actions for continuous integration steps: build, lint, and test._
#### - [Test](actions/test/README.md)
+#### - [Rewrite Report Paths](actions/rewrite-report-paths/README.md)
+
### Dependencies
_Actions dedicated to caching and validating Node.js dependencies._
diff --git a/actions/build/action.yml b/actions/build/action.yml
index 5b92425..e4c0ebf 100644
--- a/actions/build/action.yml
+++ b/actions/build/action.yml
@@ -119,12 +119,12 @@ runs:
for (const command of commands) {
core.info(`Running build command: ${command}`);
-
+
try {
const result = await exec.getExecOutput(runScriptCommand, [command], {
cwd: require('path').resolve(process.env.GITHUB_WORKSPACE, workingDirectory)
});
-
+
if (result.stdout) {
core.info(result.stdout);
}
diff --git a/actions/get-package-manager/action.yml b/actions/get-package-manager/action.yml
index 3165a01..c47d607 100644
--- a/actions/get-package-manager/action.yml
+++ b/actions/get-package-manager/action.yml
@@ -44,6 +44,7 @@ runs:
if (!path.isAbsolute(workingDirectory)) {
workingDirectory = path.join(process.env.GITHUB_WORKSPACE, workingDirectory);
}
+ core.debug(`Resolved working directory: ${workingDirectory}`);
if (!fs.existsSync(workingDirectory)) {
core.setFailed(`The specified working directory does not exist: ${workingDirectory}`);
@@ -91,6 +92,8 @@ runs:
}
let relativeWorkingDirectory = path.relative(process.env.GITHUB_WORKSPACE, workingDirectory) || '.';
+ core.debug(`Relative working directory to GITHUB_WORKSPACE (${process.env.GITHUB_WORKSPACE}): ${relativeWorkingDirectory}`);
+
let cacheDependencyPathPrefix = relativeWorkingDirectory;
if (relativeWorkingDirectory.startsWith('../')) {
@@ -115,6 +118,8 @@ runs:
}
}
+ core.debug(`Cache dependency path prefix: ${cacheDependencyPathPrefix}`);
+
const packageManagerConfig = {
yarn: {
cacheDependencyPath: cacheDependencyPathPrefix ? `${cacheDependencyPathPrefix}/**/yarn.lock` : '',
diff --git a/actions/lint/README.md b/actions/lint/README.md
index 4216595..e1453a1 100644
--- a/actions/lint/README.md
+++ b/actions/lint/README.md
@@ -42,6 +42,13 @@ Action to lint Node.js projects with support for pull request reporting and anno
# Default: `false`
container: "false"
+ # NPM/package manager script command to run for linting.
+ # This should be a script defined in your package.json.
+ # The command should generate lint report files in a standard format (ESLint JSON or Checkstyle XML).
+ #
+ # Default: `lint:ci`
+ command: "lint:ci"
+
# Path to lint report file to process as GitHub annotations.
# Supports ESLint JSON and Checkstyle XML formats.
# If not specified, auto-detection will be attempted for common paths:
@@ -60,6 +67,9 @@ Action to lint Node.js projects with support for pull request reporting and anno
| **`working-directory`** | Working directory where lint commands are executed. | **false** | `.` |
| | Can be absolute or relative to the repository root. | | |
| **`container`** | Whether running in container mode (skips checkout and node setup) | **false** | `false` |
+| **`command`** | NPM/package manager script command to run for linting. | **false** | `lint:ci` |
+| | This should be a script defined in your package.json. | | |
+| | The command should generate lint report files in a standard format. | | |
| **`report-file`** | Path to lint report file to process as GitHub annotations. | **false** | - |
| | Supports ESLint JSON and Checkstyle XML formats. | | |
| | If not specified, auto-detection will be attempted for common paths: | | |
diff --git a/actions/lint/action.yml b/actions/lint/action.yml
index 6cd4a4e..406524a 100644
--- a/actions/lint/action.yml
+++ b/actions/lint/action.yml
@@ -16,13 +16,18 @@ inputs:
description: "Whether running in container mode (skips checkout and node setup)"
required: false
default: "false"
+ command:
+ description: |
+ NPM/package manager script command to run for linting.
+ This should be a script defined in your package.json.
+ The command should generate lint report files in a standard format (ESLint JSON or Checkstyle XML).
+ required: false
+ default: "lint:ci"
report-file:
description: |
- Path to lint report file to process as GitHub annotations.
- Supports ESLint JSON and Checkstyle XML formats.
- If not specified, auto-detection will be attempted for common paths:
- - eslint-report.json, eslint.json
- - checkstyle-result.xml, checkstyle.xml
+ Optional lint report path forwarded to the [parse-ci-reports](https://hoverkraft-tech/ci-github-common/actions/parse-ci-reports) action.
+ Provide an absolute path or one relative to the working directory.
+ When omitted, the action falls back to "auto:lint" detection (ESLint JSON / Checkstyle XML).
required: false
default: ""
@@ -53,24 +58,26 @@ runs:
env:
RUN_LINT_COMMAND: ${{ inputs.container == 'true' && steps.get-package-manager.outputs.run-script-command || steps.setup-node.outputs.run-script-command }}
WORKING_DIRECTORY: ${{ inputs.working-directory }}
+ LINT_COMMAND: ${{ inputs.command }}
with:
script: |
const workingDirectory = process.env.WORKING_DIRECTORY || '.';
const runScriptCommand = process.env.RUN_LINT_COMMAND;
+ const lintCommand = process.env.LINT_COMMAND || 'lint:ci';
- core.info('๐ Running lint...');
+ core.info(`๐ Running lint command: ${lintCommand}...`);
try {
- const result = await exec.getExecOutput(runScriptCommand, ['lint'], {
+ const result = await exec.getExecOutput(runScriptCommand, [lintCommand], {
cwd: require('path').resolve(process.env.GITHUB_WORKSPACE, workingDirectory),
ignoreReturnCode: true
});
-
+
if (result.stdout) core.info(result.stdout);
if (result.stderr) core.warning(result.stderr);
-
+
core.setOutput('lint-exit-code', result.exitCode);
-
+
if (result.exitCode !== 0) {
core.setFailed(`Linting failed with exit code ${result.exitCode}`);
}
@@ -79,85 +86,13 @@ runs:
core.setFailed(`Linting error: ${error.message}`);
}
- # Auto-detect report file if not specified
- - id: detect-report-file
+ - name: ๐ Parse lint reports
if: always()
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
- env:
- REPORT_FILE: ${{ inputs.report-file }}
- WORKING_DIRECTORY: ${{ inputs.working-directory }}
- with:
- script: |
- const path = require('node:path');
- const fs = require('node:fs');
-
- const workingDirectory = process.env.WORKING_DIRECTORY || '.';
- const workDir = path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory);
-
- const autoDetectReportFormat = (filePath) => {
- if (filePath.endsWith('.json')) {
- return 'eslint';
- } else if (filePath.endsWith('.xml')) {
- return 'checkstyle';
- }
- return core.setFailed(`Unable to auto-detect report format from file extension: ${filePath}`);
- };
-
- if (process.env.REPORT_FILE && process.env.REPORT_FILE.trim() !== '') {
- const reportFilePath = path.join(workDir, process.env.REPORT_FILE.trim());
-
- if (!fs.existsSync(reportFilePath)) {
- core.setFailed(`Specified report file does not exist: ${process.env.REPORT_FILE.trim()}`);
- return;
- }
- core.info(`Report file specified: ${reportFilePath}`);
- core.setOutput('report-file', reportFilePath);
- core.setOutput('report-format', autoDetectReportFormat(reportFilePath));
-
- return;
- }
-
- // Common lint report file paths
- const commonPaths = [
- 'eslint-report.json',
- 'eslint.json',
- '.eslint-report.json',
- 'checkstyle-result.xml',
- 'checkstyle.xml',
- 'lint-results.xml',
- 'reports/eslint-report.json',
- 'reports/checkstyle.xml'
- ];
-
- for (const filePath of commonPaths) {
- const fullPath = path.join(workDir, filePath);
- if (fs.existsSync(fullPath)) {
- core.info(`Auto-detected lint report file: ${fullPath}`);
- core.setOutput('report-file', fullPath);
-
- // Auto-detect format from extension
- core.setOutput('report-format', autoDetectReportFormat(fullPath));
- return;
- }
- }
-
- core.info('No lint report file auto-detected');
-
- # Process ESLint report
- - name: ๐ Annotate ESLint results
- if: always() && steps.detect-report-file.outputs.report-format == 'eslint'
- uses: ataylorme/eslint-annotate-action@d57a1193d4c59cbfbf3f86c271f42612f9dbd9e9 # v3.0.0
- with:
- report-json: ${{ steps.detect-report-file.outputs.report-file }}
- fail-on-error: false
- fail-on-warning: false
-
- # Process Checkstyle report
- - name: ๐ Annotate Checkstyle results
- if: always() && steps.detect-report-file.outputs.report-format == 'checkstyle'
- uses: lcollins/checkstyle-github-action@658deddef713a1132a9c59b64d754221b66a6f27 # v3.1.0
+ uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
with:
- path: ${{ steps.detect-report-file.outputs.report-file }}
+ report-paths: ${{ inputs.report-file || 'auto:lint' }}
+ report-name: "Lint Results"
+ output-format: "annotations,summary"
# FIXME: workaround until will be merged: https://github.com/actions/runner/pull/1684
- shell: bash
diff --git a/actions/rewrite-report-paths/README.md b/actions/rewrite-report-paths/README.md
new file mode 100644
index 0000000..463638f
--- /dev/null
+++ b/actions/rewrite-report-paths/README.md
@@ -0,0 +1,175 @@
+
+
+#  GitHub Action: Rewrite Report Paths
+
+
+

+
+
+---
+
+
+
+
+[](https://github.com/marketplace/actions/rewrite-report-paths)
+[](https://github.com/hoverkraft-tech/ci-github-nodejs/releases)
+[](http://choosealicense.com/licenses/mit/)
+[](https://img.shields.io/github/stars/hoverkraft-tech/ci-github-nodejs?style=social)
+[](https://github.com/hoverkraft-tech/ci-github-nodejs/blob/main/CONTRIBUTING.md)
+
+
+
+
+## Overview
+
+Rewrites file paths in report files to match repository paths when running in containers.
+
+When running tests or linting in Docker containers, the file paths in generated reports (coverage, lint results, etc.) often reference the container's internal paths (e.g., `/app/src/file.js`). This action rewrites those paths to match the actual repository structure, ensuring that GitHub annotations and coverage reports correctly reference the source files.
+
+
+
+
+## Usage
+
+```yaml
+- uses: hoverkraft-tech/ci-github-nodejs/actions/rewrite-report-paths@main
+ with:
+ # Path or glob pattern for report files to process.
+ # Supports multiple files separated by newlines.
+ # Common patterns: coverage/**, reports/**, **/*.xml, **/*.json
+ #
+ # Required: true
+ report-files: |
+ coverage/cobertura-coverage.xml
+ reports/eslint.json
+
+ # Source root path in the container that should be replaced.
+ # If not specified, will attempt to auto-detect from file paths.
+ # Common values: /app, /workspace, /usr/src/app
+ #
+ # Default: "" (auto-detect)
+ source-root: "/app"
+
+ # Target root path in the repository.
+ # Typically this is the GITHUB_WORKSPACE or a subdirectory.
+ #
+ # Default: GITHUB_WORKSPACE
+ target-root: ""
+
+ # Working directory where report files are located.
+ # Can be absolute or relative to the repository root.
+ #
+ # Default: `.`
+ working-directory: .
+```
+
+
+
+
+## Inputs
+
+| **Input** | **Description** | **Required** | **Default** |
+| ----------------------- | ----------------------------------------------------------------------- | ------------ | ----------- |
+| **`report-files`** | Path or glob pattern for report files to process. | **true** | - |
+| | Supports multiple files separated by newlines. | | |
+| | Common patterns: coverage/\*\*, reports/\*\*, \*\*/\*.xml, \*\*/\*.json | | |
+| **`source-root`** | Source root path in the container that should be replaced. | **false** | - |
+| | If not specified, will attempt to auto-detect from file paths. | | |
+| **`target-root`** | Target root path in the repository. | **false** | - |
+| | Typically this is the GITHUB_WORKSPACE or a subdirectory. | | |
+| **`working-directory`** | Working directory where report files are located. | **false** | `.` |
+| | Can be absolute or relative to the repository root. | | |
+
+
+
+
+
+
+## Outputs
+
+| **Output** | **Description** |
+| --------------------- | ------------------------------------------ |
+| **`files-processed`** | Number of report files that were processed |
+| **`paths-replaced`** | Total number of paths that were rewritten |
+
+
+
+
+## Examples
+
+### Basic Usage with Auto-Detection
+
+```yaml
+- name: Rewrite coverage paths
+ uses: hoverkraft-tech/ci-github-nodejs/actions/rewrite-report-paths@main
+ with:
+ report-files: |
+ coverage/cobertura-coverage.xml
+ coverage/lcov.info
+```
+
+### Explicit Source Root
+
+```yaml
+- name: Rewrite report paths
+ uses: hoverkraft-tech/ci-github-nodejs/actions/rewrite-report-paths@main
+ with:
+ report-files: |
+ coverage/**/*.xml
+ reports/**/*.json
+ source-root: "/app"
+ target-root: ${{ github.workspace }}
+```
+
+### Multiple Report Types
+
+```yaml
+- name: Rewrite all report paths
+ uses: hoverkraft-tech/ci-github-nodejs/actions/rewrite-report-paths@main
+ with:
+ report-files: |
+ coverage/cobertura-coverage.xml
+ reports/eslint.json
+ test-results/junit.xml
+ source-root: "/workspace"
+```
+
+
+
+
+
+
+
+## Contributing
+
+Contributions are welcome! Please see the [contributing guidelines](https://github.com/hoverkraft-tech/ci-github-nodejs/blob/main/CONTRIBUTING.md) for more details.
+
+
+
+
+
+
+## License
+
+This project is licensed under the MIT License.
+
+SPDX-License-Identifier: MIT
+
+Copyright ยฉ 2025 hoverkraft
+
+For more details, see the [license](http://choosealicense.com/licenses/mit/).
+
+
+
+
+---
+
+This documentation was automatically generated by [CI Dokumentor](https://github.com/hoverkraft-tech/ci-dokumentor).
+
+
+
+
diff --git a/actions/rewrite-report-paths/action.yml b/actions/rewrite-report-paths/action.yml
new file mode 100644
index 0000000..064ec36
--- /dev/null
+++ b/actions/rewrite-report-paths/action.yml
@@ -0,0 +1,151 @@
+name: "Rewrite Report Paths"
+description: "Rewrites file paths in report files to match repository paths when running in containers"
+author: hoverkraft
+branding:
+ icon: edit
+ color: blue
+
+inputs:
+ report-files:
+ description: |
+ Path or glob pattern for report files to process.
+ Supports multiple files separated by newlines.
+ Common patterns: coverage/**, reports/**, **/*.xml, **/*.json
+ required: true
+ source-root:
+ description: |
+ Source root path in the container that should be replaced.
+ If not specified, will attempt to auto-detect from file paths.
+ required: false
+ default: ""
+ target-root:
+ description: |
+ Target root path in the repository.
+ Typically this is the GITHUB_WORKSPACE or a subdirectory.
+ required: false
+ default: ""
+ working-directory:
+ description: |
+ Working directory where report files are located.
+ Can be absolute or relative to the repository root.
+ required: false
+ default: "."
+
+runs:
+ using: "composite"
+ steps:
+ - id: rewrite-paths
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ env:
+ REPORT_FILES: ${{ inputs.report-files }}
+ SOURCE_ROOT: ${{ inputs.source-root }}
+ TARGET_ROOT: ${{ inputs.target-root }}
+ WORKING_DIRECTORY: ${{ inputs.working-directory }}
+ with:
+ script: |
+ const fs = require('fs');
+ const path = require('path');
+ const { glob } = require('glob');
+
+ const workingDirectory = process.env.WORKING_DIRECTORY || '.';
+ const workDir = path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory);
+ const reportFilesInput = process.env.REPORT_FILES.trim();
+
+ if (!reportFilesInput) {
+ core.warning('No report files specified for path rewriting');
+ return;
+ }
+
+ // Parse report files (can be newline separated or comma separated)
+ const reportPatterns = reportFilesInput
+ .split(/[\n,]/)
+ .map(p => p.trim())
+ .filter(Boolean);
+
+ core.info(`Looking for report files matching patterns: ${reportPatterns.join(', ')}`);
+
+ // Find all matching files
+ let reportFiles = [];
+ for (const pattern of reportPatterns) {
+ const fullPattern = path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern);
+ const matches = await glob(fullPattern, { nodir: true });
+ reportFiles.push(...matches);
+ }
+
+ if (reportFiles.length === 0) {
+ core.warning(`No report files found matching patterns: ${reportPatterns.join(', ')}`);
+ return;
+ }
+
+ core.info(`Found ${reportFiles.length} report file(s) to process`);
+
+ // Determine source and target roots
+ let sourceRoot = process.env.SOURCE_ROOT.trim();
+ const targetRoot = process.env.TARGET_ROOT.trim() || process.env.GITHUB_WORKSPACE;
+
+ // Auto-detect source root if not provided
+ if (!sourceRoot) {
+ // Common container working directories
+ const commonRoots = ['/app', '/workspace', '/usr/src/app', '/home/node/app'];
+
+ // Try to detect from the first file
+ if (reportFiles.length > 0) {
+ const firstFile = reportFiles[0];
+ const content = fs.readFileSync(firstFile, 'utf8');
+
+ for (const root of commonRoots) {
+ if (content.includes(root)) {
+ sourceRoot = root;
+ core.info(`Auto-detected source root: ${sourceRoot}`);
+ break;
+ }
+ }
+ }
+
+ if (!sourceRoot) {
+ core.warning('Could not auto-detect source root. Skipping path rewriting.');
+ return;
+ }
+ }
+
+ core.info(`Rewriting paths from "${sourceRoot}" to "${targetRoot}"`);
+
+ let filesProcessed = 0;
+ let pathsReplaced = 0;
+
+ // Process each report file
+ for (const reportFile of reportFiles) {
+ try {
+ let content = fs.readFileSync(reportFile, 'utf8');
+ const originalContent = content;
+
+ // Create a regex to match the source root path
+ // Handle both Unix-style and Windows-style paths
+ const escapedSource = sourceRoot.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ const regex = new RegExp(escapedSource.replace(/\\\//g, '[\\\\/]'), 'g');
+
+ // Count matches before replacement
+ const matches = content.match(regex);
+ const matchCount = matches ? matches.length : 0;
+
+ if (matchCount > 0) {
+ // Replace source root with target root
+ content = content.replace(regex, targetRoot.replace(/\\/g, '/'));
+
+ // Write back the modified content
+ fs.writeFileSync(reportFile, content, 'utf8');
+
+ core.info(`โ
Processed ${reportFile}: ${matchCount} path(s) rewritten`);
+ filesProcessed++;
+ pathsReplaced += matchCount;
+ } else {
+ core.info(`โญ๏ธ Skipped ${reportFile}: no matching paths found`);
+ }
+ } catch (error) {
+ core.warning(`Failed to process ${reportFile}: ${error.message}`);
+ }
+ }
+
+ core.info(`\n๐ Summary: ${filesProcessed} file(s) processed, ${pathsReplaced} path(s) rewritten`);
+ core.setOutput('files-processed', filesProcessed);
+ core.setOutput('paths-replaced', pathsReplaced);
diff --git a/actions/test/README.md b/actions/test/README.md
index 77e597b..fad696d 100644
--- a/actions/test/README.md
+++ b/actions/test/README.md
@@ -42,6 +42,13 @@ Action to test Node.js projects with support for coverage reporting and pull req
# Default: `false`
container: "false"
+ # NPM/package manager script command to run for testing.
+ # This should be a script defined in your package.json.
+ # The command should generate coverage report files in a standard format (Cobertura XML, lcov, etc.).
+ #
+ # Default: `test:ci`
+ command: "test:ci"
+
# Code coverage reporter to use. Supported values:
# - `github`: Use ReportGenerator for PR comments with coverage reports
# - `codecov`: Upload coverage to Codecov
@@ -69,24 +76,27 @@ Action to test Node.js projects with support for coverage reporting and pull req
## Inputs
-| **Input** | **Description** | **Required** | **Default** |
-| ----------------------- | --------------------------------------------------------------------- | ------------ | ----------- |
-| **`working-directory`** | Working directory where test commands are executed. | **false** | `.` |
-| | Can be absolute or relative to the repository root. | | |
-| **`container`** | Whether running in container mode (skips checkout and node setup) | **false** | `false` |
-| **`coverage`** | Code coverage reporter to use. Supported values: | **false** | `github` |
-| | - `github`: Use ReportGenerator for PR comments with coverage reports | | |
-| | - `codecov`: Upload coverage to Codecov | | |
-| | - `""` or `null`: No coverage reporting | | |
-| **`coverage-files`** | Path to coverage files for reporting. | **false** | - |
-| | Supports multiple formats (Cobertura, OpenCover, lcov, etc.). | | |
-| | Can be a single file or multiple files separated by semicolons. | | |
-| | If not specified, auto-detection will be attempted for common paths: | | |
-| | - coverage/cobertura-coverage.xml, coverage/coverage.xml | | |
-| | - coverage/lcov.info | | |
-| | - coverage/clover.xml | | |
-| **`github-token`** | GitHub token for coverage PR comments. | **false** | - |
-| | Required when coverage is set to `github`. | | |
+| **Input** | **Description** | **Required** | **Default** |
+| ----------------------- | ----------------------------------------------------------------------- | ------------ | ----------- |
+| **`working-directory`** | Working directory where test commands are executed. | **false** | `.` |
+| | Can be absolute or relative to the repository root. | | |
+| **`container`** | Whether running in container mode (skips checkout and node setup) | **false** | `false` |
+| **`command`** | NPM/package manager script command to run for testing. | **false** | `test:ci` |
+| | This should be a script defined in your package.json. | | |
+| | The command should generate coverage report files in a standard format. | | |
+| **`coverage`** | Code coverage reporter to use. Supported values: | **false** | `github` |
+| | - "GitHub": Use ReportGenerator for PR comments with coverage reports | | |
+| | - "Codecov": Upload coverage to Codecov | | |
+| | - "": No coverage reporting | | |
+| **`coverage-files`** | Path to coverage files for reporting. | **false** | - |
+| | Supports multiple formats (Cobertura, OpenCover, lcov, etc.). | | |
+| | Can be a single file or multiple files separated by semicolons. | | |
+| | If not specified, auto-detection will be attempted for common paths: | | |
+| | - coverage/cobertura-coverage.xml, coverage/coverage.xml | | |
+| | - coverage/lcov.info | | |
+| | - coverage/clover.xml | | |
+| **`github-token`** | GitHub token for coverage PR comments. | **false** | - |
+| | Required when coverage is set to "GitHub". | | |
diff --git a/actions/test/action.yml b/actions/test/action.yml
index 3513ba6..7efc7f7 100644
--- a/actions/test/action.yml
+++ b/actions/test/action.yml
@@ -16,23 +16,28 @@ inputs:
description: "Whether running in container mode (skips checkout and node setup)"
required: false
default: "false"
+ command:
+ description: |
+ NPM/package manager script command to run for testing.
+ This should be a script defined in your package.json.
+ The command should generate coverage report files in a standard format (Cobertura XML, lcov, etc.).
+ required: false
+ default: "test:ci"
coverage:
description: |
Code coverage reporter to use. Supported values:
- - `github`: Use ReportGenerator for PR comments with coverage reports
+ - `github`: Parse coverage reports via [parse-ci-reports](https://hoverkraft-tech/ci-github-common/actions/parse-ci-reports) action, with GitHub summaries/PR comments
- `codecov`: Upload coverage to Codecov
- `""` or `null`: No coverage reporting
required: false
default: "github"
coverage-files:
description: |
- Path to coverage files for reporting.
+ Optional coverage report paths forwarded to the hoverkraft-tech/ci-github-common/actions/parse-ci-reports action.
Supports multiple formats (Cobertura, OpenCover, lcov, etc.).
- Can be a single file or multiple files separated by semicolons.
- If not specified, auto-detection will be attempted for common paths:
- - coverage/cobertura-coverage.xml, coverage/coverage.xml
- - coverage/lcov.info
- - coverage/clover.xml
+ Provide absolute paths or paths relative to the working directory.
+ Multiple entries can be separated by newlines, commas, or semicolons.
+ When omitted, the action falls back to "auto:test" detection (LCOV / Cobertura / Clover).
required: false
default: ""
github-token:
@@ -70,22 +75,27 @@ runs:
env:
RUN_TEST_COMMAND: ${{ inputs.container == 'true' && steps.get-package-manager.outputs.run-script-command || steps.setup-node.outputs.run-script-command }}
WORKING_DIRECTORY: ${{ inputs.working-directory }}
+ TEST_COMMAND: ${{ inputs.command }}
with:
script: |
const workingDirectory = process.env.WORKING_DIRECTORY || '.';
const runScriptCommand = process.env.RUN_TEST_COMMAND;
+ const testCommand = process.env.TEST_COMMAND || 'test:ci';
+
+ core.info(`๐งช Running test command: ${testCommand}...`);
+
try {
- const result = await exec.getExecOutput(runScriptCommand, ['test:ci'], {
+ const result = await exec.getExecOutput(runScriptCommand, [testCommand], {
cwd: require('path').resolve(process.env.GITHUB_WORKSPACE, workingDirectory),
env: { ...process.env, CI: 'true' },
ignoreReturnCode: true
});
-
+
if (result.stdout) core.info(result.stdout);
if (result.stderr) core.warning(result.stderr);
-
+
core.setOutput('test-exit-code', result.exitCode);
-
+
if (result.exitCode !== 0) {
core.setFailed(`Tests failed with exit code ${result.exitCode}`);
}
@@ -94,84 +104,21 @@ runs:
core.setFailed(`Test execution error: ${error.message}`);
}
- # Auto-detect coverage files if not specified
- - id: detect-coverage-files
+ - name: ๐ Parse coverage reports
if: always() && inputs.coverage == 'github'
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
- env:
- WORKING_DIRECTORY: ${{ inputs.working-directory }}
- COVERAGE_FILES: ${{ inputs.coverage-files }}
+ id: parse-coverage-reports
+ uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
with:
- script: |
- const path = require('node:path');
- const fs = require('node:fs');
-
- const workingDirectory = process.env.WORKING_DIRECTORY || '.';
- const workDir = path.resolve(process.env.GITHUB_WORKSPACE, workingDirectory);
-
- if (process.env.COVERAGE_FILES && process.env.COVERAGE_FILES.trim() !== '') {
- core.info(`Using specified coverage files: ${process.env.COVERAGE_FILES}`);
- core.setOutput('coverage-files', process.env.COVERAGE_FILES);
- return;
- }
-
- // Common coverage file paths
- const commonPaths = [
- 'coverage/cobertura-coverage.xml',
- 'coverage/coverage.xml',
- 'coverage/lcov.info',
- 'coverage/clover.xml',
- 'coverage/coverage-final.json',
- 'test-results/coverage.xml',
- 'test-results/cobertura-coverage.xml'
- ];
-
- for (const filePath of commonPaths) {
- const fullPath = path.join(workDir, filePath);
- if (fs.existsSync(fullPath)) {
- core.info(`Auto-detected coverage file: ${fullPath}`);
- core.setOutput('coverage-files', fullPath);
- return;
- }
- }
-
- core.warning('No coverage file auto-detected');
-
- # ReportGenerator for PR comments with coverage reports
- - name: ๐ Generate coverage report
- if: always() && inputs.coverage == 'github' && steps.detect-coverage-files.outputs.coverage-files
- uses: danielpalme/ReportGenerator-GitHub-Action@dcdfb6e704e87df6b2ed0cf123a6c9f69e364869 # v5.5.0
- with:
- reports: ${{ steps.detect-coverage-files.outputs.coverage-files }}
- targetdir: ${{ runner.temp }}/coveragereport-${{ github.run_id }}
- reporttypes: MarkdownSummaryGithub
- sourcedirs: ${{ inputs.working-directory }}
-
- - if: always() && inputs.coverage == 'github'
- id: get-coverage-report-summary
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
- env:
- SUMMARY_FILE: ${{ runner.temp }}/coveragereport-${{ github.run_id }}/SummaryGithub.md
- with:
- script: |
- const fs = require('fs');
- const summaryFilePath = process.env.SUMMARY_FILE;
-
- if (!fs.existsSync(summaryFilePath)) {
- return core.setFailed(`Coverage summary file not found: ${summaryFilePath}`);
- }
-
- const summaryContent = fs.readFileSync(summaryFilePath, 'utf8');
- core.summary.addRaw(summaryContent).write();
-
- core.setOutput('summary-content', summaryContent);
+ report-paths: ${{ inputs.coverage-files || 'auto:test' }}
+ report-name: "Coverage Results"
+ output-format: "summary,markdown"
- name: ๐ Add coverage PR comment
- if: always() && steps.get-coverage-report-summary.outputs.summary-content && github.event_name == 'pull_request'
+ if: always() && inputs.coverage == 'github' && github.event_name == 'pull_request' && steps.parse-coverage-reports.outputs.markdown
uses: hoverkraft-tech/ci-github-common/actions/create-or-update-comment@1127e708e4072515056a4b0d26bcb0653646cedc # 0.30.0
with:
title: "Code Coverage Report"
- body: ${{ steps.get-coverage-report-summary.outputs.summary-content }}
+ body: ${{ steps.parse-coverage-reports.outputs.markdown }}
# Install dependencies for codecov in container mode
- name: Install Codecov dependencies
diff --git a/tests/npm/package.json b/tests/npm/package.json
index 6e58404..18da720 100644
--- a/tests/npm/package.json
+++ b/tests/npm/package.json
@@ -3,6 +3,7 @@
"main": "src/index.js",
"scripts": {
"lint": "echo \"lint test\"",
+ "lint:ci": "echo \"lint:ci test\"",
"build": "mkdir -p dist && echo \"build test\" > dist/test.txt",
"test:ci": "jest --coverage"
},