diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..9d477d1 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +* @im-open/swat @im-open/infra-purple +/.github/CODEOWNERS @im-open/swat \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 20a52f4..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: danielpalme -liberapay: danielpalme \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..d35dcf8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,27 @@ +name: Build and Test +on: + pull_request: + paths-ignore: + - '**.md' +jobs: + build: + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macOS-latest] + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Node.js 14 + uses: actions/setup-node@v1 + with: + node-version: 14.x + - name: Build + run: npm run build + - name: Format + run: npm run format + - name: Check for unstaged changes + if: runner.os != 'windows' + run: ./check-for-unstaged-changes.sh diff --git a/.github/workflows/increment-version-on-merge.yml b/.github/workflows/increment-version-on-merge.yml new file mode 100644 index 0000000..4816a04 --- /dev/null +++ b/.github/workflows/increment-version-on-merge.yml @@ -0,0 +1,49 @@ +name: Increment Version on Merge +on: + pull_request: + types: [closed] + +jobs: + increment-version: + if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main' + + runs-on: [ubuntu-20.04] + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Increment the version + uses: actions/github-script@v4 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const util = require('util'); + const exec = util.promisify(require('child_process').exec); + + let newTag; + try { + ({ stdout: tag } = await exec(`git describe --tags --abbrev=0`)); + + tag = tag.replace('\n', '').trim(); + core.info(`The latest tag is: ${tag}`); + const majorMinorPatch = tag.split('.'); + const patch = parseInt(majorMinorPatch[2]) + 1; + newTag = `${majorMinorPatch[0]}.${majorMinorPatch[1]}.${patch}` + core.info(`The new tag is: ${newTag}`); + } + catch (error) { + newTag = 'v1.0.0'; + core.info('An error occurred getting the tags for the repo. It most likely does not have any tags to use. Defaulting to v1.0.0.'); + core.info(error); + } + + core.info(`Pushing tag '${newTag}' to the repository...`) + await github.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `refs/tags/${newTag}`, + sha: context.sha + }); diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..4dafe2b --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "none", + "arrowParens": "avoid", + "printWidth": 125 +} \ No newline at end of file diff --git a/README.md b/README.md index af7915f..85b6ef0 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,93 @@ # ReportGenerator -[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. +This action is based on [danielpalme/ReportGenerator-GitHub-Action]. + +[ReportGenerator] converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov into human readable reports in various formats. + +This action does not generate the code coverage reports itself, those must be created by a previous action. + +## Inputs +| Parameter | Is Required | Default Value | Description | +| ----------------- | ----------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `reports` | false | */**/coverage.opencover.xml | The coverage reports that should be parsed (separated by semicolon). Globbing is supported. | +| `targetdir` | false | coverage-results | The directory where the generated report should be saved. | +| `reporttypes` | false | Html;MarkdownSummary; | The output formats and scope (separated by semicolon)
Values: Badges, Clover, Cobertura, CsvSummary, Html, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Dark, HtmlSummary, JsonSummary, Latex, LatexSummary, lcov, MarkdownSummary, MHtml, PngChart, SonarQube, TeamCitySummary, TextSummary, Xml, XmlSummary | +| `sourcedirs` | false | '' | Optional directories which contain the corresponding source code (separated by semicolon). The source directories are used if coverage report contains classes without path information. | +| `historydir` | false | '' | Optional directory for storing persistent coverage information. Can be used in future reports to show coverage evolution. | +| `plugins` | false | '' | Optional plugin files for custom reports or custom history storage (separated by semicolon). | +| `assemblyfilters` | false | +* | Optional list of assemblies that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. | +| `classfilters` | false | +* | Optional list of classes that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. | +| `filefilters` | false | +* | Optional list of files that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. | +| `verbosity` | false | Info | The verbosity level of the log messages.
Values: Verbose, Info, Warning, Error, Off | +| `title` | false | '' | Optional title. | +| `tag` | false | ${{ github.run_number }}_${{ github.run_id }} | Optional tag or build version. | +| `customSettings` | false | '' | Optional custom settings (separated by semicolon). See [Settings]. | +| `toolpath` | false | reportgeneratortool | Default directory for installing the dotnet tool. | ## Usage ```yml -- name: Setup .NET Core # Required to execute ReportGenerator +- name: Setup .NET Core # Required to execute ReportGenerator uses: actions/setup-dotnet@v1 with: dotnet-version: 5.0.301 +- name: dotnet test with coverage + continue-on-error: true + run: dotnet test ${{ env.SOLUTION }} --no-restore --logger trx --configuration Release /property:CollectCoverage=True /property:CoverletOutputFormat=opencover + - name: ReportGenerator - uses: danielpalme/ReportGenerator-GitHub-Action@4.8.12 + uses: im-open/code-coverage-report-generator@4.8.12 with: - reports: 'coverage.xml' # REQUIRED # The coverage reports that should be parsed (separated by semicolon). Globbing is supported. - targetdir: 'coveragereport' # REQUIRED # The directory where the generated report should be saved. - reporttypes: 'HtmlInline;Cobertura' # The output formats and scope (separated by semicolon) Values: Badges, Clover, Cobertura, CsvSummary, Html, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Dark, HtmlSummary, JsonSummary, Latex, LatexSummary, lcov, MarkdownSummary, MHtml, PngChart, SonarQube, TeamCitySummary, TextSummary, Xml, XmlSummary - 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. - historydir: '' # Optional directory for storing persistent coverage information. Can be used in future reports to show coverage evolution. - plugins: '' # Optional plugin files for custom reports or custom history storage (separated by semicolon). - assemblyfilters: '+*' # Optional list of assemblies that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. - classfilters: '+*' # Optional list of classes that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. - filefilters: '+*' # Optional list of files that should be included or excluded in the report. Exclusion filters take precedence over inclusion filters. Wildcards are allowed. - verbosity: 'Info' # The verbosity level of the log messages. Values: Verbose, Info, Warning, Error, Off - title: '' # Optional title. - tag: '${{ github.run_number }}_${{ github.run_id }}' # Optional tag or build version. - customSettings: '' # Optional custom settings (separated by semicolon). See: https://github.com/danielpalme/ReportGenerator/wiki/Settings. - toolpath: 'reportgeneratortool' # Default directory for installing the dotnet tool. + reports: '*/**/coverage.opencover.xml' + targetdir: ${{ env.CODE_COVERAGE_DIR }}' + reporttypes: 'Html;MarkdownSummary' + sourcedirs: '' + historydir: '' + plugins: '' + assemblyfilters: '-xunit*;-Dapper;' + classfilters: '+*' + filefilters: '-Startup.cs;-Program.cs;-*.cshtml' + verbosity: 'Warning' + title: ${{ env.CODE_COVERAGE_REPORT_NAME }} + tag: '${{ github.workflow}}_${{ github.run_id }}' + customSettings: '' + toolpath: 'reportgeneratortool' - name: Upload coverage report artifact uses: actions/upload-artifact@v2.2.3 with: - name: CoverageReport # Artifact name - path: coveragereport # Directory containing files to upload + name: Coverage Report + path: ${{ env.CODE_COVERAGE_DIR }} + +- name: Create a PR comment from the summary file + uses: im-open/process-code-coverage-summary@v1.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + summary-file: '${{ env.CODE_COVERAGE_DIR }}/Summary.md' + create-pr-comment: true + create-status-check: false +``` + +## Recompiling + +If changes are made to the action's code in this repository, or its dependencies, you will need to re-compile the action. + +```sh +# Installs dependencies and bundles the code +npm run build ``` + +These commands utilize [ncc](https://github.com/vercel/ncc) to bundle the action and its dependencies into a single file located in the `dist` folder. + +## Code of Conduct + +This project has adopted the [im-open's Code of Conduct](https://github.com/im-open/.github/blob/master/CODE_OF_CONDUCT.md). + +## License + +Copyright © 2021, Extend Health, LLC. Code released under the [MIT license](LICENSE). + +[danielpalme/ReportGenerator-GitHub-Action]: https://github.com/danielpalme/ReportGenerator-GitHub-Action +[ReportGenerator]: https://github.com/danielpalme/ReportGenerator +[Settings]: https://github.com/danielpalme/ReportGenerator/wiki/Settings \ No newline at end of file diff --git a/action.yml b/action.yml index c127045..7e4ec13 100644 --- a/action.yml +++ b/action.yml @@ -1,19 +1,18 @@ -name: 'ReportGenerator' -author: 'danielpalme' +name: 'code-coverage-report-generator' description: 'Creates coverage reports from tools like OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov' inputs: reports: description: 'The coverage reports that should be parsed (separated by semicolon). Globbing is supported.' required: true - default: 'coverage.xml' + default: '*/**/coverage.opencover.xml' targetdir: description: 'The directory where the generated report should be saved.' required: true - default: 'coveragereport' + default: 'coverage-results' reporttypes: description: 'The output formats and scope (separated by semicolon) Values: Badges, Clover, Cobertura, CsvSummary, Html, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Dark, HtmlSummary, JsonSummary, Latex, LatexSummary, lcov, MHtml, PngChart, SonarQube, TeamCitySummary, TextSummary, Xml, XmlSummary' required: false - default: 'HtmlInline;Cobertura' + default: 'Html;MarkdownSummary' sourcedirs: 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.' required: false @@ -62,5 +61,5 @@ runs: using: 'node12' main: 'dist/index.js' branding: - icon: 'bar-chart-2' + icon: 'bar-chart-2' color: 'green' diff --git a/check-for-unstaged-changes.sh b/check-for-unstaged-changes.sh new file mode 100755 index 0000000..287290b --- /dev/null +++ b/check-for-unstaged-changes.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [[ "$(git status --porcelain)" != "" ]]; then + echo ---------------------------------------- + echo git status + echo ---------------------------------------- + git status + echo ---------------------------------------- + echo git diff + echo ---------------------------------------- + git diff + echo ---------------------------------------- + echo Troubleshooting + echo ---------------------------------------- + echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm run build && npm run format" + exit 1 +fi \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 92e3e12..eae2751 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,262 +1,277 @@ -module.exports = -/******/ (function(modules, runtime) { // webpackBootstrap -/******/ "use strict"; -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ var threw = true; -/******/ try { -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ threw = false; -/******/ } finally { -/******/ if(threw) delete installedModules[moduleId]; -/******/ } -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ __webpack_require__.ab = __dirname + "/"; -/******/ -/******/ // the startup function -/******/ function startup() { -/******/ // Load entry module and return exports -/******/ return __webpack_require__(267); -/******/ }; -/******/ -/******/ // run startup -/******/ return startup(); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ 1: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); +module.exports = /******/ (function (modules, runtime) { + // webpackBootstrap + /******/ 'use strict'; + /******/ // The module cache + /******/ var installedModules = {}; + /******/ + /******/ // The require function + /******/ function __webpack_require__(moduleId) { + /******/ + /******/ // Check if module is in cache + /******/ if (installedModules[moduleId]) { + /******/ return installedModules[moduleId].exports; + /******/ + } + /******/ // Create a new module (and put it into the cache) + /******/ var module = (installedModules[moduleId] = { + /******/ i: moduleId, + /******/ l: false, + /******/ exports: {} + /******/ }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const childProcess = __webpack_require__(129); -const path = __webpack_require__(622); -const util_1 = __webpack_require__(669); -const ioUtil = __webpack_require__(672); -const exec = util_1.promisify(childProcess.exec); -/** - * Copies a file or folder. - * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js - * - * @param source source path - * @param dest destination path - * @param options optional. See CopyOptions. - */ -function cp(source, dest, options = {}) { - return __awaiter(this, void 0, void 0, function* () { - const { force, recursive } = readCopyOptions(options); - const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; - // Dest is an existing file, but not forcing - if (destStat && destStat.isFile() && !force) { + /******/ + /******/ // Execute the module function + /******/ var threw = true; + /******/ try { + /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + /******/ threw = false; + /******/ + } finally { + /******/ if (threw) delete installedModules[moduleId]; + /******/ + } + /******/ + /******/ // Flag the module as loaded + /******/ module.l = true; + /******/ + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ + } + /******/ + /******/ + /******/ __webpack_require__.ab = __dirname + '/'; + /******/ + /******/ // the startup function + /******/ function startup() { + /******/ // Load entry module and return exports + /******/ return __webpack_require__(267); + /******/ + } + /******/ + /******/ // run startup + /******/ return startup(); + /******/ +})( + /************************************************************************/ + /******/ { + /***/ 1: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; + + var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports, '__esModule', { value: true }); + const childProcess = __webpack_require__(129); + const path = __webpack_require__(622); + const util_1 = __webpack_require__(669); + const ioUtil = __webpack_require__(672); + const exec = util_1.promisify(childProcess.exec); + /** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ + function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { return; - } - // If dest is an existing directory, should copy inside. - const newDest = destStat && destStat.isDirectory() - ? path.join(dest, path.basename(source)) - : dest; - if (!(yield ioUtil.exists(source))) { + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() ? path.join(dest, path.basename(source)) : dest; + if (!(yield ioUtil.exists(source))) { throw new Error(`no such file or directory: ${source}`); - } - const sourceStat = yield ioUtil.stat(source); - if (sourceStat.isDirectory()) { + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { if (!recursive) { - throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } else { + yield cpDirRecursive(source, newDest, 0, force); } - else { - yield cpDirRecursive(source, newDest, 0, force); - } - } - else { + } else { if (path.relative(source, newDest) === '') { - // a file cannot be copied to itself - throw new Error(`'${newDest}' and '${source}' are the same file`); + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); } yield copyFile(source, newDest, force); - } - }); -} -exports.cp = cp; -/** - * Moves a path. - * - * @param source source path - * @param dest destination path - * @param options optional. See MoveOptions. - */ -function mv(source, dest, options = {}) { - return __awaiter(this, void 0, void 0, function* () { - if (yield ioUtil.exists(dest)) { + } + }); + } + exports.cp = cp; + /** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ + function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { let destExists = true; if (yield ioUtil.isDirectory(dest)) { - // If dest is directory copy src into dest - dest = path.join(dest, path.basename(source)); - destExists = yield ioUtil.exists(dest); + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); } if (destExists) { - if (options.force == null || options.force) { - yield rmRF(dest); - } - else { - throw new Error('Destination already exists'); - } + if (options.force == null || options.force) { + yield rmRF(dest); + } else { + throw new Error('Destination already exists'); + } } - } - yield mkdirP(path.dirname(dest)); - yield ioUtil.rename(source, dest); - }); -} -exports.mv = mv; -/** - * Remove a path recursively with force - * - * @param inputPath path to remove - */ -function rmRF(inputPath) { - return __awaiter(this, void 0, void 0, function* () { - if (ioUtil.IS_WINDOWS) { + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); + } + exports.mv = mv; + /** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ + function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del. try { - if (yield ioUtil.isDirectory(inputPath, true)) { - yield exec(`rd /s /q "${inputPath}"`); - } - else { - yield exec(`del /f /a "${inputPath}"`); - } - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; + if (yield ioUtil.isDirectory(inputPath, true)) { + yield exec(`rd /s /q "${inputPath}"`); + } else { + yield exec(`del /f /a "${inputPath}"`); + } + } catch (err) { + // if you try to delete a file that doesn't exist, desired result is achieved + // other errors are valid + if (err.code !== 'ENOENT') throw err; } // Shelling out fails to remove a symlink folder with missing source, this unlink catches that try { - yield ioUtil.unlink(inputPath); - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; + yield ioUtil.unlink(inputPath); + } catch (err) { + // if you try to delete a file that doesn't exist, desired result is achieved + // other errors are valid + if (err.code !== 'ENOENT') throw err; } - } - else { + } else { let isDir = false; try { - isDir = yield ioUtil.isDirectory(inputPath); - } - catch (err) { - // if you try to delete a file that doesn't exist, desired result is achieved - // other errors are valid - if (err.code !== 'ENOENT') - throw err; - return; + isDir = yield ioUtil.isDirectory(inputPath); + } catch (err) { + // if you try to delete a file that doesn't exist, desired result is achieved + // other errors are valid + if (err.code !== 'ENOENT') throw err; + return; } if (isDir) { - yield exec(`rm -rf "${inputPath}"`); + yield exec(`rm -rf "${inputPath}"`); + } else { + yield ioUtil.unlink(inputPath); } - else { - yield ioUtil.unlink(inputPath); - } - } - }); -} -exports.rmRF = rmRF; -/** - * Make a directory. Creates the full path with folders in between - * Will throw if it fails - * - * @param fsPath path to create - * @returns Promise - */ -function mkdirP(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - yield ioUtil.mkdirP(fsPath); - }); -} -exports.mkdirP = mkdirP; -/** - * Returns path of a tool had the tool actually been invoked. Resolves via paths. - * If you check and the tool does not exist, it will throw. - * - * @param tool name of the tool - * @param check whether to check if tool exists - * @returns Promise path to tool - */ -function which(tool, check) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { + } + }); + } + exports.rmRF = rmRF; + /** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ + function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + yield ioUtil.mkdirP(fsPath); + }); + } + exports.mkdirP = mkdirP; + /** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ + function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { throw new Error("parameter 'tool' is required"); - } - // recursive when check=true - if (check) { + } + // recursive when check=true + if (check) { const result = yield which(tool, false); if (!result) { - if (ioUtil.IS_WINDOWS) { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); - } - else { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); - } + if (ioUtil.IS_WINDOWS) { + throw new Error( + `Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.` + ); + } else { + throw new Error( + `Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.` + ); + } } - } - try { + } + try { // build the list of extensions to try const extensions = []; if (ioUtil.IS_WINDOWS && process.env.PATHEXT) { - for (const extension of process.env.PATHEXT.split(path.delimiter)) { - if (extension) { - extensions.push(extension); - } + for (const extension of process.env.PATHEXT.split(path.delimiter)) { + if (extension) { + extensions.push(extension); } + } } // if it's rooted, return it if exists. otherwise return empty. if (ioUtil.isRooted(tool)) { - const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); - if (filePath) { - return filePath; - } - return ''; + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return filePath; + } + return ''; } // if any path separators, return empty if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) { - return ''; + return ''; } // build the list of directories // @@ -266,239 +281,252 @@ function which(tool, check) { // across platforms. const directories = []; if (process.env.PATH) { - for (const p of process.env.PATH.split(path.delimiter)) { - if (p) { - directories.push(p); - } + for (const p of process.env.PATH.split(path.delimiter)) { + if (p) { + directories.push(p); } + } } // return the first match for (const directory of directories) { - const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions); - if (filePath) { - return filePath; - } + const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions); + if (filePath) { + return filePath; + } } return ''; - } - catch (err) { + } catch (err) { throw new Error(`which failed with message ${err.message}`); - } - }); -} -exports.which = which; -function readCopyOptions(options) { - const force = options.force == null ? true : options.force; - const recursive = Boolean(options.recursive); - return { force, recursive }; -} -function cpDirRecursive(sourceDir, destDir, currentDepth, force) { - return __awaiter(this, void 0, void 0, function* () { - // Ensure there is not a run away recursive copy - if (currentDepth >= 255) - return; - currentDepth++; - yield mkdirP(destDir); - const files = yield ioUtil.readdir(sourceDir); - for (const fileName of files) { + } + }); + } + exports.which = which; + function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + return { force, recursive }; + } + function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { const srcFile = `${sourceDir}/${fileName}`; const destFile = `${destDir}/${fileName}`; const srcFileStat = yield ioUtil.lstat(srcFile); if (srcFileStat.isDirectory()) { - // Recurse - yield cpDirRecursive(srcFile, destFile, currentDepth, force); + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } else { + yield copyFile(srcFile, destFile, force); } - else { - yield copyFile(srcFile, destFile, force); - } - } - // Change the mode for the newly created directory - yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); - }); -} -// Buffered file copy -function copyFile(srcFile, destFile, force) { - return __awaiter(this, void 0, void 0, function* () { - if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + } + // Change the mode for the newly created directory + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); + } + // Buffered file copy + function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { // unlink/re-link it try { - yield ioUtil.lstat(destFile); + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield ioUtil.chmod(destFile, '0666'); yield ioUtil.unlink(destFile); - } - catch (e) { - // Try to override file permission - if (e.code === 'EPERM') { - yield ioUtil.chmod(destFile, '0666'); - yield ioUtil.unlink(destFile); - } - // other errors = it doesn't exist, no work to do + } + // other errors = it doesn't exist, no work to do } // Copy over symlink const symlinkFull = yield ioUtil.readlink(srcFile); yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); - } - else if (!(yield ioUtil.exists(destFile)) || force) { + } else if (!(yield ioUtil.exists(destFile)) || force) { yield ioUtil.copyFile(srcFile, destFile); - } - }); -} -//# sourceMappingURL=io.js.map - -/***/ }), + } + }); + } + //# sourceMappingURL=io.js.map -/***/ 9: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ + }, -"use strict"; + /***/ 9: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const os = __importStar(__webpack_require__(87)); -const events = __importStar(__webpack_require__(614)); -const child = __importStar(__webpack_require__(129)); -const path = __importStar(__webpack_require__(622)); -const io = __importStar(__webpack_require__(1)); -const ioUtil = __importStar(__webpack_require__(672)); -/* eslint-disable @typescript-eslint/unbound-method */ -const IS_WINDOWS = process.platform === 'win32'; -/* - * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. - */ -class ToolRunner extends events.EventEmitter { - constructor(toolPath, args, options) { - super(); - if (!toolPath) { + var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result['default'] = mod; + return result; + }; + Object.defineProperty(exports, '__esModule', { value: true }); + const os = __importStar(__webpack_require__(87)); + const events = __importStar(__webpack_require__(614)); + const child = __importStar(__webpack_require__(129)); + const path = __importStar(__webpack_require__(622)); + const io = __importStar(__webpack_require__(1)); + const ioUtil = __importStar(__webpack_require__(672)); + /* eslint-disable @typescript-eslint/unbound-method */ + const IS_WINDOWS = process.platform === 'win32'; + /* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ + class ToolRunner extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; } - this.toolPath = toolPath; - this.args = args || []; - this.options = options || {}; - } - _debug(message) { - if (this.options.listeners && this.options.listeners.debug) { + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { this.options.listeners.debug(message); + } } - } - _getCommandString(options, noPrefix) { - const toolPath = this._getSpawnFileName(); - const args = this._getSpawnArgs(options); - let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool - if (IS_WINDOWS) { + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (IS_WINDOWS) { // Windows + cmd file if (this._isCmdFile()) { - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; - } + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } } // Windows + verbatim else if (options.windowsVerbatimArguments) { - cmd += `"${toolPath}"`; - for (const a of args) { - cmd += ` ${a}`; - } + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } } // Windows (regular) else { - cmd += this._windowsQuoteCmdArg(toolPath); - for (const a of args) { - cmd += ` ${this._windowsQuoteCmdArg(a)}`; - } + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } } - } - else { + } else { // OSX/Linux - this can likely be improved with some form of quoting. // creating processes on Unix is fundamentally different than Windows. // on Unix, execvp() takes an arg array. cmd += toolPath; for (const a of args) { - cmd += ` ${a}`; + cmd += ` ${a}`; } + } + return cmd; } - return cmd; - } - _processLineBuffer(data, strBuffer, onLine) { - try { + _processLineBuffer(data, strBuffer, onLine) { + try { let s = strBuffer + data.toString(); let n = s.indexOf(os.EOL); while (n > -1) { - const line = s.substring(0, n); - onLine(line); - // the rest of the string ... - s = s.substring(n + os.EOL.length); - n = s.indexOf(os.EOL); + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + os.EOL.length); + n = s.indexOf(os.EOL); } strBuffer = s; - } - catch (err) { + } catch (err) { // streaming lines to console is best effort. Don't fail a build. this._debug(`error processing line. Failed with error ${err}`); + } } - } - _getSpawnFileName() { - if (IS_WINDOWS) { + _getSpawnFileName() { + if (IS_WINDOWS) { if (this._isCmdFile()) { - return process.env['COMSPEC'] || 'cmd.exe'; + return process.env['COMSPEC'] || 'cmd.exe'; } + } + return this.toolPath; } - return this.toolPath; - } - _getSpawnArgs(options) { - if (IS_WINDOWS) { + _getSpawnArgs(options) { + if (IS_WINDOWS) { if (this._isCmdFile()) { - let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; - for (const a of this.args) { - argline += ' '; - argline += options.windowsVerbatimArguments - ? a - : this._windowsQuoteCmdArg(a); - } - argline += '"'; - return [argline]; + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments ? a : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; } + } + return this.args; } - return this.args; - } - _endsWith(str, end) { - return str.endsWith(end); - } - _isCmdFile() { - const upperToolPath = this.toolPath.toUpperCase(); - return (this._endsWith(upperToolPath, '.CMD') || - this._endsWith(upperToolPath, '.BAT')); - } - _windowsQuoteCmdArg(arg) { - // for .exe, apply the normal quoting rules that libuv applies - if (!this._isCmdFile()) { - return this._uvQuoteCmdArg(arg); + _endsWith(str, end) { + return str.endsWith(end); } - // otherwise apply quoting rules specific to the cmd.exe command line parser. - // the libuv rules are generic and are not designed specifically for cmd.exe - // command line parser. - // - // for a detailed description of the cmd.exe command line parser, refer to - // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 - // need quotes for empty arg - if (!arg) { - return '""'; + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return this._endsWith(upperToolPath, '.CMD') || this._endsWith(upperToolPath, '.BAT'); } - // determine whether the arg needs to be quoted - const cmdSpecialChars = [ + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ ' ', '\t', '&', @@ -521,169 +549,159 @@ class ToolRunner extends events.EventEmitter { '<', '>', '"' - ]; - let needsQuotes = false; - for (const char of arg) { + ]; + let needsQuotes = false; + for (const char of arg) { if (cmdSpecialChars.some(x => x === char)) { - needsQuotes = true; - break; + needsQuotes = true; + break; } - } - // short-circuit if quotes not needed - if (!needsQuotes) { + } + // short-circuit if quotes not needed + if (!needsQuotes) { return arg; - } - // the following quoting rules are very similar to the rules that by libuv applies. - // - // 1) wrap the string in quotes - // - // 2) double-up quotes - i.e. " => "" - // - // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately - // doesn't work well with a cmd.exe command line. - // - // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. - // for example, the command line: - // foo.exe "myarg:""my val""" - // is parsed by a .NET console app into an arg array: - // [ "myarg:\"my val\"" ] - // which is the same end result when applying libuv quoting rules. although the actual - // command line from libuv quoting rules would look like: - // foo.exe "myarg:\"my val\"" - // - // 3) double-up slashes that precede a quote, - // e.g. hello \world => "hello \world" - // hello\"world => "hello\\""world" - // hello\\"world => "hello\\\\""world" - // hello world\ => "hello world\\" - // - // technically this is not required for a cmd.exe command line, or the batch argument parser. - // the reasons for including this as a .cmd quoting rule are: - // - // a) this is optimized for the scenario where the argument is passed from the .cmd file to an - // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. - // - // b) it's what we've been doing previously (by deferring to node default behavior) and we - // haven't heard any complaints about that aspect. - // - // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be - // escaped when used on the command line directly - even though within a .cmd file % can be escaped - // by using %%. - // - // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts - // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. - // - // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would - // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the - // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args - // to an external program. - // - // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. - // % can be escaped within a .cmd file. - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { // walk the string in reverse reverse += arg[i - 1]; if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; // double the slash - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '"'; // double the quote - } - else { - quoteHit = false; + reverse += '\\'; // double the slash + } else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } else { + quoteHit = false; } + } + reverse += '"'; + return reverse.split('').reverse().join(''); } - reverse += '"'; - return reverse - .split('') - .reverse() - .join(''); - } - _uvQuoteCmdArg(arg) { - // Tool runner wraps child_process.spawn() and needs to apply the same quoting as - // Node in certain cases where the undocumented spawn option windowsVerbatimArguments - // is used. - // - // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, - // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), - // pasting copyright notice from Node within this function: - // - // Copyright Joyent, Inc. and other Node contributors. All rights reserved. - // - // Permission is hereby granted, free of charge, to any person obtaining a copy - // of this software and associated documentation files (the "Software"), to - // deal in the Software without restriction, including without limitation the - // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - // sell copies of the Software, and to permit persons to whom the Software is - // furnished to do so, subject to the following conditions: - // - // The above copyright notice and this permission notice shall be included in - // all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - // IN THE SOFTWARE. - if (!arg) { + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + // IN THE SOFTWARE. + if (!arg) { // Need double quotation for empty argument return '""'; - } - if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { // No quotation needed return arg; - } - if (!arg.includes('"') && !arg.includes('\\')) { + } + if (!arg.includes('"') && !arg.includes('\\')) { // No embedded double quotes or backslashes, so I can just wrap // quote marks around the whole thing. return `"${arg}"`; - } - // Expected input/output: - // input : hello"world - // output: "hello\"world" - // input : hello""world - // output: "hello\"\"world" - // input : hello\world - // output: hello\world - // input : hello\\world - // output: hello\\world - // input : hello\"world - // output: "hello\\\"world" - // input : hello\\"world - // output: "hello\\\\\"world" - // input : hello world\ - // output: "hello world\\" - note the comment in libuv actually reads "hello world\" - // but it appears the comment is wrong, it should be "hello world\\" - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { // walk the string in reverse reverse += arg[i - 1]; if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '\\'; - } - else { - quoteHit = false; + reverse += '\\'; + } else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } else { + quoteHit = false; } + } + reverse += '"'; + return reverse.split('').reverse().join(''); } - reverse += '"'; - return reverse - .split('') - .reverse() - .join(''); - } - _cloneExecOptions(options) { - options = options || {}; - const result = { + _cloneExecOptions(options) { + options = options || {}; + const result = { cwd: options.cwd || process.cwd(), env: options.env || process.env, silent: options.silent || false, @@ -691,1095 +709,1205 @@ class ToolRunner extends events.EventEmitter { failOnStdErr: options.failOnStdErr || false, ignoreReturnCode: options.ignoreReturnCode || false, delay: options.delay || 10000 - }; - result.outStream = options.outStream || process.stdout; - result.errStream = options.errStream || process.stderr; - return result; - } - _getSpawnOptions(options, toolPath) { - options = options || {}; - const result = {}; - result.cwd = options.cwd; - result.env = options.env; - result['windowsVerbatimArguments'] = - options.windowsVerbatimArguments || this._isCmdFile(); - if (options.windowsVerbatimArguments) { + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { result.argv0 = `"${toolPath}"`; + } + return result; } - return result; - } - /** - * Exec a tool. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param tool path to tool to exec - * @param options optional exec options. See ExecOptions - * @returns number - */ - exec() { - return __awaiter(this, void 0, void 0, function* () { + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { // root the tool path if it is unrooted and contains relative pathing - if (!ioUtil.isRooted(this.toolPath) && - (this.toolPath.includes('/') || - (IS_WINDOWS && this.toolPath.includes('\\')))) { - // prefer options.cwd if it is specified, however options.cwd may also need to be rooted - this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + if ( + !ioUtil.isRooted(this.toolPath) && + (this.toolPath.includes('/') || (IS_WINDOWS && this.toolPath.includes('\\'))) + ) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); } // if the tool is only a file name, then resolve it from the PATH // otherwise verify it exists (add extension on Windows if necessary) this.toolPath = yield io.which(this.toolPath, true); return new Promise((resolve, reject) => { - this._debug(`exec tool: ${this.toolPath}`); - this._debug('arguments:'); - for (const arg of this.args) { - this._debug(` ${arg}`); - } - const optionsNonNull = this._cloneExecOptions(this.options); - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); - } - const state = new ExecState(optionsNonNull, this.toolPath); - state.on('debug', (message) => { - this._debug(message); - }); - const fileName = this._getSpawnFileName(); - const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); - const stdbuffer = ''; - if (cp.stdout) { - cp.stdout.on('data', (data) => { - if (this.options.listeners && this.options.listeners.stdout) { - this.options.listeners.stdout(data); - } - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(data); - } - this._processLineBuffer(data, stdbuffer, (line) => { - if (this.options.listeners && this.options.listeners.stdline) { - this.options.listeners.stdline(line); - } - }); - }); - } - const errbuffer = ''; - if (cp.stderr) { - cp.stderr.on('data', (data) => { - state.processStderr = true; - if (this.options.listeners && this.options.listeners.stderr) { - this.options.listeners.stderr(data); - } - if (!optionsNonNull.silent && - optionsNonNull.errStream && - optionsNonNull.outStream) { - const s = optionsNonNull.failOnStdErr - ? optionsNonNull.errStream - : optionsNonNull.outStream; - s.write(data); - } - this._processLineBuffer(data, errbuffer, (line) => { - if (this.options.listeners && this.options.listeners.errline) { - this.options.listeners.errline(line); - } - }); - }); - } - cp.on('error', (err) => { - state.processError = err.message; - state.processExited = true; - state.processClosed = true; - state.CheckComplete(); - }); - cp.on('exit', (code) => { - state.processExitCode = code; - state.processExited = true; - this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); - state.CheckComplete(); - }); - cp.on('close', (code) => { - state.processExitCode = code; - state.processExited = true; - state.processClosed = true; - this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); - state.CheckComplete(); - }); - state.on('done', (error, exitCode) => { - if (stdbuffer.length > 0) { - this.emit('stdline', stdbuffer); - } - if (errbuffer.length > 0) { - this.emit('errline', errbuffer); - } - cp.removeAllListeners(); - if (error) { - reject(error); - } - else { - resolve(exitCode); + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', message => { + this._debug(message); + }); + const fileName = this._getSpawnFileName(); + const cp = child.spawn( + fileName, + this._getSpawnArgs(optionsNonNull), + this._getSpawnOptions(this.options, fileName) + ); + const stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', data => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + this._processLineBuffer(data, stdbuffer, line => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); } + }); }); - if (this.options.input) { - if (!cp.stdin) { - throw new Error('child process missing stdin'); + } + const errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', data => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && optionsNonNull.errStream && optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream; + s.write(data); + } + this._processLineBuffer(data, errbuffer, line => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); } - cp.stdin.end(this.options.input); + }); + }); + } + cp.on('error', err => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', code => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', code => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); } + cp.removeAllListeners(); + if (error) { + reject(error); + } else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } }); - }); - } -} -exports.ToolRunner = ToolRunner; -/** - * Convert an arg string to an array of args. Handles escaping - * - * @param argString string of arguments - * @returns string[] array of arguments - */ -function argStringToArray(argString) { - const args = []; - let inQuotes = false; - let escaped = false; - let arg = ''; - function append(c) { - // we only escape double quotes. - if (escaped && c !== '"') { + }); + } + } + exports.ToolRunner = ToolRunner; + /** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ + function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { arg += '\\'; + } + arg += c; + escaped = false; } - arg += c; - escaped = false; - } - for (let i = 0; i < argString.length; i++) { - const c = argString.charAt(i); - if (c === '"') { + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { if (!escaped) { - inQuotes = !inQuotes; - } - else { - append(c); + inQuotes = !inQuotes; + } else { + append(c); } continue; - } - if (c === '\\' && escaped) { + } + if (c === '\\' && escaped) { append(c); continue; - } - if (c === '\\' && inQuotes) { + } + if (c === '\\' && inQuotes) { escaped = true; continue; - } - if (c === ' ' && !inQuotes) { + } + if (c === ' ' && !inQuotes) { if (arg.length > 0) { - args.push(arg); - arg = ''; + args.push(arg); + arg = ''; } continue; + } + append(c); } - append(c); - } - if (arg.length > 0) { - args.push(arg.trim()); - } - return args; -} -exports.argStringToArray = argStringToArray; -class ExecState extends events.EventEmitter { - constructor(options, toolPath) { - super(); - this.processClosed = false; // tracks whether the process has exited and stdio is closed - this.processError = ''; - this.processExitCode = 0; - this.processExited = false; // tracks whether the process has exited - this.processStderr = false; // tracks whether stderr was written to - this.delay = 10000; // 10 seconds - this.done = false; - this.timeout = null; - if (!toolPath) { - throw new Error('toolPath must not be empty'); + if (arg.length > 0) { + args.push(arg.trim()); } - this.options = options; - this.toolPath = toolPath; - if (options.delay) { + return args; + } + exports.argStringToArray = argStringToArray; + class ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { this.delay = options.delay; + } } - } - CheckComplete() { - if (this.done) { + CheckComplete() { + if (this.done) { return; - } - if (this.processClosed) { + } + if (this.processClosed) { this._setResult(); - } - else if (this.processExited) { + } else if (this.processExited) { this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this); + } } - } - _debug(message) { - this.emit('debug', message); - } - _setResult() { - // determine whether there is an error - let error; - if (this.processExited) { + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { if (this.processError) { - error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); - } - else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { - error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + error = new Error( + `There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}` + ); + } else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } else if (this.processStderr && this.options.failOnStdErr) { + error = new Error( + `The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream` + ); } - else if (this.processStderr && this.options.failOnStdErr) { - error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); - } - } - // clear the timeout - if (this.timeout) { + } + // clear the timeout + if (this.timeout) { clearTimeout(this.timeout); this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); } - this.done = true; - this.emit('done', error, this.processExitCode); - } - static HandleTimeout(state) { - if (state.done) { + static HandleTimeout(state) { + if (state.done) { return; - } - if (!state.processClosed && state.processExited) { - const message = `The STDIO streams did not close within ${state.delay / - 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${ + state.delay / 1000 + } seconds of the exit event from process '${ + state.toolPath + }'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; state._debug(message); + } + state._setResult(); } - state._setResult(); - } -} -//# sourceMappingURL=toolrunner.js.map + } + //# sourceMappingURL=toolrunner.js.map -/***/ }), - -/***/ 82: -/***/ (function(__unusedmodule, exports) { - -"use strict"; - -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Sanitizes an input into a string so it can be passed into issueCommand safely - * @param input input to sanitize into a string - */ -function toCommandValue(input) { - if (input === null || input === undefined) { - return ''; - } - else if (typeof input === 'string' || input instanceof String) { - return input; - } - return JSON.stringify(input); -} -exports.toCommandValue = toCommandValue; -//# sourceMappingURL=utils.js.map + /***/ + }, -/***/ }), + /***/ 82: /***/ function (__unusedmodule, exports) { + 'use strict'; -/***/ 87: -/***/ (function(module) { - -module.exports = require("os"); + // We use any as a valid input type + /* eslint-disable @typescript-eslint/no-explicit-any */ + Object.defineProperty(exports, '__esModule', { value: true }); + /** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ + function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); + } + exports.toCommandValue = toCommandValue; + //# sourceMappingURL=utils.js.map -/***/ }), + /***/ + }, -/***/ 102: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ 87: /***/ function (module) { + module.exports = require('os'); -"use strict"; + /***/ + }, -// For internal use, subject to change. -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__webpack_require__(747)); -const os = __importStar(__webpack_require__(87)); -const utils_1 = __webpack_require__(82); -function issueCommand(command, message) { - const filePath = process.env[`GITHUB_${command}`]; - if (!filePath) { - throw new Error(`Unable to find environment variable for file command ${command}`); - } - if (!fs.existsSync(filePath)) { - throw new Error(`Missing file at path: ${filePath}`); - } - fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { - encoding: 'utf8' - }); -} -exports.issueCommand = issueCommand; -//# sourceMappingURL=file-command.js.map + /***/ 102: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -/***/ }), - -/***/ 129: -/***/ (function(module) { + // For internal use, subject to change. + var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result['default'] = mod; + return result; + }; + Object.defineProperty(exports, '__esModule', { value: true }); + // We use any as a valid input type + /* eslint-disable @typescript-eslint/no-explicit-any */ + const fs = __importStar(__webpack_require__(747)); + const os = __importStar(__webpack_require__(87)); + const utils_1 = __webpack_require__(82); + function issueCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { + encoding: 'utf8' + }); + } + exports.issueCommand = issueCommand; + //# sourceMappingURL=file-command.js.map -module.exports = require("child_process"); + /***/ + }, -/***/ }), + /***/ 129: /***/ function (module) { + module.exports = require('child_process'); -/***/ 267: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ + }, -"use strict"; + /***/ 267: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const core = __importStar(__webpack_require__(470)); -const exec = __importStar(__webpack_require__(986)); -const fs = __importStar(__webpack_require__(747)); -const VERSION = '4.8.12'; -function run() { - return __awaiter(this, void 0, void 0, function* () { - try { - core.info("Detecting .NET Core SDK"); + var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { + enumerable: true, + get: function () { + return m[k]; + } + }); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, 'default', { enumerable: true, value: v }); + } + : function (o, v) { + o['default'] = v; + }); + var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k in mod) + if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports, '__esModule', { value: true }); + const core = __importStar(__webpack_require__(470)); + const exec = __importStar(__webpack_require__(986)); + const fs = __importStar(__webpack_require__(747)); + const VERSION = '4.8.12'; + function run() { + return __awaiter(this, void 0, void 0, function* () { + try { + core.info('Detecting .NET Core SDK'); let output = ''; let resultCode = 0; let toolpath = core.getInput('toolpath'); try { - resultCode = yield exec.exec('dotnet', ['--version'], { - listeners: { - stdout: (data) => { - output += data.toString(); - } - } - }); - } - catch (error) { - core.setFailed(".NET Core SDK is not available."); - core.info("Please install with the following command in your YAML file:"); - core.info("- name: Setup .NET Core"); - core.info(" uses: actions/setup-dotnet@v1"); - core.info(" with"); - core.info(" dotnet-version: '5.0.301'"); - return; + resultCode = yield exec.exec('dotnet', ['--version'], { + listeners: { + stdout: data => { + output += data.toString(); + } + } + }); + } catch (error) { + core.setFailed('.NET Core SDK is not available.'); + core.info('Please install with the following command in your YAML file:'); + core.info('- name: Setup .NET Core'); + core.info(' uses: actions/setup-dotnet@v1'); + core.info(' with'); + core.info(" dotnet-version: '5.0.301'"); + return; } core.info("Detected .NET Core SDK version '" + output + "'"); if (fs.existsSync(toolpath)) { - core.info("ReportGenerator global tool already installed"); - } - else { - core.info("Installing ReportGenerator global tool (https://www.nuget.org/packages/dotnet-reportgenerator-globaltool)"); - output = ''; - resultCode = 0; - try { - resultCode = yield exec.exec('dotnet', ['tool', 'install', 'dotnet-reportgenerator-globaltool', '--tool-path', toolpath, '--version', VERSION, '--ignore-failed-sources'], { - listeners: { - stdout: (data) => { - output += data.toString(); - } - } - }); - } - catch (error) { - core.setFailed("Failed to install ReportGenerator global tool"); - return; - } - core.info("Successfully installed ReportGenerator global tool"); + core.info('ReportGenerator global tool already installed'); + } else { + core.info( + 'Installing ReportGenerator global tool (https://www.nuget.org/packages/dotnet-reportgenerator-globaltool)' + ); + output = ''; + resultCode = 0; + try { + resultCode = yield exec.exec( + 'dotnet', + [ + 'tool', + 'install', + 'dotnet-reportgenerator-globaltool', + '--tool-path', + toolpath, + '--version', + VERSION, + '--ignore-failed-sources' + ], + { + listeners: { + stdout: data => { + output += data.toString(); + } + } + } + ); + } catch (error) { + core.setFailed('Failed to install ReportGenerator global tool'); + return; + } + core.info('Successfully installed ReportGenerator global tool'); } - core.info("Executing ReportGenerator"); + core.info('Executing ReportGenerator'); output = ''; resultCode = 0; try { - let args = [ - '-reports:' + (core.getInput('reports') || ''), - '-targetdir:' + (core.getInput('targetdir') || ''), - '-reporttypes:' + (core.getInput('reporttypes') || ''), - '-sourcedirs:' + (core.getInput('sourcedirs') || ''), - '-historydir:' + (core.getInput('historydir') || ''), - '-plugins:' + (core.getInput('plugins') || ''), - '-assemblyfilters:' + (core.getInput('assemblyfilters') || ''), - '-classfilters:' + (core.getInput('classfilters') || ''), - '-filefilters:' + (core.getInput('filefilters') || ''), - '-verbosity:' + (core.getInput('verbosity') || ''), - '-title:' + (core.getInput('title') || ''), - '-tag:' + (core.getInput('tag') || '') - ]; - const customSettings = (core.getInput('customSettings') || ''); - if (customSettings.length > 0) { - customSettings.split(';').forEach(setting => { - args.push(setting.trim()); - }); - } - resultCode = yield exec.exec(toolpath + '/reportgenerator', args, { - listeners: { - stdout: (data) => { - output += data.toString(); - } - } + let args = [ + '-reports:' + (core.getInput('reports') || ''), + '-targetdir:' + (core.getInput('targetdir') || ''), + '-reporttypes:' + (core.getInput('reporttypes') || ''), + '-sourcedirs:' + (core.getInput('sourcedirs') || ''), + '-historydir:' + (core.getInput('historydir') || ''), + '-plugins:' + (core.getInput('plugins') || ''), + '-assemblyfilters:' + (core.getInput('assemblyfilters') || ''), + '-classfilters:' + (core.getInput('classfilters') || ''), + '-filefilters:' + (core.getInput('filefilters') || ''), + '-verbosity:' + (core.getInput('verbosity') || ''), + '-title:' + (core.getInput('title') || ''), + '-tag:' + (core.getInput('tag') || '') + ]; + const customSettings = core.getInput('customSettings') || ''; + if (customSettings.length > 0) { + customSettings.split(';').forEach(setting => { + args.push(setting.trim()); }); + } + resultCode = yield exec.exec(toolpath + '/reportgenerator', args, { + listeners: { + stdout: data => { + output += data.toString(); + } + } + }); + } catch (error) { + core.setFailed('Failed to execute ReportGenerator global tool'); + return; } - catch (error) { - core.setFailed("Failed to execute ReportGenerator global tool"); - return; - } - core.info("Successfully executed ReportGenerator"); - } - catch (error) { + core.info('Successfully executed ReportGenerator'); + } catch (error) { core.setFailed(error.message); - } - }); -} -run(); - - -/***/ }), - -/***/ 357: -/***/ (function(module) { + } + }); + } + run(); -module.exports = require("assert"); + /***/ + }, -/***/ }), + /***/ 357: /***/ function (module) { + module.exports = require('assert'); -/***/ 431: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ + }, -"use strict"; + /***/ 431: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const os = __importStar(__webpack_require__(87)); -const utils_1 = __webpack_require__(82); -/** - * Commands - * - * Command Format: - * ::name key=value,key=value::message - * - * Examples: - * ::warning::This is the message - * ::set-env name=MY_VAR::some value - */ -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); -} -exports.issueCommand = issueCommand; -function issue(name, message = '') { - issueCommand(name, {}, message); -} -exports.issue = issue; -const CMD_STRING = '::'; -class Command { - constructor(command, properties, message) { - if (!command) { + var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result['default'] = mod; + return result; + }; + Object.defineProperty(exports, '__esModule', { value: true }); + const os = __importStar(__webpack_require__(87)); + const utils_1 = __webpack_require__(82); + /** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ + function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); + } + exports.issueCommand = issueCommand; + function issue(name, message = '') { + issueCommand(name, {}, message); + } + exports.issue = issue; + const CMD_STRING = '::'; + class Command { + constructor(command, properties, message) { + if (!command) { command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; } - this.command = command; - this.properties = properties; - this.message = message; - } - toString() { - let cmdStr = CMD_STRING + this.command; - if (this.properties && Object.keys(this.properties).length > 0) { + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { cmdStr += ' '; let first = true; for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key]; - if (val) { - if (first) { - first = false; - } - else { - cmdStr += ','; - } - cmdStr += `${key}=${escapeProperty(val)}`; - } + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; } + } } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; } - cmdStr += `${CMD_STRING}${escapeData(this.message)}`; - return cmdStr; - } -} -function escapeData(s) { - return utils_1.toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A'); -} -function escapeProperty(s) { - return utils_1.toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A') - .replace(/:/g, '%3A') - .replace(/,/g, '%2C'); -} -//# sourceMappingURL=command.js.map - -/***/ }), + } + function escapeData(s) { + return utils_1.toCommandValue(s).replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A'); + } + function escapeProperty(s) { + return utils_1 + .toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); + } + //# sourceMappingURL=command.js.map -/***/ 470: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ + }, -"use strict"; + /***/ 470: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const command_1 = __webpack_require__(431); -const file_command_1 = __webpack_require__(102); -const utils_1 = __webpack_require__(82); -const os = __importStar(__webpack_require__(87)); -const path = __importStar(__webpack_require__(622)); -/** - * The code to exit an action - */ -var ExitCode; -(function (ExitCode) { - /** - * A code indicating that the action was successful - */ - ExitCode[ExitCode["Success"] = 0] = "Success"; - /** - * A code indicating that the action was a failure - */ - ExitCode[ExitCode["Failure"] = 1] = "Failure"; -})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); -//----------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------- -/** - * Sets env variable for this action and future actions in the job - * @param name the name of the variable to set - * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function exportVariable(name, val) { - const convertedVal = utils_1.toCommandValue(val); - process.env[name] = convertedVal; - const filePath = process.env['GITHUB_ENV'] || ''; - if (filePath) { - const delimiter = '_GitHubActionsFileCommandDelimeter_'; - const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; - file_command_1.issueCommand('ENV', commandValue); - } - else { - command_1.issueCommand('set-env', { name }, convertedVal); - } -} -exports.exportVariable = exportVariable; -/** - * Registers a secret which will get masked from logs - * @param secret value of the secret - */ -function setSecret(secret) { - command_1.issueCommand('add-mask', {}, secret); -} -exports.setSecret = setSecret; -/** - * Prepends inputPath to the PATH (for this action and future actions) - * @param inputPath - */ -function addPath(inputPath) { - const filePath = process.env['GITHUB_PATH'] || ''; - if (filePath) { - file_command_1.issueCommand('PATH', inputPath); - } - else { - command_1.issueCommand('add-path', {}, inputPath); - } - process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; -} -exports.addPath = addPath; -/** - * Gets the value of an input. The value is also trimmed. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string - */ -function getInput(name, options) { - const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; - if (options && options.required && !val) { - throw new Error(`Input required and not supplied: ${name}`); - } - return val.trim(); -} -exports.getInput = getInput; -/** - * Sets the value of an output. - * - * @param name name of the output to set - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function setOutput(name, value) { - command_1.issueCommand('set-output', { name }, value); -} -exports.setOutput = setOutput; -/** - * Enables or disables the echoing of commands into stdout for the rest of the step. - * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. - * - */ -function setCommandEcho(enabled) { - command_1.issue('echo', enabled ? 'on' : 'off'); -} -exports.setCommandEcho = setCommandEcho; -//----------------------------------------------------------------------- -// Results -//----------------------------------------------------------------------- -/** - * Sets the action status to failed. - * When the action exits it will be with an exit code of 1 - * @param message add error issue message - */ -function setFailed(message) { - process.exitCode = ExitCode.Failure; - error(message); -} -exports.setFailed = setFailed; -//----------------------------------------------------------------------- -// Logging Commands -//----------------------------------------------------------------------- -/** - * Gets whether Actions Step Debug is on or not - */ -function isDebug() { - return process.env['RUNNER_DEBUG'] === '1'; -} -exports.isDebug = isDebug; -/** - * Writes debug message to user log - * @param message debug message - */ -function debug(message) { - command_1.issueCommand('debug', {}, message); -} -exports.debug = debug; -/** - * Adds an error issue - * @param message error issue message. Errors will be converted to string via toString() - */ -function error(message) { - command_1.issue('error', message instanceof Error ? message.toString() : message); -} -exports.error = error; -/** - * Adds an warning issue - * @param message warning issue message. Errors will be converted to string via toString() - */ -function warning(message) { - command_1.issue('warning', message instanceof Error ? message.toString() : message); -} -exports.warning = warning; -/** - * Writes info to log with console.log. - * @param message info message - */ -function info(message) { - process.stdout.write(message + os.EOL); -} -exports.info = info; -/** - * Begin an output group. - * - * Output until the next `groupEnd` will be foldable in this group - * - * @param name The name of the output group - */ -function startGroup(name) { - command_1.issue('group', name); -} -exports.startGroup = startGroup; -/** - * End an output group. - */ -function endGroup() { - command_1.issue('endgroup'); -} -exports.endGroup = endGroup; -/** - * Wrap an asynchronous function call in a group. - * - * Returns the same type as the function itself. - * - * @param name The name of the group - * @param fn The function to wrap in the group - */ -function group(name, fn) { - return __awaiter(this, void 0, void 0, function* () { - startGroup(name); - let result; - try { - result = yield fn(); + var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result['default'] = mod; + return result; + }; + Object.defineProperty(exports, '__esModule', { value: true }); + const command_1 = __webpack_require__(431); + const file_command_1 = __webpack_require__(102); + const utils_1 = __webpack_require__(82); + const os = __importStar(__webpack_require__(87)); + const path = __importStar(__webpack_require__(622)); + /** + * The code to exit an action + */ + var ExitCode; + (function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[(ExitCode['Success'] = 0)] = 'Success'; + /** + * A code indicating that the action was a failure + */ + ExitCode[(ExitCode['Failure'] = 1)] = 'Failure'; + })((ExitCode = exports.ExitCode || (exports.ExitCode = {}))); + //----------------------------------------------------------------------- + // Variables + //----------------------------------------------------------------------- + /** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function exportVariable(name, val) { + const convertedVal = utils_1.toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + const delimiter = '_GitHubActionsFileCommandDelimeter_'; + const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; + file_command_1.issueCommand('ENV', commandValue); + } else { + command_1.issueCommand('set-env', { name }, convertedVal); } - finally { - endGroup(); + } + exports.exportVariable = exportVariable; + /** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ + function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); + } + exports.setSecret = setSecret; + /** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ + function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_1.issueCommand('PATH', inputPath); + } else { + command_1.issueCommand('add-path', {}, inputPath); } - return result; - }); -} -exports.group = group; -//----------------------------------------------------------------------- -// Wrapper action state -//----------------------------------------------------------------------- -/** - * Saves state for current action, the state can only be retrieved by this action's post job execution. - * - * @param name name of the state to store - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function saveState(name, value) { - command_1.issueCommand('save-state', { name }, value); -} -exports.saveState = saveState; -/** - * Gets the value of an state set by this action's main execution. - * - * @param name name of the state to get - * @returns string - */ -function getState(name) { - return process.env[`STATE_${name}`] || ''; -} -exports.getState = getState; -//# sourceMappingURL=core.js.map - -/***/ }), - -/***/ 614: -/***/ (function(module) { - -module.exports = require("events"); - -/***/ }), + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; + } + exports.addPath = addPath; + /** + * Gets the value of an input. The value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ + function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + return val.trim(); + } + exports.getInput = getInput; + /** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function setOutput(name, value) { + command_1.issueCommand('set-output', { name }, value); + } + exports.setOutput = setOutput; + /** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ + function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); + } + exports.setCommandEcho = setCommandEcho; + //----------------------------------------------------------------------- + // Results + //----------------------------------------------------------------------- + /** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ + function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); + } + exports.setFailed = setFailed; + //----------------------------------------------------------------------- + // Logging Commands + //----------------------------------------------------------------------- + /** + * Gets whether Actions Step Debug is on or not + */ + function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; + } + exports.isDebug = isDebug; + /** + * Writes debug message to user log + * @param message debug message + */ + function debug(message) { + command_1.issueCommand('debug', {}, message); + } + exports.debug = debug; + /** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + */ + function error(message) { + command_1.issue('error', message instanceof Error ? message.toString() : message); + } + exports.error = error; + /** + * Adds an warning issue + * @param message warning issue message. Errors will be converted to string via toString() + */ + function warning(message) { + command_1.issue('warning', message instanceof Error ? message.toString() : message); + } + exports.warning = warning; + /** + * Writes info to log with console.log. + * @param message info message + */ + function info(message) { + process.stdout.write(message + os.EOL); + } + exports.info = info; + /** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ + function startGroup(name) { + command_1.issue('group', name); + } + exports.startGroup = startGroup; + /** + * End an output group. + */ + function endGroup() { + command_1.issue('endgroup'); + } + exports.endGroup = endGroup; + /** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ + function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } finally { + endGroup(); + } + return result; + }); + } + exports.group = group; + //----------------------------------------------------------------------- + // Wrapper action state + //----------------------------------------------------------------------- + /** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function saveState(name, value) { + command_1.issueCommand('save-state', { name }, value); + } + exports.saveState = saveState; + /** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ + function getState(name) { + return process.env[`STATE_${name}`] || ''; + } + exports.getState = getState; + //# sourceMappingURL=core.js.map -/***/ 622: -/***/ (function(module) { + /***/ + }, -module.exports = require("path"); + /***/ 614: /***/ function (module) { + module.exports = require('events'); -/***/ }), + /***/ + }, -/***/ 669: -/***/ (function(module) { + /***/ 622: /***/ function (module) { + module.exports = require('path'); -module.exports = require("util"); + /***/ + }, -/***/ }), + /***/ 669: /***/ function (module) { + module.exports = require('util'); -/***/ 672: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ + }, -"use strict"; + /***/ 672: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var _a; -Object.defineProperty(exports, "__esModule", { value: true }); -const assert_1 = __webpack_require__(357); -const fs = __webpack_require__(747); -const path = __webpack_require__(622); -_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; -exports.IS_WINDOWS = process.platform === 'win32'; -function exists(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - try { + var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var _a; + Object.defineProperty(exports, '__esModule', { value: true }); + const assert_1 = __webpack_require__(357); + const fs = __webpack_require__(747); + const path = __webpack_require__(622); + (_a = fs.promises), + (exports.chmod = _a.chmod), + (exports.copyFile = _a.copyFile), + (exports.lstat = _a.lstat), + (exports.mkdir = _a.mkdir), + (exports.readdir = _a.readdir), + (exports.readlink = _a.readlink), + (exports.rename = _a.rename), + (exports.rmdir = _a.rmdir), + (exports.stat = _a.stat), + (exports.symlink = _a.symlink), + (exports.unlink = _a.unlink); + exports.IS_WINDOWS = process.platform === 'win32'; + function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { yield exports.stat(fsPath); - } - catch (err) { + } catch (err) { if (err.code === 'ENOENT') { - return false; + return false; } throw err; + } + return true; + }); + } + exports.exists = exists; + function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); + } + exports.isDirectory = isDirectory; + /** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ + function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); } - return true; - }); -} -exports.exists = exists; -function isDirectory(fsPath, useStat = false) { - return __awaiter(this, void 0, void 0, function* () { - const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); - return stats.isDirectory(); - }); -} -exports.isDirectory = isDirectory; -/** - * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: - * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). - */ -function isRooted(p) { - p = normalizeSeparators(p); - if (!p) { - throw new Error('isRooted() parameter "p" cannot be empty'); - } - if (exports.IS_WINDOWS) { - return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello - ); // e.g. C: or C:\hello - } - return p.startsWith('/'); -} -exports.isRooted = isRooted; -/** - * Recursively create a directory at `fsPath`. - * - * This implementation is optimistic, meaning it attempts to create the full - * path first, and backs up the path stack from there. - * - * @param fsPath The path to create - * @param maxDepth The maximum recursion depth - * @param depth The current recursion depth - */ -function mkdirP(fsPath, maxDepth = 1000, depth = 1) { - return __awaiter(this, void 0, void 0, function* () { - assert_1.ok(fsPath, 'a path argument must be provided'); - fsPath = path.resolve(fsPath); - if (depth >= maxDepth) - return exports.mkdir(fsPath); - try { + if (exports.IS_WINDOWS) { + return ( + p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); + } + exports.isRooted = isRooted; + /** + * Recursively create a directory at `fsPath`. + * + * This implementation is optimistic, meaning it attempts to create the full + * path first, and backs up the path stack from there. + * + * @param fsPath The path to create + * @param maxDepth The maximum recursion depth + * @param depth The current recursion depth + */ + function mkdirP(fsPath, maxDepth = 1000, depth = 1) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + fsPath = path.resolve(fsPath); + if (depth >= maxDepth) return exports.mkdir(fsPath); + try { yield exports.mkdir(fsPath); return; - } - catch (err) { + } catch (err) { switch (err.code) { - case 'ENOENT': { - yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1); - yield exports.mkdir(fsPath); - return; - } - default: { - let stats; - try { - stats = yield exports.stat(fsPath); - } - catch (err2) { - throw err; - } - if (!stats.isDirectory()) - throw err; + case 'ENOENT': { + yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1); + yield exports.mkdir(fsPath); + return; + } + default: { + let stats; + try { + stats = yield exports.stat(fsPath); + } catch (err2) { + throw err; } + if (!stats.isDirectory()) throw err; + } } - } - }); -} -exports.mkdirP = mkdirP; -/** - * Best effort attempt to determine whether a file exists and is executable. - * @param filePath file path to check - * @param extensions additional file extensions to try - * @return if file exists and is executable, returns the file path. otherwise empty string. - */ -function tryGetExecutablePath(filePath, extensions) { - return __awaiter(this, void 0, void 0, function* () { - let stats = undefined; - try { + } + }); + } + exports.mkdirP = mkdirP; + /** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ + function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { // test file exists stats = yield exports.stat(filePath); - } - catch (err) { + } catch (err) { if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); } - } - if (stats && stats.isFile()) { + } + if (stats && stats.isFile()) { if (exports.IS_WINDOWS) { - // on Windows, test for valid extension - const upperExt = path.extname(filePath).toUpperCase(); - if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { - return filePath; - } + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } else { + if (isUnixExecutable(stats)) { + return filePath; + } } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - // try each extension - const originalFilePath = filePath; - for (const extension of extensions) { + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { filePath = originalFilePath + extension; stats = undefined; try { - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } + stats = yield exports.stat(filePath); + } catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } } if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // preserve the case of the actual file (since an extension was appended) - try { - const directory = path.dirname(filePath); - const upperName = path.basename(filePath).toUpperCase(); - for (const actualName of yield exports.readdir(directory)) { - if (upperName === actualName.toUpperCase()) { - filePath = path.join(directory, actualName); - break; - } - } - } - catch (err) { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; } - return filePath; + } + } catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); } - else { - if (isUnixExecutable(stats)) { - return filePath; - } + return filePath; + } else { + if (isUnixExecutable(stats)) { + return filePath; } + } } + } + return ''; + }); + } + exports.tryGetExecutablePath = tryGetExecutablePath; + function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); } - return ''; - }); -} -exports.tryGetExecutablePath = tryGetExecutablePath; -function normalizeSeparators(p) { - p = p || ''; - if (exports.IS_WINDOWS) { - // convert slashes on Windows - p = p.replace(/\//g, '\\'); // remove redundant slashes - return p.replace(/\\\\+/g, '\\'); - } - // remove redundant slashes - return p.replace(/\/\/+/g, '/'); -} -// on Mac/Linux, test the execute bit -// R W X R W X R W X -// 256 128 64 32 16 8 4 2 1 -function isUnixExecutable(stats) { - return ((stats.mode & 1) > 0 || - ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || - ((stats.mode & 64) > 0 && stats.uid === process.getuid())); -} -//# sourceMappingURL=io-util.js.map - -/***/ }), + return p.replace(/\/\/+/g, '/'); + } + // on Mac/Linux, test the execute bit + // R W X R W X R W X + // 256 128 64 32 16 8 4 2 1 + function isUnixExecutable(stats) { + return ( + (stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid()) + ); + } + //# sourceMappingURL=io-util.js.map -/***/ 747: -/***/ (function(module) { + /***/ + }, -module.exports = require("fs"); + /***/ 747: /***/ function (module) { + module.exports = require('fs'); -/***/ }), + /***/ + }, -/***/ 986: -/***/ (function(__unusedmodule, exports, __webpack_require__) { + /***/ 986: /***/ function (__unusedmodule, exports, __webpack_require__) { + 'use strict'; -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const tr = __importStar(__webpack_require__(9)); -/** - * Exec a command. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code - */ -function exec(commandLine, args, options) { - return __awaiter(this, void 0, void 0, function* () { - const commandArgs = tr.argStringToArray(commandLine); - if (commandArgs.length === 0) { + var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result['default'] = mod; + return result; + }; + Object.defineProperty(exports, '__esModule', { value: true }); + const tr = __importStar(__webpack_require__(9)); + /** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ + function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { throw new Error(`Parameter 'commandLine' cannot be null or empty.`); - } - // Path to tool to execute should be first arg - const toolPath = commandArgs[0]; - args = commandArgs.slice(1).concat(args || []); - const runner = new tr.ToolRunner(toolPath, args, options); - return runner.exec(); - }); -} -exports.exec = exec; -//# sourceMappingURL=exec.js.map + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); + } + exports.exec = exec; + //# sourceMappingURL=exec.js.map -/***/ }) + /***/ + } -/******/ }); \ No newline at end of file + /******/ + } +); diff --git a/package-lock.json b/package-lock.json index 3139257..9a7e160 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "ReportGenerator", + "name": "code-coverage-report-generator", "version": "4.8.12", "lockfileVersion": 1, "requires": true, @@ -34,6 +34,18 @@ "integrity": "sha512-jnCLpLXWuw/PAiJiVbLjA8WBC0IJQbFeUwF4I9M+23MvIxTxk5pD4Q8byQBSPmHQjz5aBoA7AKAElQxMpjrCLQ==", "dev": true }, + "husky": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.1.tgz", + "integrity": "sha512-gceRaITVZ+cJH9sNHqx5tFwbzlLCVxtVZcusME8JYQ8Edy5mpGDOqD8QBCdMhpyo9a+JXddnujQ4rpY2Ff9SJA==", + "dev": true + }, + "prettier": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "dev": true + }, "typescript": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", diff --git a/package.json b/package.json index f2c6469..1901e60 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,18 @@ { - "name": "ReportGenerator", + "name": "code-coverage-report-generator", "version": "4.8.12", "description": "", "main": "lib/reportgenerator.js", "scripts": { - "build": "tsc && ncc build" + "build": "npm ci && tsc && ncc build", + "format": "prettier --write **/*.js", + "format-check": "prettier --check **/*.js" + }, + "husky": { + "hooks": { + "pre-commit": "npm run build && npm run format", + "pre-push": "npm run format-check" + } }, "keywords": [ "code-coverage", @@ -13,15 +21,17 @@ "reporting", "dotnet-core" ], - "author": "danielpalme", + "author": "wtw", "license": "Apache-2.0", "dependencies": { "@actions/core": "^1.2.6", "@actions/exec": "^1.0.4" }, "devDependencies": { + "@types/node": "^14.11.2", "@zeit/ncc": "^0.22.3", - "typescript": "^4.0.3", - "@types/node": "^14.11.2" + "husky": "^7.0.1", + "prettier": "^2.3.2", + "typescript": "^4.0.3" } } diff --git a/src/reportgenerator.ts b/src/reportgenerator.ts index 4415c08..e783e26 100644 --- a/src/reportgenerator.ts +++ b/src/reportgenerator.ts @@ -33,7 +33,7 @@ async function run() { core.info(" dotnet-version: '5.0.301'"); return; } - + core.info("Detected .NET Core SDK version '" + output + "'"); if (fs.existsSync(toolpath)) { @@ -43,7 +43,7 @@ async function run() { output = ''; resultCode = 0; - + try { resultCode = await exec.exec( 'dotnet', @@ -60,10 +60,10 @@ async function run() { core.setFailed("Failed to install ReportGenerator global tool"); return; } - + core.info("Successfully installed ReportGenerator global tool"); } - + core.info("Executing ReportGenerator"); @@ -89,9 +89,9 @@ async function run() { const customSettings = (core.getInput('customSettings') || ''); if (customSettings.length > 0) { - customSettings.split(';').forEach(setting => { - args.push(setting.trim()); - }); + customSettings.split(';').forEach(setting => { + args.push(setting.trim()); + }); } resultCode = await exec.exec(