Redesigned action to use CMake file api. (#3)

Redesign action to use the CMake file API rather than editing the environment before a regular build.
This commit is contained in:
d-winsor 2021-10-08 14:57:23 -07:00 коммит произвёл GitHub
Родитель cdb7e0fbcd
Коммит 502db28262
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
34 изменённых файлов: 12836 добавлений и 1131 удалений

81
.github/workflows/run-tests.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,81 @@
name: 'run-tests'
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * SUN'
env:
sample: '${{ github.workspace }}/test/sample'
build: '${{ github.workspace }}/test/sample/build'
result: '${{ github.workspace }}/test/sample/build/results.sarif'
jobs:
build_and_test:
name: Build and Test
runs-on: windows-latest
steps:
- name: Checkout action
uses: actions/checkout@v2.3.4
- name: Setup Node.js
uses: actions/setup-node@v2.4.0
with:
node-version: '12.x'
- name: Build
run: npm install
- name: Test
run: npm test
functional_test:
name: Functional - ${{ matrix.test }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- test: Regular
outcome: success
ignoredTargetPaths: test/sample/failure
- test: Compilation Error
outcome: failure
ignoredTargetPaths: ''
steps:
- name: Checkout action
uses: actions/checkout@v2.3.4
- name: Initialize sample CMake Project
uses: lukka/run-cmake@v3
with:
cmakeListsTxtPath: ${{ env.sample }}/CMakeLists.txt
buildDirectory: ${{ env.build }}
cmakeGenerator: VS16Win64
buildWithCMake: false
- name: Run action
id: run_action
continue-on-error: true
uses: ./
with:
cmakeBuildDirectory: ${{ env.build }}
resultPath: ${{ env.result }}
ruleset: AllRules.ruleset
ignoreSystemHeaders: true
ignoredTargetPaths: ${{ matrix.ignoredTargetPaths }}
- name: Validate expected action outcome
if: steps.run_action.outcome != matrix.outcome
run: exit 1
- name: Upload SARIF artifact
if: steps.run_action.outcome == 'success'
uses: actions/upload-artifact@v2
with:
name: sarif-file
path: ${{ steps.run_action.outputs.sarif }}
if-no-files-found: error

3
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
.vscode
node_modules/
test/sample/build/

109
README.md
Просмотреть файл

@ -1,83 +1,64 @@
# msvc-code-analysis-action
# Microsoft C++ Code Analysis Action
This action enables code analysis to run while building a project with the Microsoft Visual C++ Compiler. The analysis
will produce SARIF results that can be uploaded to the GitHub Code Scanning Alerts experience.
This actions run code analysis for any CMake project built with the Microsoft Visual C++ Compiler. The analysis
will produce SARIF results that can be uploaded to the GitHub Code Scanning Alerts experience and/or included as
an artifact to view locally in the Sarif Viewer VSCode Extension.
## Usage
### Pre-requisites
Include a workflow `.yml` file using an [example](#example) below as a template. Run the `msvc-code-analysis-action`
before re-building your project using the appropriate operation mode detailed below.
after configuring CMake for your project. Building the project is only required if the C++ source files involve the use
of generated files.
### Inputs
- `mode` (**default:** General) operation mode given different environments and build systems:
- **General:** enable Code Analysis for any build system. The MSVC compiler with the desired host and target
architecture must be available on the PATH.
- **MSBuild:** enable MSBuild Code Analysis experience. This is the preferred method if using MSBuild projects as it
can use Code Analysis settings as configured in Visual Studio.
- `results` (**default:** ${{ github.workspace }}) root directory containing all SARIF files produced in build.
This is commonly the root directory of the project (i.e. MSBuild) or build folder (i.e. CMake).
- `ruleset` (**default:** NativeRecommendedRules.ruleset) ruleset file used to determine what checks are run. This can
reference a ruleset that ship with Visual Studio or a custom file in the project.
- `cleanSarif` (**default:** true) SARIF files will under `results` directory are considered stale and will be deleted.
- `args` optional parameters to pass to every instance of the compiler.
### Examples
### Input Parameters
#### CMake
Description of all input parameters: [action.yml](https://github.com/microsoft/msvc-code-analysis-action/blob/main/action.yml)
### Example
```yml
# Use VCPKG to make MSVC discoverable on the PATH
- name: Add MSVC to the PATH
uses: lukka/run-vcpkg@v7
with:
setupOnly: true
env:
build: '${{ github.workspace }}/build'
# Configure MSVC to run code analysis during build
- name: Initialize MSVC Code Analysis
uses: microsoft/msvc-code-analysis-action
with:
# Path to directory that will contain produced sarif files
results: build
# Ruleset file that will determine what checks will be run
ruleset: NativeRecommendRules.ruleset
jobs:
build:
steps:
# Configure project with CMake
- name: Configure CMake
uses: lukka/run-cmake@v3
with:
buildDirectory: ${{ env.build }}
# Build is not require unless generated source files are used
buildWithCMake: false
cmakeGenerator: 'VS16Win64'
cmakeListsTxtPath: ${{ github.workspace }}/CMakeLists.txt
# Rebuild the project using any MSVC compatible build system
- name: Build Project
run: cmake -G Ninja -B build --clean-first
# Run Microsoft Visual C++ code analysis
- name: Initialize MSVC Code Analysis
uses: microsoft/msvc-code-analysis-action
# Provide a unique ID to access the sarif output path
id: run-analysis
with:
cmakeBuildDirectory: ${{ env.build }}
# Ruleset file that will determine what checks will be run
ruleset: NativeRecommendRules.ruleset
# Upload all SARIF files generated in the build directory tree
- name: Upload SARIF files
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: build
```
# Upload SARIF file to GitHub Code Scanning Alerts
- name: Upload SARIF to Github
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: ${{ steps.run-analysis.outputs.sarif }}
#### MSBuild
```yml
# Make MSBuild discoverable on the PATH
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
# Configure MSVC to run code analysis during build
- name: Initialize MSVC Code Analysis
uses: microsoft/msvc-code-analysis-action@v1
with:
# Root of MSBuild Solution containing all project directories
result: ${{ github.workspace }}
# Rebuild the project using MSBuild
- name: Build Project
run: msbuild Project.sln /p:Configuration=Release /p:Platform=x64 /t:rebuild
# Upload all SARIF files generated in the build directory tree
- name: Upload SARIF files
uses: github/codeql-action/upload-sarif@v1
with:
# Root of MSBuild Solution containing all project directories
sarif_file: ${{ github.workspace }}
# Upload SARIF file as an Artifact to download and view
- name: Upload SARIF as an Artifact
uses: actions/upload-artifact@v2
with:
name: sarif-file
path: ${{ steps.run-analysis.outputs.sarif }}
```
## Contributing

Просмотреть файл

@ -1,22 +1,38 @@
name: 'MSVC Code Analysis Action'
description: 'Setup MSVC to produce Code Analysis SARIF files for use in github/codeql-action/upload-sarif@v1'
name: 'Microsoft C++ Code Analysis Action'
description: 'Run Microsoft C++ Code Analysis to produce SARIF files for use in github/codeql-action/upload-sarif@v1'
inputs:
mode:
description: 'Operation mode given different environments and build systems.'
default: 'General'
results:
description: 'root directory containing all SARIF files produced in build.'
default: '${{ github.workspace }}'
cmakeBuildDirectory:
description: 'The CMake build directory that should already be generated.'
required: true
ruleset:
description: 'Ruleset file to use during analysis.'
description: 'Ruleset file used to determine what checks are run.'
default: 'NativeRecommendedRules.ruleset'
cleanSarif:
description: 'SARIF files will under `results` directory are considered stale and will be deleted.'
default: 'True'
args:
ignoredTargetPaths:
description: 'Any CMake targets defined inside these paths will be excluded from analysis. This is useful for excluding
code such as unit tests. List is ";" seperated and can be absolute or relative to "github.workspace"'
required: false
ignoredIncludePaths:
description: 'Any paths in this list will be treated as SYSTEM includes and will be excluded from analysis. This requires
"ignoreSystemHeaders == true". List is ";" seperated and can be absolute or relative to "github.workspace"'
required: false
ignoreSystemHeaders:
description: 'Uses /external arguments to ignore warnings from any headers marked as SYSTEM in CMake.'
default: true
resultsPath:
description: 'Optional path to generate the SARIF file to. If not supplied "results.sarif" will be created in the CMake
build directory. Path can be absolute or relative to "github.workspace".'
required: false
loadImplicitCompilerEnv:
description: 'Load implicit includes/libs for the given MSVC toolset using Visual Studio Command Prompt. Set to
false if already loaded or a custom include path is needed.'
default: true
additionalArgs:
description: 'Optional parameters to pass to every instance of the compiler.'
required: false
outputs:
sarif:
description: 'The path to the SARIF file that is generated containing all the results.'
runs:
using: 'node12'
main: 'index.js'
main: 'dist/index.js'

7142
dist/index.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

343
dist/licenses.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,343 @@
@actions/core
MIT
The MIT License (MIT)
Copyright 2019 GitHub
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.
@actions/exec
MIT
The MIT License (MIT)
Copyright 2019 GitHub
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.
@actions/io
MIT
The MIT License (MIT)
Copyright 2019 GitHub
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.
balanced-match
MIT
(MIT)
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
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.
brace-expansion
MIT
MIT License
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
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.
concat-map
MIT
This software is released under the MIT license:
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.
fs.realpath
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----
This library bundles a version of the `fs.realpath` and `fs.realpathSync`
methods from Node.js v0.10 under the terms of the Node.js MIT license.
Node's license follows, also included at the header of `old.js` which contains
the licensed code:
Copyright Joyent, Inc. and other Node contributors.
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.
glob
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
## Glob Logo
Glob's logo created by Tanya Brassie <http://tanyabrassie.com/>, licensed
under a Creative Commons Attribution-ShareAlike 4.0 International License
https://creativecommons.org/licenses/by-sa/4.0/
inflight
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
inherits
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
minimatch
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
once
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
path-is-absolute
MIT
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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.
rimraf
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
tmp
MIT
The MIT License (MIT)
Copyright (c) 2014 KARASZI István
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.
wrappy
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

3
dist/vc_env.bat поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
@CALL %1 %2 -vcvars_ver=%3
@ECHO INCLUDE=%INCLUDE%
@ECHO LIB=%LIB%

839
index.js
Просмотреть файл

@ -1,230 +1,749 @@
"use strict";
const core = require('@actions/core');
const exec = require('@actions/exec');
const fs = require('fs');
const io = require('@actions/io');
const path = require('path');
const util = require('util');
const tmp = require('tmp');
const toolrunner = require('@actions/exec/lib/toolrunner');
const RelativeRulesetPath = '..\\..\\..\\..\\..\\..\\..\\Team Tools\\Static Analysis Tools\\Rule Sets';
const DefaultRulesetName = 'NativeRecommendedRules.ruleset';
const CMakeApiClientName = "client-msvc-ca-action";
// Paths relative to absolute path to cl.exe
const RelativeRulesetPath = '..\\..\\..\\..\\..\\..\\..\\..\\Team Tools\\Static Analysis Tools\\Rule Sets';
const RelativeToolsetPath = '..\\..\\..\\..';
const RelativeCommandPromptPath = '..\\..\\..\\..\\..\\..\\..\\Auxiliary\\Build\\vcvarsall.bat';
//
// Utility functions
//
// Add Quoted command-line argument for MSVC that handles spaces and trailing backslashes.
function addArg(clArgs, arg) {
// find number of consecutive trailing backslashes
var i = 0;
while (i < arg.length && arg[arg.length - 1 - i] == '\\') {
i++;
}
// escape all trailing backslashes
if (i > 0) {
arg += new Array(i + 1).join('\\');
}
clArgs.push('"' + arg + '"');
/**
* Validate if the given directory both exists and is non-empty.
* @param {string} targetDir directory to test
* @returns {boolean} true if the directory is empty
*/
function isDirectoryEmpty(targetDir) {
return !targetDir || !fs.existsSync(targetDir) || (fs.readdirSync(targetDir).length) == 0;
}
// Find executable relative to the CWD or the system PATH
function findExecutableOnPath(executable) {
var paths = process.cwd() + ';' + process.env.PATH;
for (const pathDir of paths.split(';')) {
const executablePath = path.join(pathDir, executable);
if (fs.existsSync(executablePath)) {
return executablePath;
/**
* Validate if the targetDir is either equal or a sub-directory of the parentDir
* @param {string} parentDir parent directory
* @param {string} targetDir directory to test
* @returns {boolean} true if sub-directory
*/
function isSubdirectory(parentDir, targetDir) {
return path.normalize(targetDir).startsWith(path.normalize(parentDir));
}
/**
* Get normalized relative path from a given file/directory.
* @param {string} fromPath path to join relative path to
* @param {string} relativePath relative path to append
* @returns normalized path
*/
function getRelativeTo(fromPath, relativePath) {
return path.normalize(path.join(fromPath, relativePath))
}
/**
* Validate and resolve path by making non-absolute paths relative to GitHub
* repository root.
* @param {string} unresolvedPath path to resolve
* @returns the resolved absolute path
*/
function resolvePath(unresolvedPath) {
return path.normalize(path.isAbsolute(unresolvedPath) ?
unresolvedPath : path.join(process.env.GITHUB_WORKSPACE, unresolvedPath));
}
/**
* Validate and resolve action input path by making non-absolute paths relative to
* GitHub repository root.
* @param {string} input name of GitHub action input variable
* @param {boolean} required if true the input must be non-empty
* @returns the absolute path to the input path if specified
*/
function resolveInputPath(input, required = false) {
let inputPath = core.getInput(input);
if (!inputPath) {
if (required) {
throw new Error(input + " input path can not be empty.");
}
return undefined;
}
return resolvePath(inputPath, required);
}
/**
* Validate and resolve action input paths making non-absolute paths relative to
* GitHub repository root. Paths are seperated by the provided string.
* @param {string} input name of GitHub action input variable
* @param {boolean} required if true the input must be non-empty
* @returns the absolute path to the input path if specified
*/
function resolveInputPaths(input, required = false, seperator = ';') {
const inputPaths = core.getInput(input);
if (!inputPaths) {
if (required) {
throw new Error(input + " input paths can not be empty.");
}
return [];
}
return inputPaths.split(seperator)
.map((inputPath) => resolvePath(inputPath))
.filter((inputPath) => inputPath);
}
/**
* Create a query file for the CMake API
* @param {string} apiDir CMake API directory '.cmake/api/v1'
*/
async function createApiQuery(apiDir) {
const queryDir = path.join(apiDir, "query", CMakeApiClientName);
if (!fs.existsSync(queryDir)) {
await io.mkdirP(queryDir);
}
const queryFile = path.join(queryDir, "query.json");
const queryData = {
"requests": [
{ kind: "codemodel", version: 2 },
{ kind: "toolchains", version: 1 }
]};
try {
fs.writeFileSync(queryFile, JSON.stringify(queryData), 'utf-8');
} catch (err) {
throw new Error("Failed to write query.json file for CMake API.", err);
}
}
/**
* Read and parse the given JSON reply file.
* @param {string} replyFile absolute path to JSON reply
* @returns parsed JSON data of the reply file
*/
function parseReplyFile(replyFile) {
if (!fs.existsSync(replyFile)) {
throw new Error("Failed to find CMake API reply file: " + replyFile);
}
let jsonData = fs.readFileSync(replyFile, (err) => {
if (err) {
throw new Error("Failed to read CMake API reply file: " + replyFile, err);
}
});
return JSON.parse(jsonData);
}
/**
* Get the JSON filepath for the given response kind.
* @param {string} replyDir CMake API directory for replies '.cmake/api/v1/reply'
* @param {object} indexReply parsed JSON data from index-xxx.json reply
* @param {string} kind the kind of response to search for
* @returns the absolute path to the JSON response file, null if not found
*/
function getResponseFilepath(replyDir, clientResponses, kind) {
const response = clientResponses.find((response) => response["kind"] == kind);
return response ? path.join(replyDir, response.jsonFile) : null;
}
/**
* Information extracted from CMake API index reply which details all other requested responses.
* @param {string} replyDir CMake API directory for replies '.cmake/api/v1/reply'
* @param {object} indexReply parsed JSON data from index-xxx.json reply
*/
function ReplyIndexInfo(replyDir, indexReply) {
const clientResponses = indexReply.reply[CMakeApiClientName]["query.json"].responses;
this.codemodelResponseFile = getResponseFilepath(replyDir, clientResponses, "codemodel");
this.toolchainsResponseFile = getResponseFilepath(replyDir, clientResponses, "toolchains");
this.version = indexReply.cmake.version.string;
}
/**
* Load the information needed from the reply index file for the CMake API
* @param {string} apiDir CMake API directory '.cmake/api/v1'
* @returns ReplyIndexInfo info extracted from index-xxx.json reply
*/
function getApiReplyIndex(apiDir) {
const replyDir = path.join(apiDir, "reply");
let indexFilepath;
if (fs.existsSync(replyDir)) {
for (const filename of fs.readdirSync(replyDir)) {
if (filename.startsWith("index-")) {
// get the most recent index query file (ordered lexicographically)
const filepath = path.join(replyDir, filename);
if (!indexFilepath || filepath > indexFilepath) {
indexFilepath = filepath;
}
};
}
}
throw new Error(executable + ' is not accessible on the PATH');
if (!indexFilepath) {
throw new Error("Failed to find CMake API index reply file.");
}
const indexReply = parseReplyFile(indexFilepath);
const replyIndexInfo = new ReplyIndexInfo(replyDir, indexReply);
core.info(`Loaded '${indexFilepath}' reply generated from CMake API.`);
return replyIndexInfo;
}
// Ensure results directory for SARIF files exists and delete stale files if needed.
function prepareResultsDir() {
var outputDir = core.getInput('results');
if (outputDir == '') {
// set path to repo root if not specified
outputDir = process.env.GITHUB_WORKSPACE;
} else if (!path.isAbsolute(outputDir)) {
// make path relative to the repo root if not absolute
outputDir = path.join(process.env.GITHUB_WORKSPACE, outputDir);
/**
* Load reply data from the CMake API. This will:
* - Create a query file in cmake API directory requesting data needed
* - Re-run CMake on build directory to generate reply data
* - Extract required information from the index-xxx.json reply
* - Validate the version of CMake to ensure required reply data exists
* @param {string} buildRoot build directory of CMake project
* @return ReplyIndexInfo info extracted from index-xxx.json reply
*/
async function loadCMakeApiReplies(buildRoot) {
if (isDirectoryEmpty(buildRoot)) {
throw new Error("CMake build root must exist, be non-empty and be configured with CMake");
}
if (fs.existsSync(outputDir)) {
var cleanSarif = core.getInput('cleanSarif');
switch (cleanSarif.toLowerCase()) {
case 'true':
{
// delete existing Sarif files that are consider stale
files = fs.readdirSync(outputDir, { withFileTypes: true });
files.forEach(file => {
if (file.isFile() && path.extname(file.name).toLowerCase() == '.sarif') {
fs.unlinkSync(path.join(outputDir, file.name));
}
});
break;
}
case 'false':
break;
default:
throw new Error('Unsupported value for \'cleanSarif\'. Must be either \'True\' or \'False\'');
}
// validate CMake can be found on the PATH
await io.which("cmake", true);
// create CMake API query file for the generation of replies needed
const apiDir = path.join(buildRoot, ".cmake/api/v1");
await createApiQuery(apiDir);
// regenerate CMake build directory to acquire CMake file API reply
core.info(`Running CMake to generate reply data.`);
try {
await exec.exec("cmake", [ buildRoot ])
} catch (err) {
throw new Error(`CMake failed to reconfigure project with error: ${err}`);
}
return outputDir;
// load reply index generated from the CMake Api
const replyIndexInfo = getApiReplyIndex(apiDir);
if (replyIndexInfo.version < "3.20.5") {
throw new Error("Action requires CMake version >= 3.20.5");
}
return replyIndexInfo;
}
// EspXEngine.dll only exists in host/target bin for MSVC Visual Studio release.
function findEspXEngine(clPath) {
const clDir = path.dirname(clPath);
/**
* Information on compiler include path.
* @param {string} path the absolute path to the include directory
* @param {boolean} isSystem true if this should be treated as a CMake SYSTEM path
*/
function IncludePath(path, isSystem) {
this.path = path;
this.isSystem = isSystem;
}
// check if we already have the correct host/target pair
var dllPath = path.join(clDir, 'EspXEngine.dll');
if (fs.existsSync(dllPath)) {
return dllPath;
}
/**
* Information about the language and compiler being used to compile a source file.
* @param {object} toolchain ReplyIndexInfo info extracted from index-xxx.json reply
*/
function ToolchainInfo(toolchain) {
this.language = toolchain.language;
this.path = toolchain.compiler.path;
this.version = toolchain.compiler.version;
this.includes = (toolchain.compiler.implicit.includeDirectories || []).map(
(include) => new IncludePath(include, true));
var targetName = '';
var hostDir = path.dirname(clDir);
// extract toolset-version & host/target arch from folder layout in VS
this.toolsetVersion = path.basename(getRelativeTo(this.path, RelativeToolsetPath));
const targetDir = path.dirname(this.path);
const hostDir = path.dirname(targetDir);
this.targetArch = path.basename(targetDir);
switch (path.basename(hostDir)) {
case 'HostX86':
targetName = 'x86';
case 'Hostx86':
this.hostArch = 'x86';
break;
case 'HostX64':
targetName = 'x64';
case 'Hostx64':
this.hostArch = 'x64';
break;
default:
throw new Error('Unknown MSVC toolset layout');
}
dllPath = path.join(hostDir, targetName, 'EspXEngine.dll');
if (fs.existsSync(dllPath)) {
return dllPath;
}
throw new Error('Unable to find EspXEngine.dll');
}
// Find official ruleset directory using the known path of MSVC compiler in Visual Studio.
function findRulesetDirectory(clPath) {
const rulesetDirectory = path.normalize(path.join(path.dirname(clPath), RelativeRulesetPath));
/**
* Parse the toolchain-xxx.json file to find information on any MSVC toolchains used. If none are
* found issue an error.
* @param {ReplyIndexInfo} replyIndexInfo ReplyIndexInfo info extracted from index-xxx.json reply
* @returns Toolchain info extracted from toolchain-xxx.json
*/
function loadToolchainMap(replyIndexInfo) {
if (!fs.existsSync(replyIndexInfo.toolchainsResponseFile)) {
throw new Error("Failed to load toolchains response from CMake API");
}
const toolchainMap = {};
const toolchains = parseReplyFile(replyIndexInfo.toolchainsResponseFile);
const cToolchain = toolchains.toolchains.find(
(t) => t.language == "C" && t.compiler.id == "MSVC");
if (cToolchain) {
toolchainMap[cToolchain.language] = new ToolchainInfo(cToolchain);
}
const cxxToolchain = toolchains.toolchains.find(
(t) => t.language == "CXX" && t.compiler.id == "MSVC");
if (cxxToolchain) {
toolchainMap[cxxToolchain.language] = new ToolchainInfo(cxxToolchain);
}
if (Object.keys(toolchainMap).length === 0) {
throw new Error("Action requires use of MSVC for either/both C or C++.");
}
return toolchainMap;
}
/**
* Information on each compilation unit extracted from the CMake targets.
* @param {object} group compilation data shared between one or more source files
* @param {string} source absolute path to source file being compiled
*/
function CompileCommand(group, source) {
// Filepath to source file being compiled
this.source = source;
// Compiler language used
this.language = group.language;
// C++ Standard
this.standard = group.languageStandard ? group.languageStandard.standard : undefined;
// Compile command line fragments appended into a single string
this.args = (group.compileCommandFragments || []).map((c) => c.fragment).join(" ");
// includes, both regular and system
this.includes = (group.includes || []).map((inc) =>
new IncludePath(inc.path, inc.isSystem || false));
// defines
this.defines = (group.defines || []).map((d) => d.define);
}
/**
* Parse the codemodel-xxx.json and each target-xxx.json to find information on required to compile
* each source file in the project.
* @param {ReplyIndexInfo} replyIndexInfo ReplyIndexInfo info extracted from index-xxx.json reply
* @returns CompileCommand information for each compiled source file in the project
*/
function loadCompileCommands(replyIndexInfo, excludedTargetPaths) {
if (!fs.existsSync(replyIndexInfo.codemodelResponseFile)) {
throw new Error("Failed to load codemodel response from CMake API");
}
let compileCommands = [];
const codemodel = parseReplyFile(replyIndexInfo.codemodelResponseFile);
const sourceRoot = codemodel.paths.source;
const replyDir = path.dirname(replyIndexInfo.codemodelResponseFile);
const codemodelInfo = codemodel.configurations[0];
for (const targetInfo of codemodelInfo.targets) {
const targetDir = path.join(sourceRoot, codemodelInfo.directories[targetInfo.directoryIndex].source);
if (excludedTargetPaths.some((excludePath) => isSubdirectory(excludePath, targetDir))) {
continue;
}
const target = parseReplyFile(path.join(replyDir, targetInfo.jsonFile));
for (const group of target.compileGroups || []) {
for (const sourceIndex of group.sourceIndexes) {
const source = path.join(sourceRoot, target.sources[sourceIndex].path);
compileCommands.push(new CompileCommand(group, source));
}
}
}
return compileCommands;
}
/**
* Find path to EspXEngine.dll as it only exists in host/target bin for MSVC Visual Studio release.
* @param {ToolchainInfo} toolchain information on the toolchain being used
* @returns absolute path to EspXEngine.dll
*/
function findEspXEngine(toolchain) {
const hostDir = path.dirname(path.dirname(toolchain.path));
const espXEnginePath = path.join(hostDir, toolchain.hostArch, 'EspXEngine.dll');
if (fs.existsSync(espXEnginePath)) {
return espXEnginePath;
}
throw new Error(`Unable to find: ${espXEnginePath}`);
}
/**
* Find official ruleset directory using the known path of MSVC compiler in Visual Studio.
* @param {ToolchainInfo} toolchain information on the toolchain being used
* @returns absolute path to directory containing all Visual Studio rulesets
*/
function findRulesetDirectory(toolchain) {
const rulesetDirectory = getRelativeTo(toolchain.path, RelativeRulesetPath);
return fs.existsSync(rulesetDirectory) ? rulesetDirectory : undefined;
}
/**
* Find ruleset first searching relative to GitHub repository and then relative to the official ruleset directory
* shipped in Visual Studio.
* @param {string} rulesetDirectory path to directory containing all Visual Studio rulesets
* @returns path to ruleset found locally or inside Visual Studio
*/
function findRuleset(rulesetDirectory) {
var rulesetPath = core.getInput('ruleset');
if (rulesetPath == '') {
const repoRulesetPath = resolveInputPath("ruleset");
if (!repoRulesetPath) {
return undefined;
}
if (path.isAbsolute(rulesetPath)) {
return fs.existsSync(rulesetPath) ? rulesetPath : undefined;
}
// search for a path relative to the project directory
const repoRulesetPath = path.join(process.env.GITHUB_WORKSPACE, rulesetPath);
if (fs.existsSync(repoRulesetPath)) {
} else if (fs.existsSync(repoRulesetPath)) {
core.info(`Found local ruleset: ${repoRulesetPath}`);
return repoRulesetPath;
}
// search official ruleset directory that ships inside of Visual Studio
const rulesetPath = core.getInput("ruleset");
if (rulesetDirectory != undefined) {
const officialRulesetPath = path.join(rulesetDirectory, rulesetPath);
if (fs.existsSync(officialRulesetPath)) {
core.info(`Found official ruleset: ${officialRulesetPath}`);
return officialRulesetPath;
}
} else {
core.warning('Unable to find official rulesets shipped with Visual Studio');
core.warning("Unable to find official rulesets shipped with Visual Studio.");
}
throw new Error('Unable to fine ruleset specified: ' + rulesetPath);
throw new Error(`Unable to find local or official ruleset specified: ${rulesetPath}`);
}
//
// Build 'mode' functions
//
/**
* Options to enable/disable different compiler features.
*/
function CompilerCommandOptions() {
// Use /external command line options to ignore warnings in CMake SYSTEM headers.
this.ignoreSystemHeaders = core.getInput("ignoreSystemHeaders");
// Toggle whether implicit includes/libs are loaded from Visual Studio Command Prompt
this.loadImplicitCompilerEnv = core.getInput("loadImplicitCompilerEnv");
// Ignore analysis on any CMake targets defined in these paths
this.ignoredTargetPaths = resolveInputPaths("ignoredTargetPaths");
// Additional include paths to exclude from analysis
this.ignoredIncludePaths = resolveInputPaths("ignoredIncludePaths")
.map((include) => new IncludePath(include, true));
if (this.ignoredIncludePaths && !this.ignoreSystemHeaders) {
throw new Error("Use of 'ignoredIncludePaths' requires 'ignoreSystemHeaders == true'");
}
// Additional arguments to add the command-line of every analysis instance
this.additionalArgs = core.getInput("additionalArgs");
// TODO: add support to build precompiled headers before running analysis.
this.usePrecompiledHeaders = false; // core.getInput("usePrecompiledHeaders");
}
// Configuration if (mode == General).
function configureGeneralProject() {
const clArgs = ["/analyze:quiet", "/analyze:log:format:sarif"];
/**
* Construct all command-line arguments that will be common among all sources files of a given compiler.
* @param {*} toolchain information on the toolchain being used
* @param {CompilerCommandOptions} options options for different compiler features
* @returns list of analyze arguments common to the given toolchain
*/
function getCommonAnalyzeArguments(toolchain, options) {
const args = ["/analyze:only", "/analyze:quiet", "/analyze:log:format:sarif", "/nologo"];
// fine cl.exe on the corresponding EspXEngine.dll
const clPath = findExecutableOnPath('cl.exe');
const espXEngine = findEspXEngine(clPath);
addArg(clArgs, util.format('/analyze:plugin%s', espXEngine));
const espXEngine = findEspXEngine(toolchain);
args.push(`/analyze:plugin${espXEngine}`);
// find ruleset directory that ships inside of Visual Studio
const rulesetDirectory = findRulesetDirectory(clPath);
// find ruleset if specified
const rulesetDirectory = findRulesetDirectory(toolchain);
const rulesetPath = findRuleset(rulesetDirectory);
if (rulesetPath != undefined) {
addArg(clArgs, util.format('/analyze:ruleset%s', rulesetPath));
args.push(`/analyze:ruleset${rulesetPath}`);
// add ruleset directories incase user includes any official rulesets
if (rulesetDirectory != undefined) {
addArg(clArgs, util.format('/analyze:rulesetdirectory%s', rulesetDirectory));
args.push(`/analyze:rulesetdirectory${rulesetDirectory}`);
}
} else {
core.warning('Ruleset is not being used, all warnings will be enabled.');
}
if (options.ignoreSystemHeaders) {
args.push(`/external:W0`);
args.push(`/analyze:external-`);
}
if (options.additionalArgs) {
args = args.concat(toolrunner.argStringToArray(options.additionalArgs));
}
return args;
}
/**
* Extract the the implicit includes that should be used with the given compiler from the
* Visual Studio command prompt corresponding with the toolchain used. This is required
* as MSVC does not populate the CMake API `toolchain.implicit.includeDirectories` property.
* @param {ToolchainInfo} toolchain information on the toolchain being used
* @returns array of default includes used by the given MSVC toolset
*/
async function extractEnvironmentFromCommandPrompt(toolchain) {
// use bat file to output environment variable required after running 'vcvarsall.bat'
const vcEnvScript = path.join(__dirname, "vc_env.bat");
// init arguments for 'vcvarsall.bat' to match the toolset version/arch used
const commandPromptPath = getRelativeTo(toolchain.path, RelativeCommandPromptPath);
const arch = (toolchain.hostArch == toolchain.targetArch) ?
toolchain.hostArch : `${toolchain.hostArch}_${toolchain.targetArch}`;
core.info("Extracting environment from VS Command Prompt");
const execOptions = { silent: true };
const execOutput = await exec.getExecOutput(vcEnvScript,
[commandPromptPath, arch, toolchain.toolsetVersion], execOptions);
if (execOutput.exitCode != 0) {
core.debug(execOutput.stdout);
throw new Error("Failed to run VS Command Prompt to collect implicit includes/libs");
}
const env = { INCLUDE: "", LIB: "" };
for (const line of execOutput.stdout.split(/\r?\n/)) {
const index = line.indexOf('=');
if (index != -1) {
const envVar = line.substring(0, index);
if (envVar in env) {
env[envVar] = line.substring(index + 1);
}
}
}
// add additional command-line arguments to MSVC if specified
const additionalArgs = core.getInput('args');
if (additionalArgs != '') {
clArgs.push(additionalArgs);
}
// add analysis arguments to _CL_ env variable
core.exportVariable('_CL_', clArgs.join(' '));
// enable compatibility mode as GitHub does not support some sarif options
core.exportVariable('CAEmitSarifLog', '1');
return env;
}
// Configuration if (mode == MSBuild).
function configureMSBuildProject() {
/**
* Construct all environment variables that will be common among all sources files of a given compiler.
* @param {ToolchainInfo} toolchain information on the toolchain being used
* @param {CompilerCommandOptions} options options for different compiler features
* @returns map of environment variables common to the given toolchain
*/
async function getCommonAnalyzeEnvironment(toolchain, options) {
const env = {
CAEmitSarifLog: "1", // enable compatibility mode as GitHub does not support some sarif options
CAExcludePath: process.env.CAExcludePath || "",
INCLUDE: process.env.INCLUDE || "",
LIB: process.env.LIB || "",
};
// ensure ruleset is empty or not modified from default
var rulesetPath = core.getInput('ruleset');
if (rulesetPath != '' || rulesetPath != DefaultRulesetName) {
throw new Error(
'Custom ruleset not support in MSBuild mode. Configure ruleset in project or use /p:CodeAnalysisRuleset=XXX');
if (options.loadImplicitCompilerEnv) {
const commandPromptEnv = await extractEnvironmentFromCommandPrompt(toolchain);
env.CAExcludePath += `;${commandPromptEnv.INCLUDE}`; // exclude all implicit includes
env.INCLUDE += `;${commandPromptEnv.INCLUDE}`;
env.LIB += `;${commandPromptEnv.LIB}`;
}
// add additional command-line arguments to MSVC if specified
const additionalArgs = core.getInput('args');
if (additionalArgs != '') {
core.exportVariable('_CL_', additionalArgs);
}
// force Code Analysis to run
core.exportVariable('RunCodeAnalysis', 'true');
// extra redundancy in case the user has RunCodeAnalysis manually configured in project
core.exportVariable('RunCodeAnalysisOnce', 'true');
// force generation of Sarif output that us only used in the IDE experience
core.exportVariable('VCCodeAnalysisUX', 'true');
return env;
}
//
// Main
//
/**
* Information required to run analysis on a single source file.
* @param {string} source absolute path to the source file being compiled
* @param {string} compiler absolute path to compiler used
* @param {string[]} args all compilation and analyze arguments to pass to cl.exe
* @param {[key: string]: string} env environment to use when running cl.exe
* @param {string} sarifLog absolute path to SARIF log file that will be produced
*/
function AnalyzeCommand(source, compiler, args, env, sarifLog) {
this.source = source;
this.compiler = compiler;
this.args = args;
this.env = env;
this.sarifLog = sarifLog;
}
try {
const mode = core.getInput('mode');
switch (mode.toLowerCase()) {
case 'general':
configureGeneralProject()
break;
case 'msbuild':
configureMSBuildProject()
break;
default:
throw new Error('Unknown operation mode: ' + mode);
/**
* Load information needed to compile and analyze each source file in the given CMake project.
* This makes use of the CMake file API and other sources to collect this data.
* @param {string} buildRoot absolute path to the build directory of the CMake project
* @param {CompilerCommandOptions} options options for different compiler features
* @returns list of information to compile and analyze each source file in the project
*/
async function createAnalysisCommands(buildRoot, options) {
const replyIndexInfo = await loadCMakeApiReplies(buildRoot);
const toolchainMap = loadToolchainMap(replyIndexInfo);
const compileCommands = loadCompileCommands(replyIndexInfo, options.ignoredTargetPaths);
let commonArgsMap = {};
let commonEnvMap = {};
for (const toolchain of Object.values(toolchainMap)) {
if (!(toolchain.path in commonArgsMap)) {
commonArgsMap[toolchain.path] = getCommonAnalyzeArguments(toolchain, options);
commonEnvMap[toolchain.path] = await getCommonAnalyzeEnvironment(toolchain, options);
}
}
prepareResultsDir();
let analyzeCommands = []
for (const command of compileCommands) {
const toolchain = toolchainMap[command.language];
if (toolchain) {
let args = toolrunner.argStringToArray(command.args);
const allIncludes = toolchain.includes.concat(
command.includes, options.ignoredIncludePaths);
for (const include of allIncludes) {
if (options.ignoreSystemHeaders && include.isSystem) {
// TODO: filter compilers that don't support /external.
args.push(`/external:I${include.path}`);
} else {
args.push(`/I${include.path}`);
}
}
} catch (error) {
core.setFailed(error.message);
for (const define of command.defines) {
args.push(`/D${define}`);
}
args.push(command.source);
let sarifLog = null;
try {
sarifLog = tmp.fileSync({ postfix: '.sarif', discardDescriptor: true }).name;
} catch (err) {
// Clean up all temp SARIF logs
analyzeCommands.forEach(command => fs.unlinkSync(command.sarifLog));
throw Error(`Failed to create temporary file to write SARIF: ${err}`, err);
}
args.push(`/analyze:log${sarifLog}`);
args = args.concat(commonArgsMap[toolchain.path]);
analyzeCommands.push(new AnalyzeCommand(
command.source, toolchain.path, args, commonEnvMap[toolchain.path], sarifLog));
}
}
return analyzeCommands;
}
// TODO: use a more performant data-structure such a hash-set
function ResultCache() {
this.files = {};
this.addIfUnique = function(sarifResult) {
const file = sarifResult.locations[0].physicalLocation.artifactLocation.uri;
const id = sarifResult.ruleId;
const line = sarifResult.locations[0].physicalLocation.region.startLine;
const column = sarifResult.locations[0].physicalLocation.region.startColumn;
const message = sarifResult.message.text;
this.files[file] = this.files[file] || {};
this.files[file][id] = this.files[file][id] || [];
const ruleCache = this.files[file][id];
if (ruleCache.some((result) =>
result.line == line && result.column == column && result.message == message)) {
return false;
}
ruleCache.push({
line: line,
column: column,
message: message
});
return true;
};
};
function filterRun(run, resultCache) {
// remove any artifacts that don't contain results to reduce log size
run.artifacts = run.artifacts.filter(artifact => artifact.roles &&
artifact.roles.some(r => r == "resultFile"));
// remove any duplicate results from other sarif runs
run.results = run.results.filter(result => resultCache.addIfUnique(result));
return run;
}
function combineSarif(resultPath, sarifFiles) {
const resultCache = new ResultCache();
const combinedSarif = {
"version": "2.1.0",
"$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json",
"runs": []
};
for (const sarifFile of sarifFiles) {
const sarifLog = parseReplyFile(sarifFile);
combinedSarif.runs.push(filterRun(sarifLog.runs[0], resultCache));
}
try {
fs.writeFileSync(resultPath, JSON.stringify(combinedSarif), 'utf-8');
} catch (err) {
throw new Error("Failed to write combined SARIF result file.", err);
}
}
/**
* Main
*/
async function main() {
var analyzeCommands = [];
try {
const buildDir = resolveInputPath("cmakeBuildDirectory", true);
if (!fs.existsSync(buildDir)) {
throw new Error("CMake build directory does not exist. Ensure CMake is already configured.");
}
let resultPath = resolveInputPath("resultsPath", false);
if (!resultPath) {
resultPath = path.join(buildDir, "results.sarif");
} else if (!fs.existsSync(path.dirname(resultPath))) {
throw new Error("Directory of the 'resultPath' file must already exist.");
}
const options = new CompilerCommandOptions();
analyzeCommands = await createAnalysisCommands(buildDir, options);
if (analyzeCommands.length == 0) {
throw new Error('No C/C++ files were found in the project that could be analyzed.');
}
// TODO: parallelism
const failedSourceFiles = [];
for (const command of analyzeCommands) {
const execOptions = {
cwd: buildDir,
env: command.env,
};
// TODO: timeouts
core.info(`Running analysis on: ${command.source}`);
try {
await exec.exec(`"${command.compiler}"`, command.args, execOptions);
} catch (err) {
core.debug(`Compilation failed with error: ${err}`);
core.debug("Environment:");
core.debug(execOptions.env);
failedSourceFiles.push(command.source);
}
}
if (failedSourceFiles.length > 0) {
const fileList = failedSourceFiles
.map(file => path.basename(file))
.join(",");
throw new Error(`Analysis failed due to compiler errors in files: ${fileList}`);
}
const sarifResults = analyzeCommands.map(command => command.sarifLog);
combineSarif(resultPath, sarifResults);
core.setOutput("sarif", resultPath);
} catch (error) {
if (core.isDebug()) {
core.setFailed(error.stack)
} else {
core.setFailed(error)
}
} finally {
analyzeCommands.map(command => command.sarifLog)
.filter(log => fs.existsSync(log))
.forEach(log => fs.unlinkSync(log));
}
}
if (require.main === module) {
(async () => {
await main();
})();
}

12
node_modules/.package-lock.json сгенерированный поставляемый
Просмотреть файл

@ -1,12 +0,0 @@
{
"name": "msvc-code-analysis-action",
"lockfileVersion": 2,
"requires": true,
"packages": {
"node_modules/@actions/core": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.4.0.tgz",
"integrity": "sha512-CGx2ilGq5i7zSLgiiGUtBCxhRRxibJYU6Fim0Q1Wg2aQL2LTnF27zbqZOrxfvFQ55eSBW0L8uVStgtKMpa0Qlg=="
}
}
}

9
node_modules/@actions/core/LICENSE.md сгенерированный поставляемый
Просмотреть файл

@ -1,9 +0,0 @@
The MIT License (MIT)
Copyright 2019 GitHub
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.

209
node_modules/@actions/core/README.md сгенерированный поставляемый
Просмотреть файл

@ -1,209 +0,0 @@
# `@actions/core`
> Core functions for setting results, logging, registering secrets and exporting variables across actions
## Usage
### Import the package
```js
// javascript
const core = require('@actions/core');
// typescript
import * as core from '@actions/core';
```
#### Inputs/Outputs
Action inputs can be read with `getInput` which returns a `string` or `getBooleanInput` which parses a boolean based on the [yaml 1.2 specification](https://yaml.org/spec/1.2/spec.html#id2804923). If `required` set to be false, the input should have a default value in `action.yml`.
Outputs can be set with `setOutput` which makes them available to be mapped into inputs of other actions to ensure they are decoupled.
```js
const myInput = core.getInput('inputName', { required: true });
const myBooleanInput = core.getBooleanInput('booleanInputName', { required: true });
const myMultilineInput = core.getMultilineInput('multilineInputName', { required: true });
core.setOutput('outputKey', 'outputVal');
```
#### Exporting variables
Since each step runs in a separate process, you can use `exportVariable` to add it to this step and future steps environment blocks.
```js
core.exportVariable('envVar', 'Val');
```
#### Setting a secret
Setting a secret registers the secret with the runner to ensure it is masked in logs.
```js
core.setSecret('myPassword');
```
#### PATH Manipulation
To make a tool's path available in the path for the remainder of the job (without altering the machine or containers state), use `addPath`. The runner will prepend the path given to the jobs PATH.
```js
core.addPath('/path/to/mytool');
```
#### Exit codes
You should use this library to set the failing exit code for your action. If status is not set and the script runs to completion, that will lead to a success.
```js
const core = require('@actions/core');
try {
// Do stuff
}
catch (err) {
// setFailed logs the message and sets a failing exit code
core.setFailed(`Action failed with error ${err}`);
}
```
Note that `setNeutral` is not yet implemented in actions V2 but equivalent functionality is being planned.
#### Logging
Finally, this library provides some utilities for logging. Note that debug logging is hidden from the logs by default. This behavior can be toggled by enabling the [Step Debug Logs](../../docs/action-debugging.md#step-debug-logs).
```js
const core = require('@actions/core');
const myInput = core.getInput('input');
try {
core.debug('Inside try block');
if (!myInput) {
core.warning('myInput was not set');
}
if (core.isDebug()) {
// curl -v https://github.com
} else {
// curl https://github.com
}
// Do stuff
core.info('Output to the actions build log')
}
catch (err) {
core.error(`Error ${err}, action may still succeed though`);
}
```
This library can also wrap chunks of output in foldable groups.
```js
const core = require('@actions/core')
// Manually wrap output
core.startGroup('Do some function')
doSomeFunction()
core.endGroup()
// Wrap an asynchronous function call
const result = await core.group('Do something async', async () => {
const response = await doSomeHTTPRequest()
return response
})
```
#### Styling output
Colored output is supported in the Action logs via standard [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code). 3/4 bit, 8 bit and 24 bit colors are all supported.
Foreground colors:
```js
// 3/4 bit
core.info('\u001b[35mThis foreground will be magenta')
// 8 bit
core.info('\u001b[38;5;6mThis foreground will be cyan')
// 24 bit
core.info('\u001b[38;2;255;0;0mThis foreground will be bright red')
```
Background colors:
```js
// 3/4 bit
core.info('\u001b[43mThis background will be yellow');
// 8 bit
core.info('\u001b[48;5;6mThis background will be cyan')
// 24 bit
core.info('\u001b[48;2;255;0;0mThis background will be bright red')
```
Special styles:
```js
core.info('\u001b[1mBold text')
core.info('\u001b[3mItalic text')
core.info('\u001b[4mUnderlined text')
```
ANSI escape codes can be combined with one another:
```js
core.info('\u001b[31;46mRed foreground with a cyan background and \u001b[1mbold text at the end');
```
> Note: Escape codes reset at the start of each line
```js
core.info('\u001b[35mThis foreground will be magenta')
core.info('This foreground will reset to the default')
```
Manually typing escape codes can be a little difficult, but you can use third party modules such as [ansi-styles](https://github.com/chalk/ansi-styles).
```js
const style = require('ansi-styles');
core.info(style.color.ansi16m.hex('#abcdef') + 'Hello world!')
```
#### Action state
You can use this library to save state and get state for sharing information between a given wrapper action:
**action.yml**:
```yaml
name: 'Wrapper action sample'
inputs:
name:
default: 'GitHub'
runs:
using: 'node12'
main: 'main.js'
post: 'cleanup.js'
```
In action's `main.js`:
```js
const core = require('@actions/core');
core.saveState("pidToKill", 12345);
```
In action's `cleanup.js`:
```js
const core = require('@actions/core');
var pid = core.getState("pidToKill");
process.kill(pid);
```

16
node_modules/@actions/core/lib/command.d.ts сгенерированный поставляемый
Просмотреть файл

@ -1,16 +0,0 @@
interface CommandProperties {
[key: string]: any;
}
/**
* Commands
*
* Command Format:
* ::name key=value,key=value::message
*
* Examples:
* ::warning::This is the message
* ::set-env name=MY_VAR::some value
*/
export declare function issueCommand(command: string, properties: CommandProperties, message: any): void;
export declare function issue(name: string, message?: string): void;
export {};

92
node_modules/@actions/core/lib/command.js сгенерированный поставляемый
Просмотреть файл

@ -1,92 +0,0 @@
"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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.issue = exports.issueCommand = void 0;
const os = __importStar(require("os"));
const utils_1 = require("./utils");
/**
* 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;
}
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)}`;
}
}
}
}
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

1
node_modules/@actions/core/lib/command.js.map сгенерированный поставляемый
Просмотреть файл

@ -1 +0,0 @@
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAwB;AACxB,mCAAsC;AAWtC;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,UAA6B,EAC7B,OAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AAC/C,CAAC;AAPD,oCAOC;AAED,SAAgB,KAAK,CAAC,IAAY,EAAE,OAAO,GAAG,EAAE;IAC9C,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACjC,CAAC;AAFD,sBAEC;AAED,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,MAAM,OAAO;IAKX,YAAY,OAAe,EAAE,UAA6B,EAAE,OAAe;QACzE,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,iBAAiB,CAAA;SAC5B;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,QAAQ;QACN,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,OAAO,CAAA;QAEtC,IAAI,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9D,MAAM,IAAI,GAAG,CAAA;YACb,IAAI,KAAK,GAAG,IAAI,CAAA;YAChB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;oBACvC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;oBAChC,IAAI,GAAG,EAAE;wBACP,IAAI,KAAK,EAAE;4BACT,KAAK,GAAG,KAAK,CAAA;yBACd;6BAAM;4BACL,MAAM,IAAI,GAAG,CAAA;yBACd;wBAED,MAAM,IAAI,GAAG,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAA;qBAC1C;iBACF;aACF;SACF;QAED,MAAM,IAAI,GAAG,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;QACpD,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED,SAAS,UAAU,CAAC,CAAM;IACxB,OAAO,sBAAc,CAAC,CAAC,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,cAAc,CAAC,CAAM;IAC5B,OAAO,sBAAc,CAAC,CAAC,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACzB,CAAC"}

146
node_modules/@actions/core/lib/core.d.ts сгенерированный поставляемый
Просмотреть файл

@ -1,146 +0,0 @@
/**
* Interface for getInput options
*/
export interface InputOptions {
/** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */
required?: boolean;
/** Optional. Whether leading/trailing whitespace will be trimmed for the input. Defaults to true */
trimWhitespace?: boolean;
}
/**
* The code to exit an action
*/
export declare enum ExitCode {
/**
* A code indicating that the action was successful
*/
Success = 0,
/**
* A code indicating that the action was a failure
*/
Failure = 1
}
/**
* 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
*/
export declare function exportVariable(name: string, val: any): void;
/**
* Registers a secret which will get masked from logs
* @param secret value of the secret
*/
export declare function setSecret(secret: string): void;
/**
* Prepends inputPath to the PATH (for this action and future actions)
* @param inputPath
*/
export declare function addPath(inputPath: string): void;
/**
* Gets the value of an input.
* Unless trimWhitespace is set to false in InputOptions, the value is also trimmed.
* Returns an empty string if the value is not defined.
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns string
*/
export declare function getInput(name: string, options?: InputOptions): string;
/**
* Gets the values of an multiline input. Each value is also trimmed.
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns string[]
*
*/
export declare function getMultilineInput(name: string, options?: InputOptions): string[];
/**
* Gets the input value of the boolean type in the YAML 1.2 "core schema" specification.
* Support boolean input list: `true | True | TRUE | false | False | FALSE` .
* The return value is also in boolean type.
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns boolean
*/
export declare function getBooleanInput(name: string, options?: InputOptions): boolean;
/**
* 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
*/
export declare function setOutput(name: string, value: any): void;
/**
* 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.
*
*/
export declare function setCommandEcho(enabled: boolean): void;
/**
* 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
*/
export declare function setFailed(message: string | Error): void;
/**
* Gets whether Actions Step Debug is on or not
*/
export declare function isDebug(): boolean;
/**
* Writes debug message to user log
* @param message debug message
*/
export declare function debug(message: string): void;
/**
* Adds an error issue
* @param message error issue message. Errors will be converted to string via toString()
*/
export declare function error(message: string | Error): void;
/**
* Adds an warning issue
* @param message warning issue message. Errors will be converted to string via toString()
*/
export declare function warning(message: string | Error): void;
/**
* Writes info to log with console.log.
* @param message info message
*/
export declare function info(message: string): void;
/**
* Begin an output group.
*
* Output until the next `groupEnd` will be foldable in this group
*
* @param name The name of the output group
*/
export declare function startGroup(name: string): void;
/**
* End an output group.
*/
export declare function endGroup(): void;
/**
* 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
*/
export declare function group<T>(name: string, fn: () => Promise<T>): Promise<T>;
/**
* 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
*/
export declare function saveState(name: string, value: any): void;
/**
* Gets the value of an state set by this action's main execution.
*
* @param name name of the state to get
* @returns string
*/
export declare function getState(name: string): string;

294
node_modules/@actions/core/lib/core.js сгенерированный поставляемый
Просмотреть файл

@ -1,294 +0,0 @@
"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.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 });
exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0;
const command_1 = require("./command");
const file_command_1 = require("./file-command");
const utils_1 = require("./utils");
const os = __importStar(require("os"));
const path = __importStar(require("path"));
/**
* 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.
* Unless trimWhitespace is set to false in InputOptions, the value is also trimmed.
* Returns an empty string if the value is not defined.
*
* @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}`);
}
if (options && options.trimWhitespace === false) {
return val;
}
return val.trim();
}
exports.getInput = getInput;
/**
* Gets the values of an multiline input. Each value is also trimmed.
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns string[]
*
*/
function getMultilineInput(name, options) {
const inputs = getInput(name, options)
.split('\n')
.filter(x => x !== '');
return inputs;
}
exports.getMultilineInput = getMultilineInput;
/**
* Gets the input value of the boolean type in the YAML 1.2 "core schema" specification.
* Support boolean input list: `true | True | TRUE | false | False | FALSE` .
* The return value is also in boolean type.
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns boolean
*/
function getBooleanInput(name, options) {
const trueValue = ['true', 'True', 'TRUE'];
const falseValue = ['false', 'False', 'FALSE'];
const val = getInput(name, options);
if (trueValue.includes(val))
return true;
if (falseValue.includes(val))
return false;
throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` +
`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
}
exports.getBooleanInput = getBooleanInput;
/**
* 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) {
process.stdout.write(os.EOL);
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

1
node_modules/@actions/core/lib/core.js.map сгенерированный поставляемый
Просмотреть файл

@ -1 +0,0 @@
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}

1
node_modules/@actions/core/lib/file-command.d.ts сгенерированный поставляемый
Просмотреть файл

@ -1 +0,0 @@
export declare function issueCommand(command: string, message: any): void;

42
node_modules/@actions/core/lib/file-command.js сгенерированный поставляемый
Просмотреть файл

@ -1,42 +0,0 @@
"use strict";
// For internal use, subject to change.
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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.issueCommand = void 0;
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const utils_1 = require("./utils");
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

1
node_modules/@actions/core/lib/file-command.js.map сгенерированный поставляемый
Просмотреть файл

@ -1 +0,0 @@
{"version":3,"file":"file-command.js","sourceRoot":"","sources":["../src/file-command.ts"],"names":[],"mappings":";AAAA,uCAAuC;;;;;;;;;;;;;;;;;;;;;;AAEvC,mCAAmC;AACnC,uDAAuD;AAEvD,uCAAwB;AACxB,uCAAwB;AACxB,mCAAsC;AAEtC,SAAgB,YAAY,CAAC,OAAe,EAAE,OAAY;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAA;IACjD,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,IAAI,KAAK,CACb,wDAAwD,OAAO,EAAE,CAClE,CAAA;KACF;IACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;KACrD;IAED,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,sBAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QACjE,QAAQ,EAAE,MAAM;KACjB,CAAC,CAAA;AACJ,CAAC;AAdD,oCAcC"}

5
node_modules/@actions/core/lib/utils.d.ts сгенерированный поставляемый
Просмотреть файл

@ -1,5 +0,0 @@
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
export declare function toCommandValue(input: any): string;

20
node_modules/@actions/core/lib/utils.js сгенерированный поставляемый
Просмотреть файл

@ -1,20 +0,0 @@
"use strict";
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", { value: true });
exports.toCommandValue = void 0;
/**
* 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

1
node_modules/@actions/core/lib/utils.js.map сгенерированный поставляемый
Просмотреть файл

@ -1 +0,0 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA,mCAAmC;AACnC,uDAAuD;;;AAEvD;;;GAGG;AACH,SAAgB,cAAc,CAAC,KAAU;IACvC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE;QACzC,OAAO,EAAE,CAAA;KACV;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,MAAM,EAAE;QAC/D,OAAO,KAAe,CAAA;KACvB;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;AAC9B,CAAC;AAPD,wCAOC"}

41
node_modules/@actions/core/package.json сгенерированный поставляемый
Просмотреть файл

@ -1,41 +0,0 @@
{
"name": "@actions/core",
"version": "1.4.0",
"description": "Actions core lib",
"keywords": [
"github",
"actions",
"core"
],
"homepage": "https://github.com/actions/toolkit/tree/main/packages/core",
"license": "MIT",
"main": "lib/core.js",
"types": "lib/core.d.ts",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib",
"!.DS_Store"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/actions/toolkit.git",
"directory": "packages/core"
},
"scripts": {
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json",
"test": "echo \"Error: run tests from root\" && exit 1",
"tsc": "tsc"
},
"bugs": {
"url": "https://github.com/actions/toolkit/issues"
},
"devDependencies": {
"@types/node": "^12.0.2"
}
}

4031
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,5 +1,16 @@
{
"scripts": {
"test": "mocha"
},
"dependencies": {
"@actions/core": "^1.4.0"
"@actions/core": "^1.4.0",
"@actions/exec": "^1.1.0",
"@actions/io": "^1.1.1",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"mocha": "^9.0.3",
"rewire": "^5.0.0",
"testdouble": "^3.16.1",
"tmp": "^0.2.1"
}
}

379
test/cmake-api-tests.js Normal file
Просмотреть файл

@ -0,0 +1,379 @@
"use strict";
const assert = require("assert");
const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
const path = require("path");
const rewire = require("rewire");
const td = require("testdouble");
chai.use(chaiAsPromised);
const expect = chai.expect;
chai.should();
const cmakeExePath = path.normalize("C:\\path\\to\\cmake.exe");
const cmakeBuildDir = path.normalize("path\\to\\cmake\\build");
const cmakeSrcDir = path.normalize("path\\to\\project\\src");
const cmakeApiDir = path.join(cmakeBuildDir, path.normalize(".cmake\\api\\v1"));
const cmakeQueryDir = path.join(cmakeApiDir, "query");
const cmakeReplyDir = path.join(cmakeApiDir, "reply");
const clPath = "C:/VS/root/Tools/MSVC/14.29.30133/bin/Hostx86/x86/cl.exe";
const clInclude = "C:/VS/root/Tools/MSVC/14.29.30133/include";
const PATHEnv = [
path.dirname(clPath),
path.dirname(cmakeExePath)
].join(";");
const cmakeIndexReply = "index-1.json";
const cmakeCacheReply = "cache-1.json";
const cmakeCodemodelReply = "codemodel-1.json";
const cmakeToolchainsReply = "toolchains-1.json";
const cmakeTarget1Reply = "target-1.json";
const cmakeTarget2Reply = "target-2.json";
let defaultFileContents = {};
defaultFileContents[cmakeIndexReply] = {
"cmake": {
"generator": {
"multiConfig": true,
"name": "Visual Studio 17 2022"
},
"paths": {
"cmake": cmakeExePath
},
"version": {
"string": "3.21.6"
},
},
"reply" : {
"client-fake": {
"invalid": "data"
},
"client-msvc-ca-action" : {
"query.json" : {
"responses": [
{ "kind" : "cache", "jsonFile" : cmakeCacheReply },
{ "kind" : "codemodel", "jsonFile" : cmakeCodemodelReply },
{ "kind" : "toolchains", "jsonFile" : cmakeToolchainsReply }
]
}
}
}
};
defaultFileContents[cmakeCodemodelReply] = {
"kind": "codemodel",
"paths": {
"build": cmakeBuildDir,
"source": cmakeSrcDir
},
"configurations" : [
{
"name": "Regular",
"directories": [
{ "source": "." },
{ "source": "test" }
],
"targets": [
{
"directoryIndex": 0,
"jsonFile": cmakeTarget1Reply
},
{
"directoryIndex": 0,
"jsonFile": cmakeTarget2Reply
}
]
},
{
"name": "OnlyTarget2",
"directories": [
{ "source": "." }
],
"targets": [
{
"directoryIndex": 0,
"jsonFile": cmakeTarget2Reply
}
]
}
]
};
const CLangIndex = 0;
const CXXLangIndex = 1;
defaultFileContents[cmakeCacheReply] = {
"kind": "cache",
"entries": [
{ // CLangIndex
"name": "CMAKE_C_COMPILER",
"value": clPath
},
{ // CXXLangIndex
"name": "CMAKE_CXX_COMPILER",
"value": clPath
}
]
};
defaultFileContents[cmakeToolchainsReply] = {
"kind": "toolchains",
"toolchains": [
{ // CLangIndex
"language": "C",
"compiler" : {
"path": clPath,
"id": "MSVC",
"version": "14.29.30133",
"implicit": {
"includeDirectories": [
clInclude
]
}
}
},
{ // CXXLangIndex
"language": "CXX",
"compiler" : {
"path": clPath,
"id": "MSVC",
"version": "14.29.30133",
"implicit": {
"includeDirectories": [
clInclude
]
}
}
}
]
};
const sharedArgs = "/a /b /c";
const uniqueArgs = "/e /f";
const totalCompileCommands = 4;
defaultFileContents[cmakeTarget1Reply] = {
"compileGroups": [
{
"compileCommandFragments": [
{ "fragment": sharedArgs },
{ "fragment": uniqueArgs }
],
"includes": [
{ "path": "regular/include"},
{ "path": "external/include", "isSystem": true }
],
"language": "CXX",
"sourceIndexes": [
0,
2
]
},
{
"compileCommandFragments": [
{ "fragment": sharedArgs }
],
"includes": [
{ "path": "regular/include", "isSystem": false },
{ "path": "external/include", "isSystem": true }
],
"language": "C",
"sourceIndexes": [
1
]
},
],
"sources": [
{ "path" : "src/file1.cpp"},
{ "path" : "src/file2.c"},
{ "path" : "src/file3.cxx"},
]
};
defaultFileContents[cmakeTarget2Reply] = {
"compileGroups": [
{
"compileCommandFragments": [
{ "fragment": sharedArgs }
],
"includes": [
{ "path": "regular/include" },
{ "path": "external/include", "isSystem": true }
],
"defines": [
{ "define": "a=b"},
{ "define": "c=d"},
],
"language": "CXX",
"sourceIndexes": [
0
]
},
],
"sources": [
{ "path" : "src/file4.cpp"},
]
};
describe("CMakeApi", () => {
let action;
let exec;
let fs;
let io;
let getApiReplyIndex;
let loadCMakeApiReplies;
let loadToolchainMap;
let loadCompileCommands;
function setReplyContents(filename) {
const filepath = path.join(cmakeReplyDir, filename);
td.when(fs.existsSync(filepath)).thenReturn(true);
td.when(fs.readFileSync(filepath, td.matchers.anything())).thenReturn(
JSON.stringify(defaultFileContents[filename]));
}
function editReplyContents(filename, editCallback) {
const filepath = path.join(cmakeReplyDir, filename);
let contents = JSON.parse(JSON.stringify(defaultFileContents[filename]));
editCallback(contents);
td.when(fs.readFileSync(filepath, td.matchers.anything())).thenReturn(JSON.stringify(contents));
}
function validateCompileCommands(compileCommands) {
for (const command of compileCommands) {
command.args.should.contain(sharedArgs);
command.includes.length.should.equal(2);
switch (path.basename(command.source)) {
case "file1.cpp":
case "file3.cxx":
command.args.should.contain(uniqueArgs);
break;
case "file2.c":
break;
case "file4.cpp":
command.defines.should.contain("a=b");
command.defines.should.contain("c=d");
break;
default:
assert.fail("Unknown source file: " + compileCommand.source);
}
}
}
beforeEach(() => {
// modules
exec = td.replace('@actions/exec');
fs = td.replace("fs");
io = td.replace('@actions/io');
action = rewire("../index.js");
getApiReplyIndex = action.__get__("getApiReplyIndex");
loadCMakeApiReplies = action.__get__("loadCMakeApiReplies");
loadToolchainMap = action.__get__("loadToolchainMap");
loadCompileCommands = action.__get__("loadCompileCommands");
// default cmake folders
td.when(fs.existsSync(cmakeBuildDir)).thenReturn(true);
td.when(fs.existsSync(cmakeSrcDir)).thenReturn(true);
td.when(fs.existsSync(cmakeApiDir)).thenReturn(true);
td.when(fs.existsSync(cmakeQueryDir)).thenReturn(true);
td.when(fs.existsSync(cmakeReplyDir)).thenReturn(true);
// cmakeBuildDir must be non-empty
td.when(fs.readdirSync(cmakeBuildDir)).thenReturn([".cmake"]);
// cmake discoverable and successfully executable
td.when(io.which("cmake", true)).thenResolve(cmakeExePath);
td.when(exec.exec("cmake", [cmakeBuildDir])).thenResolve(0);
// default MSVC toolset
td.when(fs.existsSync(clPath)).thenReturn(true);
td.when(fs.existsSync(clInclude)).thenReturn(true);
// default reply files
td.when(fs.readdirSync(cmakeReplyDir)).thenReturn(Object.keys(defaultFileContents));
for (const filename of Object.keys(defaultFileContents)) {
setReplyContents(filename);
}
});
afterEach(() => {
td.reset();
});
// Common tests.
it("loadCompileCommands", async () => {
const replyIndexInfo = getApiReplyIndex(cmakeApiDir);
const compileCommands = loadCompileCommands(replyIndexInfo, []);
validateCompileCommands(compileCommands);
compileCommands.length.should.equal(totalCompileCommands);
});
it("filterAllCommands", async () => {
const replyIndexInfo = getApiReplyIndex(cmakeApiDir);
const compileCommands = loadCompileCommands(replyIndexInfo, [cmakeSrcDir]);
validateCompileCommands(compileCommands);
compileCommands.length.should.equal(0);
});
it("loadToolchainMap", async () => {
const replyIndexInfo = getApiReplyIndex(cmakeApiDir);
const toolchainMap = loadToolchainMap(replyIndexInfo);
toolchainMap.should.have.keys(["C", "CXX"]);
});
// only testing user errors, assume format of query/reply files is valid
describe("errors", () => {
it("empty buildRoot", async () => {
await expect(loadCMakeApiReplies("")).to.be.rejectedWith(
"CMake build root must exist, be non-empty and be configured with CMake");
});
it("buildRoot does not exist", async () => {
td.when(fs.existsSync(cmakeBuildDir)).thenReturn(false);
await expect(loadCMakeApiReplies(cmakeBuildDir)).to.be.rejectedWith(
"CMake build root must exist, be non-empty and be configured with CMake");
});
it("cmake not on path", async () => {
td.when(io.which("cmake", true)).thenReject(new Error("cmake missing"));
await expect(loadCMakeApiReplies(cmakeBuildDir)).to.be.rejectedWith("cmake missing");
});
it("cmake.exe failed to run", async () => {
td.when(exec.exec("cmake", td.matchers.anything())).thenReject(new Error());
await expect(loadCMakeApiReplies(cmakeBuildDir)).to.be.rejectedWith(
"CMake failed to reconfigure project with error:");
});
it("cmake not run (missing .cmake/api dir)", async () => {
td.when(fs.existsSync(cmakeReplyDir)).thenReturn(false);
await expect(loadCMakeApiReplies(cmakeBuildDir)).to.be.rejectedWith(
"Failed to find CMake API index reply file.");
});
it("cmake version < 3.20.5", async () => {
editReplyContents(cmakeIndexReply, (reply) => {
reply.cmake.version.string = "3.20.4";
});
await expect(loadCMakeApiReplies(cmakeBuildDir)).to.be.rejectedWith(
"Action requires CMake version >= 3.20.5");
});
it("msvc for neither C/C++", async () => {
editReplyContents(cmakeToolchainsReply, (reply) => {
reply.toolchains[CLangIndex].compiler.path = "clang.exe";
reply.toolchains[CLangIndex].compiler.id = "Clang";
reply.toolchains[CXXLangIndex].compiler.path = "clang.exe";
reply.toolchains[CXXLangIndex].compiler.id = "Clang";
});
const replyIndexInfo = getApiReplyIndex(cmakeApiDir);
expect(() => loadToolchainMap(replyIndexInfo)).to.throw(
"Action requires use of MSVC for either/both C or C++.");
});
});
});

Просмотреть файл

@ -0,0 +1,27 @@
cmake_minimum_required (VERSION 3.20.5)
project (Sample)
add_library (${PROJECT_NAME}
src/fileA.cpp
src/fileb.cpp
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)
target_include_directories (${PROJECT_NAME}
SYSTEM PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include/system
)
target_include_directories (${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include/regular
)
add_subdirectory(failure)

Просмотреть файл

@ -0,0 +1,12 @@
set(TARGET_NAME Failure)
add_library (${TARGET_NAME}
fail.cpp
)
set_target_properties(${TARGET_NAME}
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)

Просмотреть файл

@ -0,0 +1,4 @@
// This file is design to purposfully fail compilation because it should be ignored by the
// 'ignoredTargetPaths' action parameter
invalid C++

Просмотреть файл

@ -0,0 +1,8 @@
#include <string>
// Duplicate warnings will be avoided in headers included > 1 times
const char *regularHeaderFunction()
{
std::string s;
return s.c_str(); // C26816
}

Просмотреть файл

@ -0,0 +1,9 @@
#include <string>
// Marked as System header in CMake
// No warning should be issued if ignoreSystemHeaders is used
const char *systemHeaderFunction()
{
std::string s;
return s.c_str(); // C26816
}

17
test/sample/src/fileA.cpp Normal file
Просмотреть файл

@ -0,0 +1,17 @@
#include <system.h>
#include <regular.h>
#include <optional>
std::optional<int> getTempOptional() noexcept { return {}; }
void C26815() noexcept
{
if (const auto val = *getTempOptional()) // C26815
{
(void)val;
}
}
int main() noexcept {
return 0;
}

12
test/sample/src/fileB.cpp Normal file
Просмотреть файл

@ -0,0 +1,12 @@
// Include the same header as fileA to ensure duplicate warnings are not produced
#include <regular.h>
constexpr void C6001()
{
int x[4];
x[4] = 1;
}
int main() noexcept {
return 0;
}