apex-code-coverage-transformer 2.18.3 → 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +70 -22
- package/lib/handlers/BaseHandler.d.ts +2 -2
- package/lib/handlers/BaseHandler.js.map +1 -1
- package/lib/handlers/getHandler.d.ts +2 -0
- package/lib/handlers/getHandler.js +2 -0
- package/lib/handlers/getHandler.js.map +1 -1
- package/lib/handlers/githubActions.d.ts +33 -0
- package/lib/handlers/githubActions.js +82 -0
- package/lib/handlers/githubActions.js.map +1 -0
- package/lib/handlers/markdown.d.ts +28 -0
- package/lib/handlers/markdown.js +105 -0
- package/lib/handlers/markdown.js.map +1 -0
- package/lib/transformers/generators/generateGitHubActions.d.ts +2 -0
- package/lib/transformers/generators/generateGitHubActions.js +27 -0
- package/lib/transformers/generators/generateGitHubActions.js.map +1 -0
- package/lib/transformers/generators/generateHtml.d.ts +0 -1
- package/lib/transformers/generators/generateHtml.js +0 -3
- package/lib/transformers/generators/generateHtml.js.map +1 -1
- package/lib/transformers/generators/generateMarkdown.d.ts +2 -0
- package/lib/transformers/generators/generateMarkdown.js +39 -0
- package/lib/transformers/generators/generateMarkdown.js.map +1 -0
- package/lib/transformers/reportGenerator.js +26 -15
- package/lib/transformers/reportGenerator.js.map +1 -1
- package/lib/utils/types.d.ts +41 -1
- package/messages/transformer.transform.md +2 -0
- package/oclif.manifest.json +5 -1
- package/package.json +23 -8
- package/oclif.lock +0 -9382
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
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.
|
|
7
7
|
|
|
8
|
+
## [2.19.0](https://github.com/mcarvin8/apex-code-coverage-transformer/compare/v2.18.3...v2.19.0) (2026-05-01)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add markdown and github-actions output formats ([#283](https://github.com/mcarvin8/apex-code-coverage-transformer/issues/283)) ([4fa1c27](https://github.com/mcarvin8/apex-code-coverage-transformer/commit/4fa1c27780cfe08268a282d3c0ce2499f54d2ed1))
|
|
14
|
+
|
|
8
15
|
## [2.18.3](https://github.com/mcarvin8/apex-code-coverage-transformer/compare/v2.18.2...v2.18.3) (2026-04-21)
|
|
9
16
|
|
|
10
17
|
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
A Salesforce CLI plugin that converts Apex code coverage JSON (from deploy or test runs) into formats used by SonarQube, Codecov, GitHub, GitLab, Azure DevOps, Bitbucket, and other tools. Use it to keep coverage in sync with your CI/CD and code quality pipelines.
|
|
10
10
|
|
|
11
|
+
It also produces presentation-ready output for pull-request reviews: a Markdown summary for PR/MR comments and CI job summaries, and GitHub Actions workflow command annotations that surface uncovered lines inline on the PR diff. The GitHub Actions output is designed to pair with the Apex code quality annotations from [sf-cat](https://www.npmjs.com/package/sf-cat), so a single PR can show coverage gaps and quality findings side-by-side.
|
|
12
|
+
|
|
11
13
|
> Missing an output format via `--format`? Open an [issue](https://github.com/mcarvin8/apex-code-coverage-transformer/issues) or submit a [pull request](https://github.com/mcarvin8/apex-code-coverage-transformer/blob/main/CONTRIBUTING.md).
|
|
12
14
|
|
|
13
15
|
<!-- TABLE OF CONTENTS -->
|
|
@@ -45,7 +47,7 @@ A Salesforce CLI plugin that converts Apex code coverage JSON (from deploy or te
|
|
|
45
47
|
## Install
|
|
46
48
|
|
|
47
49
|
```bash
|
|
48
|
-
sf plugins install apex-code-coverage-transformer@
|
|
50
|
+
sf plugins install apex-code-coverage-transformer@latest
|
|
49
51
|
```
|
|
50
52
|
|
|
51
53
|
## Quick Start
|
|
@@ -87,6 +89,8 @@ This plugin is for Salesforce DX projects (`sfdx-project.json`). It maps Apex na
|
|
|
87
89
|
|
|
88
90
|
To run transformation automatically after deploy or test commands, use the [Hook](#automatic-transformation-hook).
|
|
89
91
|
|
|
92
|
+
> **Tip — diff-scoped coverage on PRs.** The Salesforce CLI already scopes `sf project deploy validate`/`start` coverage to whatever is in the deployed manifest. If your PR pipeline builds a manifest from the git diff (for example with [sfdx-git-delta](https://github.com/scolladon/sfdx-git-delta)) and then runs `sf project deploy validate --coverage-formatters json --manifest <delta>`, the resulting coverage JSON only contains the changed Apex. Running this plugin against that JSON gives you per-PR coverage with no extra flags — the diff scoping happens upstream in the deployment, not here.
|
|
93
|
+
|
|
90
94
|
### Salesforce CLI
|
|
91
95
|
|
|
92
96
|
**Deploy/validate** — coverage path: `coverage/coverage/coverage.json`
|
|
@@ -143,18 +147,20 @@ GLOBAL FLAGS
|
|
|
143
147
|
|
|
144
148
|
Use `-f` / `--format` to choose the output format. Multiple `-f` values produce multiple files with the format in the name (e.g. `coverage-sonar.xml`, `coverage-cobertura.xml`).
|
|
145
149
|
|
|
146
|
-
| Format
|
|
147
|
-
|
|
|
148
|
-
| sonar
|
|
149
|
-
| cobertura
|
|
150
|
-
| jacoco
|
|
151
|
-
| lcovonly
|
|
152
|
-
| clover
|
|
153
|
-
| json
|
|
154
|
-
| json-summary
|
|
155
|
-
| simplecov
|
|
156
|
-
| opencover
|
|
157
|
-
| html
|
|
150
|
+
| Format | Description | Typical use | Example |
|
|
151
|
+
| -------------- | -------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
152
|
+
| sonar | SonarQube generic coverage | SonarQube, SonarCloud | `sf acc-transformer transform -j "coverage.json" -r "coverage.xml" -f "sonar"` |
|
|
153
|
+
| cobertura | Cobertura XML | Codecov, Azure, Jenkins, GitLab, GitHub | `sf acc-transformer transform -j "coverage.json" -r "coverage.xml" -f "cobertura"` |
|
|
154
|
+
| jacoco | JaCoCo XML | Codecov, Jenkins, Maven, Gradle | `sf acc-transformer transform -j "coverage.json" -r "coverage.xml" -f "jacoco"` |
|
|
155
|
+
| lcovonly | LCOV | Codecov, Coveralls, GitHub | `sf acc-transformer transform -j "coverage.json" -r "coverage.info" -f "lcovonly"` |
|
|
156
|
+
| clover | Clover XML | Bamboo, Bitbucket, Jenkins | `sf acc-transformer transform -j "coverage.json" -r "coverage.xml" -f "clover"` |
|
|
157
|
+
| json | Istanbul JSON | Istanbul/NYC, Codecov | `sf acc-transformer transform -j "coverage.json" -r "coverage.json" -f "json"` |
|
|
158
|
+
| json-summary | JSON summary | Badges, PR comments | `sf acc-transformer transform -j "coverage.json" -r "coverage.json" -f "json-summary"` |
|
|
159
|
+
| simplecov | SimpleCov JSON | Codecov, Ruby tools | `sf acc-transformer transform -j "coverage.json" -r "coverage.json" -f "simplecov"` |
|
|
160
|
+
| opencover | OpenCover XML | Azure DevOps, VS, Codecov | `sf acc-transformer transform -j "coverage.json" -r "coverage.xml" -f "opencover"` |
|
|
161
|
+
| html | HTML report | Browsers, CI artifacts | `sf acc-transformer transform -j "coverage.json" -r "coverage.html" -f "html"` |
|
|
162
|
+
| markdown | Markdown summary | PR/MR comments, CI job summaries | `sf acc-transformer transform -j "coverage.json" -r "coverage.md" -f "markdown"` |
|
|
163
|
+
| github-actions | GitHub Actions annotations | GitHub Actions PR diff annotations | `sf acc-transformer transform -j "coverage.json" -r "coverage.txt" -f "github-actions"` |
|
|
158
164
|
|
|
159
165
|
## CI/CD Integration
|
|
160
166
|
|
|
@@ -198,7 +204,7 @@ jobs:
|
|
|
198
204
|
|
|
199
205
|
### SonarQube
|
|
200
206
|
|
|
201
|
-
Use the **sonar** format and upload using SonarQube's generic test coverage report formatter, `sonar.coverageReportPaths`.
|
|
207
|
+
Use the **sonar** format and upload using SonarQube's generic test coverage report formatter, `sonar.coverageReportPaths`.
|
|
202
208
|
|
|
203
209
|
**Scanner:**
|
|
204
210
|
|
|
@@ -289,6 +295,48 @@ jobs:
|
|
|
289
295
|
path: code-coverage-results.md
|
|
290
296
|
```
|
|
291
297
|
|
|
298
|
+
#### Markdown PR comments (built-in)
|
|
299
|
+
|
|
300
|
+
Skip the third-party summary action by using the built-in `markdown` format. The output is ready to drop straight into a PR comment or the GitHub Actions [job summary](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary):
|
|
301
|
+
|
|
302
|
+
```yaml
|
|
303
|
+
- name: Run Apex Tests
|
|
304
|
+
run: sf apex run test --code-coverage --output-dir coverage --target-org ci-org
|
|
305
|
+
- name: Transform Coverage to Markdown
|
|
306
|
+
run: sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.md" -f "markdown"
|
|
307
|
+
- name: Add coverage to job summary
|
|
308
|
+
run: cat coverage.md >> $GITHUB_STEP_SUMMARY
|
|
309
|
+
- name: Add Coverage PR Comment
|
|
310
|
+
uses: marocchino/sticky-pull-request-comment@v2
|
|
311
|
+
if: github.event_name == 'pull_request'
|
|
312
|
+
with:
|
|
313
|
+
recreate: true
|
|
314
|
+
path: coverage.md
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The Markdown report includes an overall summary block, a per-package-directory table, and a file-level table sorted with the lowest coverage first so reviewers see the most actionable rows at the top.
|
|
318
|
+
|
|
319
|
+
#### GitHub Actions inline annotations
|
|
320
|
+
|
|
321
|
+
The `github-actions` format emits one [`::warning`](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions) workflow command per uncovered Apex line, plus a `::notice` summary. When a step prints the file to stdout, the runner renders annotations inline on the PR diff and on the workflow run page.
|
|
322
|
+
|
|
323
|
+
```yaml
|
|
324
|
+
- name: Run Apex Tests
|
|
325
|
+
run: sf apex run test --code-coverage --output-dir coverage --target-org ci-org
|
|
326
|
+
- name: Transform Coverage to GitHub Actions Annotations
|
|
327
|
+
run: sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.txt" -f "github-actions"
|
|
328
|
+
- name: Emit coverage annotations
|
|
329
|
+
run: cat coverage.txt
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
This pairs with the [`sf-cat`](https://www.npmjs.com/package/sf-cat) plugin's GitHub Actions output for code quality findings, so a single PR shows coverage gaps and quality issues as inline annotations on the same diff.
|
|
333
|
+
|
|
334
|
+
You can produce both at once with multiple `-f` flags:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -f "markdown" -f "github-actions" -f "sonar"
|
|
338
|
+
```
|
|
339
|
+
|
|
292
340
|
### GitLab CI
|
|
293
341
|
|
|
294
342
|
Cobertura for coverage in the UI:
|
|
@@ -342,13 +390,13 @@ Create `.apexcodecovtransformer.config.json` in the project root to transform co
|
|
|
342
390
|
|
|
343
391
|
Sample configs: [Salesforce CLI](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/defaults/salesforce-cli/.apexcodecovtransformer.config.json), [SFDX Hardis](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/defaults/sfdx-hardis/.apexcodecovtransformer.config.json).
|
|
344
392
|
|
|
345
|
-
| Key | Required | Description
|
|
346
|
-
| -------------------------- | ---------- |
|
|
347
|
-
| `deployCoverageJsonPath` | For deploy | Path to deploy coverage JSON.
|
|
348
|
-
| `testCoverageJsonPath` | For test | Path to test coverage JSON.
|
|
393
|
+
| Key | Required | Description |
|
|
394
|
+
| -------------------------- | ---------- | ------------------------------------------------------------ |
|
|
395
|
+
| `deployCoverageJsonPath` | For deploy | Path to deploy coverage JSON. |
|
|
396
|
+
| `testCoverageJsonPath` | For test | Path to test coverage JSON. |
|
|
349
397
|
| `outputReportPath` | No | Output path (default: `coverage.[xml/info/json]` by format). |
|
|
350
|
-
| `format` | No | Format(s), comma-separated (default: `sonar`).
|
|
351
|
-
| `ignorePackageDirectories` | No | Comma-separated package directories to ignore.
|
|
398
|
+
| `format` | No | Format(s), comma-separated (default: `sonar`). |
|
|
399
|
+
| `ignorePackageDirectories` | No | Comma-separated package directories to ignore. |
|
|
352
400
|
|
|
353
401
|
## Troubleshooting
|
|
354
402
|
|
|
@@ -384,8 +432,8 @@ Error (1): ENOENT: no such file or directory: {packageDir}
|
|
|
384
432
|
|
|
385
433
|
## Contributing
|
|
386
434
|
|
|
387
|
-
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/mcarvin8/apex-code-coverage-transformer/blob/main/CONTRIBUTING.md)
|
|
435
|
+
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/mcarvin8/apex-code-coverage-transformer/blob/main/CONTRIBUTING.md).
|
|
388
436
|
|
|
389
437
|
## License
|
|
390
438
|
|
|
391
|
-
MIT
|
|
439
|
+
[MIT](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/LICENSE.md)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CoverageHandler, SonarCoverageObject, CoberturaCoverageObject, CloverCoverageObject, LcovCoverageObject, JaCoCoCoverageObject, IstanbulCoverageObject, JsonSummaryCoverageObject, SimpleCovCoverageObject, OpenCoverCoverageObject, HtmlCoverageObject } from '../utils/types.js';
|
|
1
|
+
import { CoverageHandler, SonarCoverageObject, CoberturaCoverageObject, CloverCoverageObject, LcovCoverageObject, JaCoCoCoverageObject, IstanbulCoverageObject, JsonSummaryCoverageObject, SimpleCovCoverageObject, OpenCoverCoverageObject, HtmlCoverageObject, MarkdownCoverageObject, GitHubActionsCoverageObject } from '../utils/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Abstract base class for coverage handlers providing common utilities.
|
|
4
4
|
* Reduces code duplication across different format handlers.
|
|
@@ -47,5 +47,5 @@ export declare abstract class BaseHandler implements CoverageHandler {
|
|
|
47
47
|
'@name'?: string;
|
|
48
48
|
}>(items: T[]): T[];
|
|
49
49
|
abstract processFile(filePath: string, fileName: string, lines: Record<string, number>, sourceContent?: string): void;
|
|
50
|
-
abstract finalize(): SonarCoverageObject | CoberturaCoverageObject | CloverCoverageObject | LcovCoverageObject | JaCoCoCoverageObject | IstanbulCoverageObject | JsonSummaryCoverageObject | SimpleCovCoverageObject | OpenCoverCoverageObject | HtmlCoverageObject;
|
|
50
|
+
abstract finalize(): SonarCoverageObject | CoberturaCoverageObject | CloverCoverageObject | LcovCoverageObject | JaCoCoCoverageObject | IstanbulCoverageObject | JsonSummaryCoverageObject | SimpleCovCoverageObject | OpenCoverCoverageObject | HtmlCoverageObject | MarkdownCoverageObject | GitHubActionsCoverageObject;
|
|
51
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseHandler.js","sourceRoot":"","sources":["../../src/handlers/BaseHandler.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseHandler.js","sourceRoot":"","sources":["../../src/handlers/BaseHandler.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAkBb;;;GAGG;AACH,MAAM,OAAgB,WAAW;IAC/B;;;;;OAKG;IACH,kDAAkD;IACxC,iBAAiB,CAAC,KAA6B;QAMvD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAChF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5E,MAAM,UAAU,GAAG,cAAc,GAAG,YAAY,CAAC;QACjD,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;IAChE,CAAC;IAED;;;;;;OAMG;IACH,kDAAkD;IACxC,oBAAoB,CAAC,KAA6B,EAAE,OAAgB;QAC5E,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;aACzB,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;aACvD,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;aAC7B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACO,sBAAsB,CAAC,KAA6B;QAI5D,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC;YAC/C,SAAS,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC;SACnD,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,kDAAkD;IACxC,UAAU,CAAyE,KAAU;QACrG,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACzB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/D,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/D,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC;CAsBF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getHandler.js","sourceRoot":"","sources":["../../src/handlers/getHandler.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,mDAAmD;AACnD,OAAO,YAAY,CAAC;AACpB,OAAO,gBAAgB,CAAC;AACxB,OAAO,aAAa,CAAC;AACrB,OAAO,WAAW,CAAC;AACnB,OAAO,aAAa,CAAC;AACrB,OAAO,mBAAmB,CAAC;AAC3B,OAAO,kBAAkB,CAAC;AAC1B,OAAO,gBAAgB,CAAC;AACxB,OAAO,gBAAgB,CAAC;AACxB,OAAO,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"getHandler.js","sourceRoot":"","sources":["../../src/handlers/getHandler.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,mDAAmD;AACnD,OAAO,YAAY,CAAC;AACpB,OAAO,gBAAgB,CAAC;AACxB,OAAO,aAAa,CAAC;AACrB,OAAO,WAAW,CAAC;AACnB,OAAO,aAAa,CAAC;AACrB,OAAO,mBAAmB,CAAC;AAC3B,OAAO,kBAAkB,CAAC;AAC1B,OAAO,gBAAgB,CAAC;AACxB,OAAO,gBAAgB,CAAC;AACxB,OAAO,WAAW,CAAC;AACnB,OAAO,eAAe,CAAC;AACvB,OAAO,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { GitHubActionsCoverageObject } from '../utils/types.js';
|
|
2
|
+
import { BaseHandler } from './BaseHandler.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handler for generating GitHub Actions workflow command output.
|
|
5
|
+
*
|
|
6
|
+
* Emits one `::warning file=...,line=...` annotation per uncovered Apex line
|
|
7
|
+
* plus a `::notice` summary line. When the resulting file is printed to stdout
|
|
8
|
+
* by a workflow step, the GitHub Actions runner renders the annotations
|
|
9
|
+
* inline on the PR diff and on the workflow run page.
|
|
10
|
+
*
|
|
11
|
+
* Pairs with the existing `sf-cat` plugin's GitHub Actions output for code
|
|
12
|
+
* quality, giving Salesforce teams a unified annotation experience for
|
|
13
|
+
* coverage and quality on the same PR.
|
|
14
|
+
*
|
|
15
|
+
* @see https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```yaml
|
|
19
|
+
* - name: Transform coverage to GitHub Actions annotations
|
|
20
|
+
* run: sf acc-transformer transform -j coverage.json -r coverage.txt -f github-actions
|
|
21
|
+
* - name: Emit annotations
|
|
22
|
+
* run: cat coverage.txt
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class GitHubActionsCoverageHandler extends BaseHandler {
|
|
26
|
+
private readonly coverageObj;
|
|
27
|
+
private totalLinesAccumulator;
|
|
28
|
+
private coveredLinesAccumulator;
|
|
29
|
+
private fileCount;
|
|
30
|
+
constructor();
|
|
31
|
+
processFile(filePath: string, _fileName: string, lines: Record<string, number>): void;
|
|
32
|
+
finalize(): GitHubActionsCoverageObject;
|
|
33
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
import { BaseHandler } from './BaseHandler.js';
|
|
3
|
+
import { HandlerRegistry } from './HandlerRegistry.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handler for generating GitHub Actions workflow command output.
|
|
6
|
+
*
|
|
7
|
+
* Emits one `::warning file=...,line=...` annotation per uncovered Apex line
|
|
8
|
+
* plus a `::notice` summary line. When the resulting file is printed to stdout
|
|
9
|
+
* by a workflow step, the GitHub Actions runner renders the annotations
|
|
10
|
+
* inline on the PR diff and on the workflow run page.
|
|
11
|
+
*
|
|
12
|
+
* Pairs with the existing `sf-cat` plugin's GitHub Actions output for code
|
|
13
|
+
* quality, giving Salesforce teams a unified annotation experience for
|
|
14
|
+
* coverage and quality on the same PR.
|
|
15
|
+
*
|
|
16
|
+
* @see https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```yaml
|
|
20
|
+
* - name: Transform coverage to GitHub Actions annotations
|
|
21
|
+
* run: sf acc-transformer transform -j coverage.json -r coverage.txt -f github-actions
|
|
22
|
+
* - name: Emit annotations
|
|
23
|
+
* run: cat coverage.txt
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class GitHubActionsCoverageHandler extends BaseHandler {
|
|
27
|
+
coverageObj;
|
|
28
|
+
totalLinesAccumulator = 0;
|
|
29
|
+
coveredLinesAccumulator = 0;
|
|
30
|
+
fileCount = 0;
|
|
31
|
+
constructor() {
|
|
32
|
+
super();
|
|
33
|
+
this.coverageObj = {
|
|
34
|
+
summary: {
|
|
35
|
+
totalLines: 0,
|
|
36
|
+
coveredLines: 0,
|
|
37
|
+
uncoveredLines: 0,
|
|
38
|
+
lineRate: 0,
|
|
39
|
+
fileCount: 0,
|
|
40
|
+
},
|
|
41
|
+
uncoveredLines: [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
processFile(filePath, _fileName, lines) {
|
|
45
|
+
const { totalLines, coveredLines } = this.calculateCoverage(lines);
|
|
46
|
+
this.totalLinesAccumulator += totalLines;
|
|
47
|
+
this.coveredLinesAccumulator += coveredLines;
|
|
48
|
+
this.fileCount += 1;
|
|
49
|
+
const uncovered = this.extractLinesByStatus(lines, false);
|
|
50
|
+
for (const lineNumber of uncovered) {
|
|
51
|
+
this.coverageObj.uncoveredLines.push({ filePath, lineNumber });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
finalize() {
|
|
55
|
+
const totalLines = this.totalLinesAccumulator;
|
|
56
|
+
const coveredLines = this.coveredLinesAccumulator;
|
|
57
|
+
const uncoveredLines = totalLines - coveredLines;
|
|
58
|
+
const lineRate = totalLines > 0 ? coveredLines / totalLines : 0;
|
|
59
|
+
this.coverageObj.summary = {
|
|
60
|
+
totalLines,
|
|
61
|
+
coveredLines,
|
|
62
|
+
uncoveredLines,
|
|
63
|
+
lineRate,
|
|
64
|
+
fileCount: this.fileCount,
|
|
65
|
+
};
|
|
66
|
+
this.coverageObj.uncoveredLines.sort((a, b) => {
|
|
67
|
+
const pathCompare = a.filePath.localeCompare(b.filePath);
|
|
68
|
+
if (pathCompare !== 0)
|
|
69
|
+
return pathCompare;
|
|
70
|
+
return a.lineNumber - b.lineNumber;
|
|
71
|
+
});
|
|
72
|
+
return this.coverageObj;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
HandlerRegistry.register({
|
|
76
|
+
name: 'github-actions',
|
|
77
|
+
description: 'GitHub Actions workflow command annotations for uncovered lines',
|
|
78
|
+
fileExtension: '.txt',
|
|
79
|
+
handler: () => new GitHubActionsCoverageHandler(),
|
|
80
|
+
compatibleWith: ['GitHub Actions'],
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=githubActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubActions.js","sourceRoot":"","sources":["../../src/handlers/githubActions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,4BAA6B,SAAQ,WAAW;IAC1C,WAAW,CAA8B;IAClD,qBAAqB,GAAG,CAAC,CAAC;IAC1B,uBAAuB,GAAG,CAAC,CAAC;IAC5B,SAAS,GAAG,CAAC,CAAC;IAEtB;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG;YACjB,OAAO,EAAE;gBACP,UAAU,EAAE,CAAC;gBACb,YAAY,EAAE,CAAC;gBACf,cAAc,EAAE,CAAC;gBACjB,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,CAAC;aACb;YACD,cAAc,EAAE,EAAE;SACnB,CAAC;IACJ,CAAC;IAEM,WAAW,CAAC,QAAgB,EAAE,SAAiB,EAAE,KAA6B;QACnF,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEnE,IAAI,CAAC,qBAAqB,IAAI,UAAU,CAAC;QACzC,IAAI,CAAC,uBAAuB,IAAI,YAAY,CAAC;QAC7C,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;QAEpB,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1D,KAAK,MAAM,UAAU,IAAI,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,uBAAuB,CAAC;QAClD,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;QACjD,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhE,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG;YACzB,UAAU;YACV,YAAY;YACZ,cAAc;YACd,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC5C,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACzD,IAAI,WAAW,KAAK,CAAC;gBAAE,OAAO,WAAW,CAAC;YAC1C,OAAO,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,eAAe,CAAC,QAAQ,CAAC;IACvB,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,iEAAiE;IAC9E,aAAa,EAAE,MAAM;IACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,4BAA4B,EAAE;IACjD,cAAc,EAAE,CAAC,gBAAgB,CAAC;CACnC,CAAC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MarkdownCoverageObject } from '../utils/types.js';
|
|
2
|
+
import { BaseHandler } from './BaseHandler.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handler for generating Markdown coverage summaries.
|
|
5
|
+
*
|
|
6
|
+
* Designed for pipeline PR / MR comments and job summary blocks
|
|
7
|
+
* (e.g. `$GITHUB_STEP_SUMMARY`, GitLab MR widgets, Bitbucket comments).
|
|
8
|
+
*
|
|
9
|
+
* The report includes:
|
|
10
|
+
* - An overall coverage summary block
|
|
11
|
+
* - A per-package-directory coverage table
|
|
12
|
+
* - A file coverage table sorted with the lowest coverage first
|
|
13
|
+
*
|
|
14
|
+
* Compatible with:
|
|
15
|
+
* - GitHub Actions (job summary, sticky PR comments)
|
|
16
|
+
* - GitLab CI (MR comments)
|
|
17
|
+
* - Bitbucket / Azure DevOps PR comments
|
|
18
|
+
* - Any tool that renders GitHub-flavored Markdown
|
|
19
|
+
*/
|
|
20
|
+
export declare class MarkdownCoverageHandler extends BaseHandler {
|
|
21
|
+
private readonly coverageObj;
|
|
22
|
+
private totalLinesAccumulator;
|
|
23
|
+
private coveredLinesAccumulator;
|
|
24
|
+
private readonly packageMap;
|
|
25
|
+
constructor();
|
|
26
|
+
processFile(filePath: string, _fileName: string, lines: Record<string, number>): void;
|
|
27
|
+
finalize(): MarkdownCoverageObject;
|
|
28
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
import { BaseHandler } from './BaseHandler.js';
|
|
3
|
+
import { HandlerRegistry } from './HandlerRegistry.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handler for generating Markdown coverage summaries.
|
|
6
|
+
*
|
|
7
|
+
* Designed for pipeline PR / MR comments and job summary blocks
|
|
8
|
+
* (e.g. `$GITHUB_STEP_SUMMARY`, GitLab MR widgets, Bitbucket comments).
|
|
9
|
+
*
|
|
10
|
+
* The report includes:
|
|
11
|
+
* - An overall coverage summary block
|
|
12
|
+
* - A per-package-directory coverage table
|
|
13
|
+
* - A file coverage table sorted with the lowest coverage first
|
|
14
|
+
*
|
|
15
|
+
* Compatible with:
|
|
16
|
+
* - GitHub Actions (job summary, sticky PR comments)
|
|
17
|
+
* - GitLab CI (MR comments)
|
|
18
|
+
* - Bitbucket / Azure DevOps PR comments
|
|
19
|
+
* - Any tool that renders GitHub-flavored Markdown
|
|
20
|
+
*/
|
|
21
|
+
export class MarkdownCoverageHandler extends BaseHandler {
|
|
22
|
+
coverageObj;
|
|
23
|
+
totalLinesAccumulator = 0;
|
|
24
|
+
coveredLinesAccumulator = 0;
|
|
25
|
+
packageMap = new Map();
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
this.coverageObj = {
|
|
29
|
+
summary: {
|
|
30
|
+
totalLines: 0,
|
|
31
|
+
coveredLines: 0,
|
|
32
|
+
uncoveredLines: 0,
|
|
33
|
+
lineRate: 0,
|
|
34
|
+
fileCount: 0,
|
|
35
|
+
},
|
|
36
|
+
packages: [],
|
|
37
|
+
files: [],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
processFile(filePath, _fileName, lines) {
|
|
41
|
+
const { totalLines, coveredLines, uncoveredLines, lineRate } = this.calculateCoverage(lines);
|
|
42
|
+
const fileRow = {
|
|
43
|
+
filePath,
|
|
44
|
+
totalLines,
|
|
45
|
+
coveredLines,
|
|
46
|
+
uncoveredLines,
|
|
47
|
+
lineRate,
|
|
48
|
+
};
|
|
49
|
+
this.coverageObj.files.push(fileRow);
|
|
50
|
+
this.totalLinesAccumulator += totalLines;
|
|
51
|
+
this.coveredLinesAccumulator += coveredLines;
|
|
52
|
+
const directory = filePath.split('/')[0];
|
|
53
|
+
const existing = this.packageMap.get(directory);
|
|
54
|
+
if (existing) {
|
|
55
|
+
existing.totalLines += totalLines;
|
|
56
|
+
existing.coveredLines += coveredLines;
|
|
57
|
+
existing.fileCount += 1;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this.packageMap.set(directory, { totalLines, coveredLines, fileCount: 1 });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
finalize() {
|
|
64
|
+
const totalLines = this.totalLinesAccumulator;
|
|
65
|
+
const coveredLines = this.coveredLinesAccumulator;
|
|
66
|
+
const uncoveredLines = totalLines - coveredLines;
|
|
67
|
+
const lineRate = totalLines > 0 ? coveredLines / totalLines : 0;
|
|
68
|
+
this.coverageObj.summary = {
|
|
69
|
+
totalLines,
|
|
70
|
+
coveredLines,
|
|
71
|
+
uncoveredLines,
|
|
72
|
+
lineRate,
|
|
73
|
+
fileCount: this.coverageObj.files.length,
|
|
74
|
+
};
|
|
75
|
+
this.coverageObj.packages = Array.from(this.packageMap.entries())
|
|
76
|
+
.map(([directory, acc]) => {
|
|
77
|
+
const pkgUncovered = acc.totalLines - acc.coveredLines;
|
|
78
|
+
const pkgLineRate = acc.totalLines > 0 ? acc.coveredLines / acc.totalLines : 0;
|
|
79
|
+
return {
|
|
80
|
+
directory,
|
|
81
|
+
fileCount: acc.fileCount,
|
|
82
|
+
totalLines: acc.totalLines,
|
|
83
|
+
coveredLines: acc.coveredLines,
|
|
84
|
+
uncoveredLines: pkgUncovered,
|
|
85
|
+
lineRate: pkgLineRate,
|
|
86
|
+
};
|
|
87
|
+
})
|
|
88
|
+
.sort((a, b) => a.directory.localeCompare(b.directory));
|
|
89
|
+
// Worst-covered files first (most actionable in a PR comment), tiebreak by path
|
|
90
|
+
this.coverageObj.files.sort((a, b) => {
|
|
91
|
+
if (a.lineRate !== b.lineRate)
|
|
92
|
+
return a.lineRate - b.lineRate;
|
|
93
|
+
return a.filePath.localeCompare(b.filePath);
|
|
94
|
+
});
|
|
95
|
+
return this.coverageObj;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
HandlerRegistry.register({
|
|
99
|
+
name: 'markdown',
|
|
100
|
+
description: 'Markdown summary for PR comments and CI job summaries',
|
|
101
|
+
fileExtension: '.md',
|
|
102
|
+
handler: () => new MarkdownCoverageHandler(),
|
|
103
|
+
compatibleWith: ['GitHub Actions', 'GitLab CI', 'Bitbucket', 'Azure DevOps'],
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/handlers/markdown.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,uBAAwB,SAAQ,WAAW;IACrC,WAAW,CAAyB;IAC7C,qBAAqB,GAAG,CAAC,CAAC;IAC1B,uBAAuB,GAAG,CAAC,CAAC;IACnB,UAAU,GAAG,IAAI,GAAG,EAA8B,CAAC;IAEpE;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG;YACjB,OAAO,EAAE;gBACP,UAAU,EAAE,CAAC;gBACb,YAAY,EAAE,CAAC;gBACf,cAAc,EAAE,CAAC;gBACjB,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,CAAC;aACb;YACD,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;SACV,CAAC;IACJ,CAAC;IAEM,WAAW,CAAC,QAAgB,EAAE,SAAiB,EAAE,KAA6B;QACnF,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAE7F,MAAM,OAAO,GAAoB;YAC/B,QAAQ;YACR,UAAU;YACV,YAAY;YACZ,cAAc;YACd,QAAQ;SACT,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAErC,IAAI,CAAC,qBAAqB,IAAI,UAAU,CAAC;QACzC,IAAI,CAAC,uBAAuB,IAAI,YAAY,CAAC;QAE7C,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,UAAU,IAAI,UAAU,CAAC;YAClC,QAAQ,CAAC,YAAY,IAAI,YAAY,CAAC;YACtC,QAAQ,CAAC,SAAS,IAAI,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,uBAAuB,CAAC;QAClD,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;QACjD,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhE,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG;YACzB,UAAU;YACV,YAAY;YACZ,cAAc;YACd,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM;SACzC,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;aAC9D,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,EAAsB,EAAE;YAC5C,MAAM,YAAY,GAAG,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC;YACvD,MAAM,WAAW,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,OAAO;gBACL,SAAS;gBACT,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,cAAc,EAAE,YAAY;gBAC5B,QAAQ,EAAE,WAAW;aACtB,CAAC;QACJ,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAE1D,gFAAgF;QAChF,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;YAC9D,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,eAAe,CAAC,QAAQ,CAAC;IACvB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,uDAAuD;IACpE,aAAa,EAAE,KAAK;IACpB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,uBAAuB,EAAE;IAC5C,cAAc,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,CAAC;CAC7E,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function formatPercent(lineRate) {
|
|
2
|
+
return `${(lineRate * 100).toFixed(2)}%`;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Escape a string for use as a GitHub Actions workflow command property value.
|
|
6
|
+
*
|
|
7
|
+
* @see https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#example-setting-a-warning-message
|
|
8
|
+
*/
|
|
9
|
+
function escapeProperty(value) {
|
|
10
|
+
return value
|
|
11
|
+
.replace(/%/g, '%25')
|
|
12
|
+
.replace(/\r/g, '%0D')
|
|
13
|
+
.replace(/\n/g, '%0A')
|
|
14
|
+
.replace(/:/g, '%3A')
|
|
15
|
+
.replace(/,/g, '%2C');
|
|
16
|
+
}
|
|
17
|
+
function escapeData(value) {
|
|
18
|
+
return value.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
|
|
19
|
+
}
|
|
20
|
+
export function generateGitHubActions(coverageObj) {
|
|
21
|
+
const { summary, uncoveredLines } = coverageObj;
|
|
22
|
+
const overall = formatPercent(summary.lineRate);
|
|
23
|
+
const summaryLine = `::notice title=Apex Code Coverage::Overall coverage ${escapeData(overall)} (${summary.coveredLines}/${summary.totalLines} lines, ${summary.uncoveredLines} uncovered across ${summary.fileCount} file${summary.fileCount === 1 ? '' : 's'})`;
|
|
24
|
+
const annotations = uncoveredLines.map(({ filePath, lineNumber }) => `::warning file=${escapeProperty(filePath)},line=${lineNumber},title=Uncovered Apex line::Line ${lineNumber} is not covered by any Apex test`);
|
|
25
|
+
return [summaryLine, ...annotations].join('\n');
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=generateGitHubActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateGitHubActions.js","sourceRoot":"","sources":["../../../src/transformers/generators/generateGitHubActions.ts"],"names":[],"mappings":"AAEA,SAAS,aAAa,CAAC,QAAgB;IACrC,OAAO,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,WAAwC;IAC5E,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC;IAChD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,WAAW,GAAG,uDAAuD,UAAU,CACnF,OAAO,CACR,KAAK,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,UAAU,WAAW,OAAO,CAAC,cAAc,qBAC/E,OAAO,CAAC,SACV,QAAQ,OAAO,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAE9C,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CACpC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,CAC3B,kBAAkB,cAAc,CAAC,QAAQ,CAAC,SAAS,UAAU,oCAAoC,UAAU,kCAAkC,CAChJ,CAAC;IAEF,OAAO,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateHtml.js","sourceRoot":"","sources":["../../../src/transformers/generators/generateHtml.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"generateHtml.js","sourceRoot":"","sources":["../../../src/transformers/generators/generateHtml.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function formatPercent(lineRate) {
|
|
2
|
+
return `${(lineRate * 100).toFixed(2)}%`;
|
|
3
|
+
}
|
|
4
|
+
function escapePipes(value) {
|
|
5
|
+
return value.replace(/\|/g, '\\|');
|
|
6
|
+
}
|
|
7
|
+
function buildPackageTable(packages) {
|
|
8
|
+
if (packages.length === 0)
|
|
9
|
+
return '';
|
|
10
|
+
const header = [
|
|
11
|
+
'| Directory | Files | Lines | Covered | Uncovered | Coverage |',
|
|
12
|
+
'| --- | ---: | ---: | ---: | ---: | ---: |',
|
|
13
|
+
].join('\n');
|
|
14
|
+
const rows = packages
|
|
15
|
+
.map((pkg) => `| ${escapePipes(pkg.directory)} | ${pkg.fileCount} | ${pkg.totalLines} | ${pkg.coveredLines} | ${pkg.uncoveredLines} | ${formatPercent(pkg.lineRate)} |`)
|
|
16
|
+
.join('\n');
|
|
17
|
+
return `## Package directory coverage\n\n${header}\n${rows}`;
|
|
18
|
+
}
|
|
19
|
+
function buildFileTable(files) {
|
|
20
|
+
if (files.length === 0)
|
|
21
|
+
return '';
|
|
22
|
+
const header = ['| File | Lines | Covered | Uncovered | Coverage |', '| --- | ---: | ---: | ---: | ---: |'].join('\n');
|
|
23
|
+
const rows = files
|
|
24
|
+
.map((file) => `| ${escapePipes(file.filePath)} | ${file.totalLines} | ${file.coveredLines} | ${file.uncoveredLines} | ${formatPercent(file.lineRate)} |`)
|
|
25
|
+
.join('\n');
|
|
26
|
+
return `## File coverage\n\nFiles are sorted with the lowest coverage first.\n\n${header}\n${rows}`;
|
|
27
|
+
}
|
|
28
|
+
export function generateMarkdown(coverageObj) {
|
|
29
|
+
const { summary, packages, files } = coverageObj;
|
|
30
|
+
const overall = formatPercent(summary.lineRate);
|
|
31
|
+
const summaryBlock = [
|
|
32
|
+
'# Apex Code Coverage Report',
|
|
33
|
+
'',
|
|
34
|
+
`**Overall coverage:** ${overall} (${summary.coveredLines} / ${summary.totalLines} lines across ${summary.fileCount} file${summary.fileCount === 1 ? '' : 's'})`,
|
|
35
|
+
].join('\n');
|
|
36
|
+
const sections = [summaryBlock, buildPackageTable(packages), buildFileTable(files)].filter(Boolean);
|
|
37
|
+
return sections.join('\n\n');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=generateMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateMarkdown.js","sourceRoot":"","sources":["../../../src/transformers/generators/generateMarkdown.ts"],"names":[],"mappings":"AAEA,SAAS,aAAa,CAAC,QAAgB;IACrC,OAAO,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,iBAAiB,CAAC,QAA4C;IACrE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG;QACb,gEAAgE;QAChE,4CAA4C;KAC7C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,IAAI,GAAG,QAAQ;SAClB,GAAG,CACF,CAAC,GAAG,EAAE,EAAE,CACN,KAAK,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,SAAS,MAAM,GAAG,CAAC,UAAU,MAAM,GAAG,CAAC,YAAY,MAC1F,GAAG,CAAC,cACN,MAAM,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CACxC;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO,oCAAoC,MAAM,KAAK,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED,SAAS,cAAc,CAAC,KAAsC;IAC5D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,CAAC,mDAAmD,EAAE,qCAAqC,CAAC,CAAC,IAAI,CAC9G,IAAI,CACL,CAAC;IACF,MAAM,IAAI,GAAG,KAAK;SACf,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CACP,KAAK,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC,YAAY,MACzE,IAAI,CAAC,cACP,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CACzC;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO,2EAA2E,MAAM,KAAK,IAAI,EAAE,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAmC;IAClE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC;IACjD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG;QACnB,6BAA6B;QAC7B,EAAE;QACF,yBAAyB,OAAO,KAAK,OAAO,CAAC,YAAY,MAAM,OAAO,CAAC,UAAU,iBAAiB,OAAO,CAAC,SAAS,QACjH,OAAO,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GACjC,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,QAAQ,GAAG,CAAC,YAAY,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpG,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|