├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── action.yml ├── dist └── index.js ├── package-lock.json ├── package.json ├── src └── reportgenerator.ts ├── tsconfig.json └── update-version.ps1 /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: danielpalme 2 | custom: https://paypal.me/danielpalme82 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | lib/ 3 | node_modules 4 | reportgeneratortool 5 | src/*.js -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ReportGenerator 2 | 3 | [ReportGenerator](https://github.com/danielpalme/ReportGenerator) converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov into human readable reports in various formats. 4 | 5 | ## Usage 6 | Use the online [configuration tool](https://reportgenerator.io/usage) to get started quickly. 7 | The more advanced settings are documented in the [wiki](https://github.com/danielpalme/ReportGenerator/wiki/Settings). They can be applied via the `customSettings` parameter. 8 | 9 | ```yml 10 | - name: Setup .NET Core # Required to execute ReportGenerator 11 | uses: actions/setup-dotnet@v4 12 | with: 13 | dotnet-version: 8.x 14 | dotnet-quality: 'ga' 15 | 16 | - name: ReportGenerator 17 | uses: danielpalme/ReportGenerator-GitHub-Action@5.4.7 18 | with: 19 | reports: 'coverage.xml' # REQUIRED # The coverage reports that should be parsed (separated by semicolon). Globbing is supported. 20 | targetdir: 'coveragereport' # REQUIRED # The directory where the generated report should be saved. 21 | reporttypes: 'HtmlInline;Cobertura' # The output formats and scope (separated by semicolon) Values: Badges, Clover, Cobertura, OpenCover, CsvSummary, Html, Html_Dark, Html_Light, Html_BlueRed, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Dark, HtmlInline_AzurePipelines_Light, HtmlSummary, Html_BlueRed_Summary, JsonSummary, CodeClimate, Latex, LatexSummary, lcov, MarkdownSummary, MarkdownAssembliesSummary, MarkdownSummaryGithub, MarkdownDeltaSummary, MHtml, SvgChart, SonarQube, TeamCitySummary, TextSummary, TextDeltaSummary, Xml, XmlSummary 22 | sourcedirs: '' # Optional directories which contain the corresponding source code (separated by semicolon). The source directories are used if coverage report contains classes without path information. 23 | historydir: '' # Optional directory for storing persistent coverage information. Can be used in future reports to show coverage evolution. 24 | workingdir: '' # Optional working directory. If available, the targetdir, sourcedirs and historydir are interpreted relative to the working directory (only if not specified as absolute paths). 25 | plugins: '' # Optional plugin files for custom reports or custom history storage (separated by semicolon). 26 | assemblyfilters: '+*' # Optional list of assemblies that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. 27 | classfilters: '+*' # Optional list of classes that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. 28 | filefilters: '+*' # Optional list of files that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. 29 | riskhotspotassemblyfilters: '+*' # Optional list of assemblies that should be included or excluded in the risk hotspots. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. 30 | riskhotspotclassfilters: '+*' # Optional list of classes that should be included or excluded in the risk hotspots. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. 31 | verbosity: 'Info' # The verbosity level of the log messages. Values: Verbose, Info, Warning, Error, Off 32 | title: '' # Optional title. 33 | tag: '${{ github.run_number }}_${{ github.run_id }}' # Optional tag or build version. 34 | license: '' # Optional license for PRO version. Get your license here: https://reportgenerator.io/pro 35 | customSettings: '' # Optional custom settings (separated by semicolon). See: https://github.com/danielpalme/ReportGenerator/wiki/Settings. 36 | toolpath: 'reportgeneratortool' # Default directory for installing the dotnet tool. 37 | 38 | - name: Upload coverage report artifact 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: CoverageReport # Artifact name 42 | path: coveragereport # Directory containing files to upload 43 | 44 | - name: Add comment to PR # Only applicable if 'MarkdownSummaryGithub' or one of the other Markdown report types is generated 45 | if: github.event_name == 'pull_request' 46 | run: gh pr comment $PR_NUMBER --body-file coveragereport/SummaryGithub.md # Adjust path and filename if necessary 47 | env: 48 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 | PR_NUMBER: ${{ github.event.number }} 50 | 51 | - name: Publish coverage in build summary # Only applicable if 'MarkdownSummaryGithub' or one of the other Markdown report types is generated 52 | run: cat coveragereport/SummaryGithub.md >> $GITHUB_STEP_SUMMARY # Adjust path and filename if necessary 53 | shell: bash 54 | ``` 55 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'ReportGenerator' 2 | author: 'danielpalme' 3 | description: 'Creates coverage reports from tools like OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov' 4 | inputs: 5 | reports: 6 | description: 'The coverage reports that should be parsed (separated by semicolon). Globbing is supported.' 7 | required: true 8 | default: 'coverage.xml' 9 | targetdir: 10 | description: 'The directory where the generated report should be saved.' 11 | required: true 12 | default: 'coveragereport' 13 | reporttypes: 14 | description: 'The output formats and scope (separated by semicolon) Values: Badges, Clover, Cobertura, CsvSummary, Html, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Dark, HtmlSummary, Html_BlueRed_Summary, JsonSummary, Latex, LatexSummary, lcov, MHtml, SvgChart, SonarQube, TeamCitySummary, TextSummary, Xml, XmlSummary' 15 | required: false 16 | default: 'HtmlInline;Cobertura' 17 | sourcedirs: 18 | description: 'Optional directories which contain the corresponding source code (separated by semicolon). The source directories are used if coverage report contains classes without path information.' 19 | required: false 20 | default: '' 21 | historydir: 22 | description: 'Optional directory for storing persistent coverage information. Can be used in future reports to show coverage evolution.' 23 | required: false 24 | default: '' 25 | workingdir: 26 | description: 'Optional working directory. If available, the targetdir, sourcedirs and historydir are interpreted relative to the working directory (only if not specified as absolute paths).' 27 | required: false 28 | default: '' 29 | toolpath: 30 | description: 'Default directory for installing the dotnet tool.' 31 | required: false 32 | default: 'reportgeneratortool' 33 | plugins: 34 | description: 'Optional plugin files for custom reports or custom history storage (separated by semicolon).' 35 | required: false 36 | default: '' 37 | assemblyfilters: 38 | description: 'Optional list of assemblies that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed.' 39 | required: false 40 | default: '+*' 41 | classfilters: 42 | description: 'Optional list of classes that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed.' 43 | required: false 44 | default: '+*' 45 | filefilters: 46 | description: 'Optional list of files that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed.' 47 | required: false 48 | default: '+*' 49 | riskhotspotassemblyfilters: 50 | description: 'Optional list of assemblies that should be included or excluded in the risk hotspots. Exclusion filters take precedence over inclusion filters. Wildcards are allowed.' 51 | required: false 52 | default: '+*' 53 | riskhotspotclassfilters: 54 | description: 'Optional list of classes that should be included or excluded in the risk hotspots. Exclusion filters take precedence over inclusion filters. Wildcards are allowed.' 55 | required: false 56 | default: '+*' 57 | verbosity: 58 | description: 'The verbosity level of the log messages. Values: Verbose, Info, Warning, Error, Off' 59 | required: false 60 | default: 'Info' 61 | title: 62 | description: 'Optional title.' 63 | required: false 64 | default: '' 65 | tag: 66 | description: 'Optional tag or build version.' 67 | required: false 68 | default: '${{ github.run_number }}_${{ github.run_id }}' 69 | license: 70 | description: 'Optional license for PRO version. Get your license here: https://reportgenerator.io/pro' 71 | required: false 72 | default: '' 73 | customSettings: 74 | description: 'Optional custom settings (separated by semicolon). See: https://github.com/danielpalme/ReportGenerator/wiki/Settings' 75 | required: false 76 | default: '' 77 | runs: 78 | using: 'node20' 79 | main: 'dist/index.js' 80 | branding: 81 | icon: 'bar-chart-2' 82 | color: 'green' 83 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReportGenerator", 3 | "version": "5.4.7", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "ReportGenerator", 9 | "version": "5.4.7", 10 | "license": "Apache-2.0", 11 | "dependencies": { 12 | "@actions/core": "^1.11.1", 13 | "@actions/exec": "^1.1.1" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "^22.13.0", 17 | "@vercel/ncc": "^0.38.3", 18 | "typescript": "^5.8.2" 19 | } 20 | }, 21 | "node_modules/@actions/core": { 22 | "version": "1.11.1", 23 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", 24 | "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", 25 | "license": "MIT", 26 | "dependencies": { 27 | "@actions/exec": "^1.1.1", 28 | "@actions/http-client": "^2.0.1" 29 | } 30 | }, 31 | "node_modules/@actions/exec": { 32 | "version": "1.1.1", 33 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", 34 | "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", 35 | "license": "MIT", 36 | "dependencies": { 37 | "@actions/io": "^1.0.1" 38 | } 39 | }, 40 | "node_modules/@actions/http-client": { 41 | "version": "2.2.3", 42 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", 43 | "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", 44 | "license": "MIT", 45 | "dependencies": { 46 | "tunnel": "^0.0.6", 47 | "undici": "^5.25.4" 48 | } 49 | }, 50 | "node_modules/@actions/io": { 51 | "version": "1.1.3", 52 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", 53 | "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", 54 | "license": "MIT" 55 | }, 56 | "node_modules/@fastify/busboy": { 57 | "version": "2.1.1", 58 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 59 | "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 60 | "license": "MIT", 61 | "engines": { 62 | "node": ">=14" 63 | } 64 | }, 65 | "node_modules/@types/node": { 66 | "version": "22.13.0", 67 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", 68 | "integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", 69 | "dev": true, 70 | "license": "MIT", 71 | "dependencies": { 72 | "undici-types": "~6.20.0" 73 | } 74 | }, 75 | "node_modules/@vercel/ncc": { 76 | "version": "0.38.3", 77 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.3.tgz", 78 | "integrity": "sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA==", 79 | "dev": true, 80 | "license": "MIT", 81 | "bin": { 82 | "ncc": "dist/ncc/cli.js" 83 | } 84 | }, 85 | "node_modules/tunnel": { 86 | "version": "0.0.6", 87 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 88 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 89 | "license": "MIT", 90 | "engines": { 91 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 92 | } 93 | }, 94 | "node_modules/typescript": { 95 | "version": "5.8.2", 96 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", 97 | "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", 98 | "dev": true, 99 | "license": "Apache-2.0", 100 | "bin": { 101 | "tsc": "bin/tsc", 102 | "tsserver": "bin/tsserver" 103 | }, 104 | "engines": { 105 | "node": ">=14.17" 106 | } 107 | }, 108 | "node_modules/undici": { 109 | "version": "5.29.0", 110 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", 111 | "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", 112 | "license": "MIT", 113 | "dependencies": { 114 | "@fastify/busboy": "^2.0.0" 115 | }, 116 | "engines": { 117 | "node": ">=14.0" 118 | } 119 | }, 120 | "node_modules/undici-types": { 121 | "version": "6.20.0", 122 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 123 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 124 | "dev": true, 125 | "license": "MIT" 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReportGenerator", 3 | "version": "5.4.7", 4 | "description": "", 5 | "main": "lib/reportgenerator.js", 6 | "scripts": { 7 | "build": "tsc && ncc build" 8 | }, 9 | "keywords": [ 10 | "code-coverage", 11 | "testing", 12 | "tdd-utilities", 13 | "reporting", 14 | "dotnet-core" 15 | ], 16 | "author": "danielpalme", 17 | "license": "Apache-2.0", 18 | "dependencies": { 19 | "@actions/core": "^1.11.1", 20 | "@actions/exec": "^1.1.1" 21 | }, 22 | "devDependencies": { 23 | "@types/node": "^22.13.0", 24 | "@vercel/ncc": "^0.38.3", 25 | "typescript": "^5.8.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/reportgenerator.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import * as exec from '@actions/exec'; 3 | import * as fs from 'fs'; 4 | import * as path from 'path'; 5 | 6 | const VERSION = '5.4.7'; 7 | 8 | async function run() { 9 | try { 10 | core.info("Detecting .NET Core SDK"); 11 | 12 | let output = ''; 13 | let resultCode = 0; 14 | let toolpath = core.getInput('toolpath'); 15 | 16 | try { 17 | resultCode = await exec.exec( 18 | 'dotnet', 19 | ['--version'], 20 | { 21 | listeners: { 22 | stdout: (data: Buffer) => { 23 | output += data.toString(); 24 | } 25 | } 26 | } 27 | ); 28 | } catch (error) { 29 | core.setFailed(".NET Core SDK is not available."); 30 | core.info("Please install with the following command in your YAML file:"); 31 | core.info("- name: Setup .NET Core"); 32 | core.info(" uses: actions/setup-dotnet@v3"); 33 | core.info(" with"); 34 | core.info(" dotnet-version: 8.x"); 35 | core.info(" dotnet-quality: 'ga'"); 36 | return; 37 | } 38 | 39 | core.info("Detected .NET Core SDK version '" + output + "'"); 40 | 41 | if (fs.existsSync(toolpath)) { 42 | core.info("ReportGenerator global tool already installed"); 43 | } else { 44 | core.info("Installing ReportGenerator global tool (https://www.nuget.org/packages/dotnet-reportgenerator-globaltool)"); 45 | 46 | output = ''; 47 | resultCode = 0; 48 | 49 | try { 50 | resultCode = await exec.exec( 51 | 'dotnet', 52 | ['tool', 'install', 'dotnet-reportgenerator-globaltool', '--tool-path', toolpath, '--version', VERSION, '--ignore-failed-sources'], 53 | { 54 | listeners: { 55 | stdout: (data: Buffer) => { 56 | output += data.toString(); 57 | } 58 | } 59 | } 60 | ); 61 | } catch (error) { 62 | core.setFailed("Failed to install ReportGenerator global tool"); 63 | return; 64 | } 65 | 66 | core.info("Successfully installed ReportGenerator global tool"); 67 | } 68 | 69 | 70 | core.info("Executing ReportGenerator"); 71 | 72 | output = ''; 73 | resultCode = 0; 74 | 75 | try { 76 | const workingdir = (core.getInput('workingdir') || '').trim(); 77 | 78 | let targetdir = (core.getInput('targetdir') || ''); 79 | let historydir = (core.getInput('historydir') || ''); 80 | let sourcedirs = (core.getInput('sourcedirs') || ''); 81 | let reports = (core.getInput('reports') || ''); 82 | 83 | if (workingdir.length > 0) { 84 | if (targetdir.length > 0 && !path.isAbsolute(targetdir)) { 85 | targetdir = path.join(workingdir, targetdir); 86 | } 87 | if (historydir.length > 0 &&!path.isAbsolute(historydir)) { 88 | historydir = path.join(workingdir, historydir); 89 | } 90 | if (sourcedirs.length > 0) { 91 | let updatedSourcedirs = ''; 92 | 93 | sourcedirs.split(/[,;]/).forEach(sourcedir => { 94 | if (!path.isAbsolute(sourcedir)) { 95 | sourcedir = path.join(workingdir, sourcedir); 96 | } 97 | 98 | if (updatedSourcedirs.length > 0) { 99 | updatedSourcedirs += ';'; 100 | } 101 | 102 | updatedSourcedirs += sourcedir; 103 | }); 104 | 105 | sourcedirs = updatedSourcedirs; 106 | } 107 | if (reports.length > 0) { 108 | let updatedReports = ''; 109 | 110 | reports.split(/[,;]/).forEach(report => { 111 | if (!path.isAbsolute(report)) { 112 | report = path.join(workingdir, report); 113 | } 114 | 115 | if (updatedReports.length > 0) { 116 | updatedReports += ';'; 117 | } 118 | 119 | updatedReports += report; 120 | }); 121 | 122 | reports = updatedReports; 123 | } 124 | } 125 | 126 | const args = [ 127 | '-reports:' + reports, 128 | '-targetdir:' + targetdir, 129 | '-reporttypes:' + (core.getInput('reporttypes') || ''), 130 | '-sourcedirs:' + sourcedirs, 131 | '-historydir:' + historydir, 132 | '-plugins:' + (core.getInput('plugins') || ''), 133 | '-assemblyfilters:' + (core.getInput('assemblyfilters') || ''), 134 | '-classfilters:' + (core.getInput('classfilters') || ''), 135 | '-filefilters:' + (core.getInput('filefilters') || ''), 136 | '-riskhotspotassemblyfilters:' + (core.getInput('riskhotspotassemblyfilters') || ''), 137 | '-riskhotspotclassfilters:' + (core.getInput('riskhotspotclassfilters') || ''), 138 | '-verbosity:' + (core.getInput('verbosity') || ''), 139 | '-title:' + (core.getInput('title') || ''), 140 | '-tag:' + (core.getInput('tag') || ''), 141 | '-license:' + (core.getInput('license') || '') 142 | ]; 143 | 144 | const customSettings = (core.getInput('customSettings') || ''); 145 | 146 | if (customSettings.length > 0) { 147 | customSettings.split(/[,;]/).forEach(setting => { 148 | args.push(setting.trim()); 149 | }); 150 | } 151 | 152 | resultCode = await exec.exec( 153 | toolpath + '/reportgenerator', 154 | args, 155 | { 156 | listeners: { 157 | stdout: (data: Buffer) => { 158 | output += data.toString(); 159 | } 160 | } 161 | } 162 | ); 163 | } catch (error) { 164 | core.setFailed("Failed to execute ReportGenerator global tool"); 165 | return; 166 | } 167 | 168 | core.info("Successfully executed ReportGenerator"); 169 | } catch (error: any) { 170 | core.setFailed(error.message); 171 | } 172 | } 173 | 174 | run(); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 6 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | "lib": [ 8 | "es6" 9 | ], 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "./lib", /* Redirect output structure to the directory. */ 18 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | }, 65 | "exclude": ["node_modules", "**/*.test.ts"] 66 | } 67 | -------------------------------------------------------------------------------- /update-version.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [string]$From, 3 | [string]$To) 4 | 5 | Write-Host $From 6 | Write-Host $To 7 | 8 | ((Get-Content -path package.json -Raw) -replace $From, $To) | Set-Content -Path package.json -NoNewline 9 | ((Get-Content -path package-lock.json -Raw) -replace $From, $To) | Set-Content -Path package-lock.json -NoNewline 10 | ((Get-Content -path README.md -Raw) -replace $From, $To) | Set-Content -Path README.md -NoNewline 11 | ((Get-Content -path src\reportgenerator.ts -Raw) -replace $From, $To) | Set-Content -Path src\reportgenerator.ts -NoNewline 12 | 13 | npm run build 14 | 15 | git commit -a -m $To 16 | git tag -f v$To 17 | git tag -f $To 18 | git tag -f v5 19 | git tag -f 5 --------------------------------------------------------------------------------