mirror of
https://github.com/github/codeql-action.git
synced 2026-06-02 20:04:28 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0439b41d07 |
@@ -1,4 +1,4 @@
|
|||||||
name: "CodeQL config"
|
name: 1
|
||||||
queries:
|
queries:
|
||||||
- name: Run custom queries
|
- name: Run custom queries
|
||||||
uses: ./queries
|
uses: ./queries
|
||||||
@@ -11,4 +11,3 @@ queries:
|
|||||||
- uses: security-and-quality
|
- uses: security-and-quality
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- tests
|
- tests
|
||||||
- lib
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
### Merge / deployment checklist
|
### Merge / deployment checklist
|
||||||
|
|
||||||
|
- Run test builds as necessary. Can be on this repository or elsewhere as needed in order to test the change - please include links to tests in other repos!
|
||||||
|
- [ ] CodeQL using init/analyze actions
|
||||||
|
- [ ] 3rd party tool using upload action
|
||||||
- [ ] Confirm this change is backwards compatible with existing workflows.
|
- [ ] Confirm this change is backwards compatible with existing workflows.
|
||||||
- [ ] Confirm the [readme](https://github.com/github/codeql-action/blob/master/README.md) has been updated if necessary.
|
- [ ] Confirm the [readme](https://github.com/github/codeql-action/blob/master/README.md) has been updated if necessary.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
# Must fetch at least the immediate parents so that if this is
|
# Must fetch at least the immediate parents so that if this is
|
||||||
# a pull request then we can checkout the head of the pull request.
|
# a pull request then we can checkout the head of the pull request.
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
multi-language-repo_test-custom-queries-and-remote-config:
|
multi-language-repo_test-custom-queries:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: cpp,csharp,java,javascript,python
|
languages: cpp,csharp,java,javascript,python
|
||||||
config-file: github/codeql-action/tests/multi-language-repo/.github/codeql/custom-queries.yml@${{ github.sha }}
|
config-file: ./.github/codeql/custom-queries.yml
|
||||||
- name: Build code
|
- name: Build code
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./build.sh
|
run: ./build.sh
|
||||||
@@ -93,6 +93,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TEST_MODE: true
|
TEST_MODE: true
|
||||||
|
|
||||||
|
|
||||||
multi-language-repo_rubocop:
|
multi-language-repo_rubocop:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
@@ -123,30 +124,3 @@ jobs:
|
|||||||
sarif_file: rubocop.sarif
|
sarif_file: rubocop.sarif
|
||||||
env:
|
env:
|
||||||
TEST_MODE: true
|
TEST_MODE: true
|
||||||
|
|
||||||
test-proxy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ubuntu:18.04
|
|
||||||
options: --dns 127.0.0.1
|
|
||||||
services:
|
|
||||||
squid-proxy:
|
|
||||||
image: datadog/squid:latest
|
|
||||||
ports:
|
|
||||||
- 3128:3128
|
|
||||||
env:
|
|
||||||
https_proxy: http://squid-proxy:3128
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Move codeql-action
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir ../action
|
|
||||||
mv * .github ../action/
|
|
||||||
mv ../action/tests/multi-language-repo/{*,.github} .
|
|
||||||
- uses: ./../action/init
|
|
||||||
with:
|
|
||||||
languages: javascript
|
|
||||||
- uses: ./../action/analyze
|
|
||||||
env:
|
|
||||||
TEST_MODE: true
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ on:
|
|||||||
# curl -H "Authorization: Bearer <token>" -X POST https://api.github.com/repos/github/codeql-action/dispatches -d '{"event_type":"update-release-branch"}'
|
# curl -H "Authorization: Bearer <token>" -X POST https://api.github.com/repos/github/codeql-action/dispatches -d '{"event_type":"update-release-branch"}'
|
||||||
# Replace <token> with a personal access token from this page: https://github.com/settings/tokens
|
# Replace <token> with a personal access token from this page: https://github.com/settings/tokens
|
||||||
types: [update-release-branch]
|
types: [update-release-branch]
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update:
|
update:
|
||||||
|
|||||||
Vendored
-25
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Debug AVA test file",
|
|
||||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/ava",
|
|
||||||
"runtimeArgs": [
|
|
||||||
"${file}",
|
|
||||||
"--break",
|
|
||||||
"--serial",
|
|
||||||
"--timeout=20m"
|
|
||||||
],
|
|
||||||
"port": 9229,
|
|
||||||
"outputCapture": "std",
|
|
||||||
"skipFiles": [
|
|
||||||
"<node_internals>/**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
+1
-22
@@ -10,34 +10,13 @@ Contributions to this project are [released](https://help.github.com/articles/gi
|
|||||||
|
|
||||||
Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.
|
Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.
|
||||||
|
|
||||||
## Development and Testing
|
|
||||||
|
|
||||||
Before you start, ensure that you have a recent version of node installed. You can see which version of node is used by the action in `init/action.yml`.
|
|
||||||
|
|
||||||
### Common tasks
|
|
||||||
|
|
||||||
* Transpile the TypeScript to JavaScript: `npm run build`. Note that the JavaScript files are committed to git.
|
|
||||||
* Run tests: `npm run test`. You’ll need to ensure that the JavaScript files are up-to-date first by running the command above.
|
|
||||||
* Run the linter: `npm run lint`.
|
|
||||||
|
|
||||||
This project also includes configuration to run tests from VSCode (with support for breakpoints) - open the test file you wish to run and choose "Debug AVA test file" from the Run menu in the Run panel.
|
|
||||||
|
|
||||||
### Running the action
|
|
||||||
|
|
||||||
To see the effect of your changes and to test them, push your changes in a branch and then look at the [Actions output](https://github.com/github/codeql-action/actions) for that branch. You can also exercise the code locally by running the automated tests.
|
|
||||||
|
|
||||||
### Integration tests
|
|
||||||
|
|
||||||
As well as the unit tests (see _Common tasks_ above), there are integration tests, defined in `.github/workflows/integration-testing.yml`. These are run by a CI check. Depending on the change you’re making, you may want to add a test to this file or extend an existing one.
|
|
||||||
|
|
||||||
## Submitting a pull request
|
## Submitting a pull request
|
||||||
|
|
||||||
1. [Fork][fork] and clone the repository
|
1. [Fork][fork] and clone the repository
|
||||||
2. Create a new branch: `git checkout -b my-branch-name`
|
2. Create a new branch: `git checkout -b my-branch-name`
|
||||||
3. Make your change, add tests, and make sure the tests still pass
|
3. Make your change, add tests, and make sure the tests still pass
|
||||||
4. Push to your fork and [submit a pull request][pr]
|
4. Push to your fork and [submit a pull request][pr]
|
||||||
5. Pat yourself on the back and wait for your pull request to be reviewed and merged.
|
5. Pat your self on the back and wait for your pull request to be reviewed and merged.
|
||||||
If you're a GitHub staff member, you can merge your own PR once it's approved; for external contributors, GitHub staff will merge your PR once it's approved.
|
|
||||||
|
|
||||||
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
CodeQL-Build:
|
CodeQL-Build:
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
|
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ inputs:
|
|||||||
description: The number of threads to be used by CodeQL.
|
description: The number of threads to be used by CodeQL.
|
||||||
required: false
|
required: false
|
||||||
default: "1"
|
default: "1"
|
||||||
checkout_path:
|
|
||||||
description: "The path at which the analyzed repository was checked out. Used to relativeize any absolute paths in the uploaded SARIF file."
|
|
||||||
required: false
|
|
||||||
default: ${{ github.workspace }}
|
|
||||||
token:
|
token:
|
||||||
default: ${{ github.token }}
|
default: ${{ github.token }}
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
+1
-5
@@ -5,7 +5,7 @@ inputs:
|
|||||||
tools:
|
tools:
|
||||||
description: URL of CodeQL tools
|
description: URL of CodeQL tools
|
||||||
required: false
|
required: false
|
||||||
default: https://github.com/github/codeql-action/releases/download/codeql-bundle-20200630/codeql-bundle.tar.gz
|
default: https://github.com/github/codeql-action/releases/download/codeql-bundle-20200601/codeql-bundle.tar.gz
|
||||||
languages:
|
languages:
|
||||||
description: The languages to be analysed
|
description: The languages to be analysed
|
||||||
required: false
|
required: false
|
||||||
@@ -16,10 +16,6 @@ inputs:
|
|||||||
config-file:
|
config-file:
|
||||||
description: Path of the config file to use
|
description: Path of the config file to use
|
||||||
required: false
|
required: false
|
||||||
setup-python-dependencies:
|
|
||||||
description: Try to auto-install your python dependencies
|
|
||||||
required: true
|
|
||||||
default: 'true'
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
main: '../lib/setup-tracer.js'
|
main: '../lib/setup-tracer.js'
|
||||||
|
|||||||
Generated
+8
-39
@@ -8,50 +8,19 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
function isInterpretedLanguage(language) {
|
function includeAndExcludeAnalysisPaths(config, languages) {
|
||||||
return language === 'javascript' || language === 'python';
|
|
||||||
}
|
|
||||||
// Matches a string containing only characters that are legal to include in paths on windows.
|
|
||||||
exports.legalWindowsPathCharactersRegex = /^[^<>:"\|?]*$/;
|
|
||||||
// Builds an environment variable suitable for LGTM_INDEX_INCLUDE or LGTM_INDEX_EXCLUDE
|
|
||||||
function buildIncludeExcludeEnvVar(paths) {
|
|
||||||
// Ignore anything containing a *
|
|
||||||
paths = paths.filter(p => p.indexOf('*') === -1);
|
|
||||||
// Some characters are illegal in path names in windows
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
paths = paths.filter(p => p.match(exports.legalWindowsPathCharactersRegex));
|
|
||||||
}
|
|
||||||
return paths.join('\n');
|
|
||||||
}
|
|
||||||
function includeAndExcludeAnalysisPaths(config) {
|
|
||||||
// The 'LGTM_INDEX_INCLUDE' and 'LGTM_INDEX_EXCLUDE' environment variables
|
|
||||||
// control which files/directories are traversed when scanning.
|
|
||||||
// This allows including files that otherwise would not be scanned, or
|
|
||||||
// excluding and not traversing entire file subtrees.
|
|
||||||
// It does not understand globs or double-globs because that would require it to
|
|
||||||
// traverse the entire file tree to determine which files are matched.
|
|
||||||
// Any paths containing "*" are not included in these.
|
|
||||||
if (config.paths.length !== 0) {
|
if (config.paths.length !== 0) {
|
||||||
core.exportVariable('LGTM_INDEX_INCLUDE', buildIncludeExcludeEnvVar(config.paths));
|
core.exportVariable('LGTM_INDEX_INCLUDE', config.paths.join('\n'));
|
||||||
}
|
}
|
||||||
if (config.pathsIgnore.length !== 0) {
|
if (config.pathsIgnore.length !== 0) {
|
||||||
core.exportVariable('LGTM_INDEX_EXCLUDE', buildIncludeExcludeEnvVar(config.pathsIgnore));
|
core.exportVariable('LGTM_INDEX_EXCLUDE', config.pathsIgnore.join('\n'));
|
||||||
}
|
}
|
||||||
// The 'LGTM_INDEX_FILTERS' environment variable controls which files are
|
function isInterpretedLanguage(language) {
|
||||||
// extracted or ignored. It does not control which directories are traversed.
|
return language === 'javascript' || language === 'python';
|
||||||
// This does understand the glob and double-glob syntax.
|
|
||||||
const filters = [];
|
|
||||||
filters.push(...config.paths.map(p => 'include:' + p));
|
|
||||||
filters.push(...config.pathsIgnore.map(p => 'exclude:' + p));
|
|
||||||
if (filters.length !== 0) {
|
|
||||||
core.exportVariable('LGTM_INDEX_FILTERS', filters.join('\n'));
|
|
||||||
}
|
}
|
||||||
// Index include/exclude/filters only work in javascript and python.
|
// Index include/exclude only work in javascript and python
|
||||||
// If any other languages are detected/configured then show a warning.
|
// If some other language is detected/configured show a warning
|
||||||
if ((config.paths.length !== 0 ||
|
if ((config.paths.length !== 0 || config.pathsIgnore.length !== 0) && !languages.every(isInterpretedLanguage)) {
|
||||||
config.pathsIgnore.length !== 0 ||
|
|
||||||
filters.length !== 0) &&
|
|
||||||
!config.languages.every(isInterpretedLanguage)) {
|
|
||||||
core.warning('The "paths"/"paths-ignore" fields of the config only have effect for Javascript and Python');
|
core.warning('The "paths"/"paths-ignore" fields of the config only have effect for Javascript and Python');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"analysis-paths.js","sourceRoot":"","sources":["../src/analysis-paths.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAsC;AAItC,SAAS,qBAAqB,CAAC,QAAQ;IACrC,OAAO,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,QAAQ,CAAC;AAC5D,CAAC;AAED,6FAA6F;AAChF,QAAA,+BAA+B,GAAG,eAAe,CAAC;AAE/D,uFAAuF;AACvF,SAAS,yBAAyB,CAAC,KAAe;IAChD,iCAAiC;IACjC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEjD,uDAAuD;IACvD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;QAChC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,uCAA+B,CAAC,CAAC,CAAC;KACrE;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAgB,8BAA8B,CAAC,MAA0B;IACvE,0EAA0E;IAC1E,+DAA+D;IAC/D,sEAAsE;IACtE,qDAAqD;IACrD,gFAAgF;IAChF,sEAAsE;IACtE,sDAAsD;IACtD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QAC7B,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,yBAAyB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;KACpF;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;QACnC,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,yBAAyB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;KAC1F;IAED,yEAAyE;IACzE,6EAA6E;IAC7E,wDAAwD;IACxD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QACxB,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KAC/D;IAED,oEAAoE;IACpE,sEAAsE;IACtE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QACxB,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;QAC/B,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;QACvB,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE;QAClD,IAAI,CAAC,OAAO,CAAC,4FAA4F,CAAC,CAAC;KAC5G;AACH,CAAC;AAjCD,wEAiCC"}
|
{"version":3,"file":"analysis-paths.js","sourceRoot":"","sources":["../src/analysis-paths.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAsC;AAItC,SAAgB,8BAA8B,CAAC,MAA0B,EAAE,SAAmB;IAC5F,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QAC7B,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KACpE;IAED,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;QACnC,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KAC1E;IAED,SAAS,qBAAqB,CAAC,QAAQ;QACrC,OAAO,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,QAAQ,CAAC;IAC5D,CAAC;IAED,2DAA2D;IAC3D,+DAA+D;IAC/D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE;QAC7G,IAAI,CAAC,OAAO,CAAC,4FAA4F,CAAC,CAAC;KAC5G;AACH,CAAC;AAlBD,wEAkBC"}
|
||||||
Generated
+9
-18
@@ -12,30 +12,21 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const analysisPaths = __importStar(require("./analysis-paths"));
|
const analysisPaths = __importStar(require("./analysis-paths"));
|
||||||
|
const configUtils = __importStar(require("./config-utils"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
testing_utils_1.silenceDebugOutput(ava_1.default);
|
||||||
ava_1.default("emptyPaths", async (t) => {
|
ava_1.default("emptyPaths", async (t) => {
|
||||||
const config = {
|
let config = new configUtils.Config();
|
||||||
languages: [],
|
analysisPaths.includeAndExcludeAnalysisPaths(config, []);
|
||||||
queries: {},
|
|
||||||
pathsIgnore: [],
|
|
||||||
paths: [],
|
|
||||||
};
|
|
||||||
analysisPaths.includeAndExcludeAnalysisPaths(config);
|
|
||||||
t.is(process.env['LGTM_INDEX_INCLUDE'], undefined);
|
t.is(process.env['LGTM_INDEX_INCLUDE'], undefined);
|
||||||
t.is(process.env['LGTM_INDEX_EXCLUDE'], undefined);
|
t.is(process.env['LGTM_INDEX_EXCLUDE'], undefined);
|
||||||
t.is(process.env['LGTM_INDEX_FILTERS'], undefined);
|
|
||||||
});
|
});
|
||||||
ava_1.default("nonEmptyPaths", async (t) => {
|
ava_1.default("nonEmptyPaths", async (t) => {
|
||||||
const config = {
|
let config = new configUtils.Config();
|
||||||
languages: [],
|
config.paths.push('path1', 'path2');
|
||||||
queries: {},
|
config.pathsIgnore.push('path3', 'path4');
|
||||||
paths: ['path1', 'path2', '**/path3'],
|
analysisPaths.includeAndExcludeAnalysisPaths(config, []);
|
||||||
pathsIgnore: ['path4', 'path5', 'path6/**'],
|
|
||||||
};
|
|
||||||
analysisPaths.includeAndExcludeAnalysisPaths(config);
|
|
||||||
t.is(process.env['LGTM_INDEX_INCLUDE'], 'path1\npath2');
|
t.is(process.env['LGTM_INDEX_INCLUDE'], 'path1\npath2');
|
||||||
t.is(process.env['LGTM_INDEX_EXCLUDE'], 'path4\npath5');
|
t.is(process.env['LGTM_INDEX_EXCLUDE'], 'path3\npath4');
|
||||||
t.is(process.env['LGTM_INDEX_FILTERS'], 'include:path1\ninclude:path2\ninclude:**/path3\nexclude:path4\nexclude:path5\nexclude:path6/**');
|
|
||||||
});
|
});
|
||||||
//# sourceMappingURL=analysis-paths.test.js.map
|
//# sourceMappingURL=analysis-paths.test.js.map
|
||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"analysis-paths.test.js","sourceRoot":"","sources":["../src/analysis-paths.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AAEvB,gEAAkD;AAClD,mDAA2C;AAE3C,0BAAU,CAAC,aAAI,CAAC,CAAC;AAEjB,aAAI,CAAC,YAAY,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IAC3B,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,EAAE;QACf,KAAK,EAAE,EAAE;KACV,CAAC;IACF,aAAa,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,SAAS,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,eAAe,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IAC9B,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;QACrC,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;KAC5C,CAAC;IACF,aAAa,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,gGAAgG,CAAC,CAAC;AAC5I,CAAC,CAAC,CAAC"}
|
{"version":3,"file":"analysis-paths.test.js","sourceRoot":"","sources":["../src/analysis-paths.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AAEvB,gEAAkD;AAClD,4DAA8C;AAC9C,mDAAmD;AAEnD,kCAAkB,CAAC,aAAI,CAAC,CAAC;AAEzB,aAAI,CAAC,YAAY,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IAC3B,IAAI,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;IACtC,aAAa,CAAC,8BAA8B,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,SAAS,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,eAAe,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IAC9B,IAAI,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;IACtC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,aAAa,CAAC,8BAA8B,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,cAAc,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC"}
|
||||||
Generated
-22
@@ -1,22 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const core = __importStar(require("@actions/core"));
|
|
||||||
const github = __importStar(require("@actions/github"));
|
|
||||||
const console_log_level_1 = __importDefault(require("console-log-level"));
|
|
||||||
exports.getApiClient = function () {
|
|
||||||
return new github.GitHub(core.getInput('token'), {
|
|
||||||
userAgent: "CodeQL Action",
|
|
||||||
log: console_log_level_1.default({ level: "debug" })
|
|
||||||
});
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=api-client.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAsC;AACtC,wDAA0C;AAC1C,0EAAgD;AAEnC,QAAA,YAAY,GAAG;IAC1B,OAAO,IAAI,MAAM,CAAC,MAAM,CACtB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EACtB;QACE,SAAS,EAAE,eAAe;QAC1B,GAAG,EAAE,2BAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;KACzC,CAAC,CAAC;AACP,CAAC,CAAC"}
|
|
||||||
Generated
+14
-3
@@ -8,7 +8,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const codeql_1 = require("./codeql");
|
const exec = __importStar(require("@actions/exec"));
|
||||||
|
const path = __importStar(require("path"));
|
||||||
const sharedEnv = __importStar(require("./shared-environment"));
|
const sharedEnv = __importStar(require("./shared-environment"));
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
async function run() {
|
async function run() {
|
||||||
@@ -32,8 +33,18 @@ async function run() {
|
|||||||
core.warning(`We will only automatically build ${language} code. If you wish to scan ${autobuildLanguages.slice(1).join(' and ')}, you must replace this block with custom build steps.`);
|
core.warning(`We will only automatically build ${language} code. If you wish to scan ${autobuildLanguages.slice(1).join(' and ')}, you must replace this block with custom build steps.`);
|
||||||
}
|
}
|
||||||
core.startGroup(`Attempting to automatically build ${language} code`);
|
core.startGroup(`Attempting to automatically build ${language} code`);
|
||||||
const codeQL = codeql_1.getCodeQL();
|
// TODO: share config accross actions better via env variables
|
||||||
await codeQL.runAutobuild(language);
|
const codeqlCmd = util.getRequiredEnvParam(sharedEnv.CODEQL_ACTION_CMD);
|
||||||
|
const cmdName = process.platform === 'win32' ? 'autobuild.cmd' : 'autobuild.sh';
|
||||||
|
const autobuildCmd = path.join(path.dirname(codeqlCmd), language, 'tools', cmdName);
|
||||||
|
// Update JAVA_TOOL_OPTIONS to contain '-Dhttp.keepAlive=false'
|
||||||
|
// This is because of an issue with Azure pipelines timing out connections after 4 minutes
|
||||||
|
// and Maven not properly handling closed connections
|
||||||
|
// Otherwise long build processes will timeout when pulling down Java packages
|
||||||
|
// https://developercommunity.visualstudio.com/content/problem/292284/maven-hosted-agent-connection-timeout.html
|
||||||
|
let javaToolOptions = process.env['JAVA_TOOL_OPTIONS'] || "";
|
||||||
|
process.env['JAVA_TOOL_OPTIONS'] = [...javaToolOptions.split(/\s+/), '-Dhttp.keepAlive=false', '-Dmaven.wagon.http.pool=false'].join(' ');
|
||||||
|
await exec.exec(autobuildCmd);
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"autobuild.js","sourceRoot":"","sources":["../src/autobuild.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAsC;AAEtC,qCAAqC;AACrC,gEAAkD;AAClD,6CAA+B;AAE/B,KAAK,UAAU,GAAG;;IAChB,IAAI;QACF,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAAE;YACzF,OAAO;SACR;QAED,0CAA0C;QAC1C,mFAAmF;QACnF,oFAAoF;QACpF,4EAA4E;QAC5E,MAAM,kBAAkB,GAAG,OAAA,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,8BAA8B,CAAC,0CAAE,KAAK,CAAC,GAAG,MAAK,EAAE,CAAC;QACnG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;QAEvC,IAAI,CAAC,QAAQ,EAAE;YACb,IAAI,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAC7E,OAAO;SACR;QAED,IAAI,CAAC,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;QAE7D,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE;YACjC,IAAI,CAAC,OAAO,CAAC,oCAAoC,QAAQ,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,wDAAwD,CAAC,CAAC;SAC3L;QAED,IAAI,CAAC,UAAU,CAAC,qCAAqC,QAAQ,OAAO,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,kBAAS,EAAE,CAAC;QAC3B,MAAM,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAEpC,IAAI,CAAC,QAAQ,EAAE,CAAC;KAEjB;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,SAAS,CAAC,kIAAkI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QACnK,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO;KACR;IAED,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACd,IAAI,CAAC,SAAS,CAAC,4BAA4B,GAAG,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC"}
|
{"version":3,"file":"autobuild.js","sourceRoot":"","sources":["../src/autobuild.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAsC;AACtC,oDAAsC;AACtC,2CAA6B;AAE7B,gEAAkD;AAClD,6CAA+B;AAE/B,KAAK,UAAU,GAAG;;IAChB,IAAI;QACF,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAAE;YACzF,OAAO;SACR;QAED,0CAA0C;QAC1C,mFAAmF;QACnF,oFAAoF;QACpF,4EAA4E;QAC5E,MAAM,kBAAkB,GAAG,OAAA,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,8BAA8B,CAAC,0CAAE,KAAK,CAAC,GAAG,MAAK,EAAE,CAAC;QACnG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;QAEvC,IAAI,CAAC,QAAQ,EAAE;YACb,IAAI,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAC7E,OAAO;SACR;QAED,IAAI,CAAC,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;QAE7D,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE;YACjC,IAAI,CAAC,OAAO,CAAC,oCAAoC,QAAQ,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,wDAAwD,CAAC,CAAC;SAC3L;QAED,IAAI,CAAC,UAAU,CAAC,qCAAqC,QAAQ,OAAO,CAAC,CAAC;QACtE,8DAA8D;QAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAExE,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,cAAc,CAAC;QAChF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAGpF,+DAA+D;QAC/D,0FAA0F;QAC1F,qDAAqD;QACrD,8EAA8E;QAC9E,gHAAgH;QAChH,IAAI,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,wBAAwB,EAAE,+BAA+B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE1I,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;KAEjB;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,SAAS,CAAC,kIAAkI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QACnK,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO;KACR;IAED,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACd,IAAI,CAAC,SAAS,CAAC,4BAA4B,GAAG,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC"}
|
||||||
Generated
-226
@@ -1,226 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const core = __importStar(require("@actions/core"));
|
|
||||||
const exec = __importStar(require("@actions/exec"));
|
|
||||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
|
||||||
const fs = __importStar(require("fs"));
|
|
||||||
const path = __importStar(require("path"));
|
|
||||||
const semver = __importStar(require("semver"));
|
|
||||||
const util = __importStar(require("./util"));
|
|
||||||
/**
|
|
||||||
* Stores the CodeQL object, and is populated by `setupCodeQL` or `getCodeQL`.
|
|
||||||
* Can be overridden in tests using `setCodeQL`.
|
|
||||||
*/
|
|
||||||
let cachedCodeQL = undefined;
|
|
||||||
/**
|
|
||||||
* Environment variable used to store the location of the CodeQL CLI executable.
|
|
||||||
* Value is set by setupCodeQL and read by getCodeQL.
|
|
||||||
*/
|
|
||||||
const CODEQL_ACTION_CMD = "CODEQL_ACTION_CMD";
|
|
||||||
async function setupCodeQL() {
|
|
||||||
try {
|
|
||||||
const codeqlURL = core.getInput('tools', { required: true });
|
|
||||||
const codeqlURLVersion = getCodeQLURLVersion(codeqlURL);
|
|
||||||
let codeqlFolder = toolcache.find('CodeQL', codeqlURLVersion);
|
|
||||||
if (codeqlFolder) {
|
|
||||||
core.debug(`CodeQL found in cache ${codeqlFolder}`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const codeqlPath = await toolcache.downloadTool(codeqlURL);
|
|
||||||
const codeqlExtracted = await toolcache.extractTar(codeqlPath);
|
|
||||||
codeqlFolder = await toolcache.cacheDir(codeqlExtracted, 'CodeQL', codeqlURLVersion);
|
|
||||||
}
|
|
||||||
let codeqlCmd = path.join(codeqlFolder, 'codeql', 'codeql');
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
codeqlCmd += ".exe";
|
|
||||||
}
|
|
||||||
else if (process.platform !== 'linux' && process.platform !== 'darwin') {
|
|
||||||
throw new Error("Unsupported plaform: " + process.platform);
|
|
||||||
}
|
|
||||||
cachedCodeQL = getCodeQLForCmd(codeqlCmd);
|
|
||||||
core.exportVariable(CODEQL_ACTION_CMD, codeqlCmd);
|
|
||||||
return cachedCodeQL;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
core.error(e);
|
|
||||||
throw new Error("Unable to download and extract CodeQL CLI");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.setupCodeQL = setupCodeQL;
|
|
||||||
function getCodeQLURLVersion(url) {
|
|
||||||
const match = url.match(/\/codeql-bundle-(.*)\//);
|
|
||||||
if (match === null || match.length < 2) {
|
|
||||||
throw new Error(`Malformed tools url: ${url}. Version could not be inferred`);
|
|
||||||
}
|
|
||||||
let version = match[1];
|
|
||||||
if (!semver.valid(version)) {
|
|
||||||
core.debug(`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`);
|
|
||||||
version = '0.0.0-' + version;
|
|
||||||
}
|
|
||||||
const s = semver.clean(version);
|
|
||||||
if (!s) {
|
|
||||||
throw new Error(`Malformed tools url ${url}. Version should be in SemVer format but have ${version} instead`);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
exports.getCodeQLURLVersion = getCodeQLURLVersion;
|
|
||||||
function getCodeQL() {
|
|
||||||
if (cachedCodeQL === undefined) {
|
|
||||||
const codeqlCmd = util.getRequiredEnvParam(CODEQL_ACTION_CMD);
|
|
||||||
cachedCodeQL = getCodeQLForCmd(codeqlCmd);
|
|
||||||
}
|
|
||||||
return cachedCodeQL;
|
|
||||||
}
|
|
||||||
exports.getCodeQL = getCodeQL;
|
|
||||||
function resolveFunction(partialCodeql, methodName) {
|
|
||||||
if (typeof partialCodeql[methodName] !== 'function') {
|
|
||||||
const dummyMethod = () => {
|
|
||||||
throw new Error('CodeQL ' + methodName + ' method not correctly defined');
|
|
||||||
};
|
|
||||||
return dummyMethod;
|
|
||||||
}
|
|
||||||
return partialCodeql[methodName];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Set the functionality for CodeQL methods. Only for use in tests.
|
|
||||||
*
|
|
||||||
* Accepts a partial object and any undefined methods will be implemented
|
|
||||||
* to immediately throw an exception indicating which method is missing.
|
|
||||||
*/
|
|
||||||
function setCodeQL(partialCodeql) {
|
|
||||||
cachedCodeQL = {
|
|
||||||
getDir: resolveFunction(partialCodeql, 'getDir'),
|
|
||||||
printVersion: resolveFunction(partialCodeql, 'printVersion'),
|
|
||||||
getTracerEnv: resolveFunction(partialCodeql, 'getTracerEnv'),
|
|
||||||
databaseInit: resolveFunction(partialCodeql, 'databaseInit'),
|
|
||||||
runAutobuild: resolveFunction(partialCodeql, 'runAutobuild'),
|
|
||||||
extractScannedLanguage: resolveFunction(partialCodeql, 'extractScannedLanguage'),
|
|
||||||
finalizeDatabase: resolveFunction(partialCodeql, 'finalizeDatabase'),
|
|
||||||
resolveQueries: resolveFunction(partialCodeql, 'resolveQueries'),
|
|
||||||
databaseAnalyze: resolveFunction(partialCodeql, 'databaseAnalyze')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
exports.setCodeQL = setCodeQL;
|
|
||||||
function getCodeQLForCmd(cmd) {
|
|
||||||
return {
|
|
||||||
getDir: function () {
|
|
||||||
return path.dirname(cmd);
|
|
||||||
},
|
|
||||||
printVersion: async function () {
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'version',
|
|
||||||
'--format=json'
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
getTracerEnv: async function (databasePath, compilerSpec) {
|
|
||||||
let envFile = path.resolve(databasePath, 'working', 'env.tmp');
|
|
||||||
const compilerSpecArg = compilerSpec ? ["--compiler-spec=" + compilerSpec] : [];
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'database',
|
|
||||||
'trace-command',
|
|
||||||
databasePath,
|
|
||||||
...compilerSpecArg,
|
|
||||||
process.execPath,
|
|
||||||
path.resolve(__dirname, 'tracer-env.js'),
|
|
||||||
envFile
|
|
||||||
]);
|
|
||||||
return JSON.parse(fs.readFileSync(envFile, 'utf-8'));
|
|
||||||
},
|
|
||||||
databaseInit: async function (databasePath, language, sourceRoot) {
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'database',
|
|
||||||
'init',
|
|
||||||
databasePath,
|
|
||||||
'--language=' + language,
|
|
||||||
'--source-root=' + sourceRoot,
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
runAutobuild: async function (language) {
|
|
||||||
const cmdName = process.platform === 'win32' ? 'autobuild.cmd' : 'autobuild.sh';
|
|
||||||
const autobuildCmd = path.join(path.dirname(cmd), language, 'tools', cmdName);
|
|
||||||
// Update JAVA_TOOL_OPTIONS to contain '-Dhttp.keepAlive=false'
|
|
||||||
// This is because of an issue with Azure pipelines timing out connections after 4 minutes
|
|
||||||
// and Maven not properly handling closed connections
|
|
||||||
// Otherwise long build processes will timeout when pulling down Java packages
|
|
||||||
// https://developercommunity.visualstudio.com/content/problem/292284/maven-hosted-agent-connection-timeout.html
|
|
||||||
let javaToolOptions = process.env['JAVA_TOOL_OPTIONS'] || "";
|
|
||||||
process.env['JAVA_TOOL_OPTIONS'] = [...javaToolOptions.split(/\s+/), '-Dhttp.keepAlive=false', '-Dmaven.wagon.http.pool=false'].join(' ');
|
|
||||||
await exec.exec(autobuildCmd);
|
|
||||||
},
|
|
||||||
extractScannedLanguage: async function (databasePath, language) {
|
|
||||||
// Get extractor location
|
|
||||||
let extractorPath = '';
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'resolve',
|
|
||||||
'extractor',
|
|
||||||
'--format=json',
|
|
||||||
'--language=' + language
|
|
||||||
], {
|
|
||||||
silent: true,
|
|
||||||
listeners: {
|
|
||||||
stdout: (data) => { extractorPath += data.toString(); },
|
|
||||||
stderr: (data) => { process.stderr.write(data); }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Set trace command
|
|
||||||
const ext = process.platform === 'win32' ? '.cmd' : '.sh';
|
|
||||||
const traceCommand = path.resolve(JSON.parse(extractorPath), 'tools', 'autobuild' + ext);
|
|
||||||
// Run trace command
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'database',
|
|
||||||
'trace-command',
|
|
||||||
databasePath,
|
|
||||||
'--',
|
|
||||||
traceCommand
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
finalizeDatabase: async function (databasePath) {
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'database',
|
|
||||||
'finalize',
|
|
||||||
databasePath
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
resolveQueries: async function (queries, extraSearchPath) {
|
|
||||||
const codeqlArgs = [
|
|
||||||
'resolve',
|
|
||||||
'queries',
|
|
||||||
...queries,
|
|
||||||
'--format=bylanguage'
|
|
||||||
];
|
|
||||||
if (extraSearchPath !== undefined) {
|
|
||||||
codeqlArgs.push('--search-path', extraSearchPath);
|
|
||||||
}
|
|
||||||
let output = '';
|
|
||||||
await exec.exec(cmd, codeqlArgs, {
|
|
||||||
listeners: {
|
|
||||||
stdout: (data) => {
|
|
||||||
output += data.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return JSON.parse(output);
|
|
||||||
},
|
|
||||||
databaseAnalyze: async function (databasePath, sarifFile, querySuite) {
|
|
||||||
await exec.exec(cmd, [
|
|
||||||
'database',
|
|
||||||
'analyze',
|
|
||||||
util.getMemoryFlag(),
|
|
||||||
util.getThreadsFlag(),
|
|
||||||
databasePath,
|
|
||||||
'--format=sarif-latest',
|
|
||||||
'--output=' + sarifFile,
|
|
||||||
'--no-sarif-add-snippets',
|
|
||||||
querySuite
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=codeql.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
Generated
-60
@@ -1,60 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
|
||||||
const ava_1 = __importDefault(require("ava"));
|
|
||||||
const nock_1 = __importDefault(require("nock"));
|
|
||||||
const path = __importStar(require("path"));
|
|
||||||
const codeql = __importStar(require("./codeql"));
|
|
||||||
const testing_utils_1 = require("./testing-utils");
|
|
||||||
const util = __importStar(require("./util"));
|
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
|
||||||
ava_1.default('download codeql bundle cache', async (t) => {
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
|
||||||
process.env['RUNNER_TEMP'] = path.join(tmpDir, 'temp');
|
|
||||||
process.env['RUNNER_TOOL_CACHE'] = path.join(tmpDir, 'cache');
|
|
||||||
const versions = ['20200601', '20200610'];
|
|
||||||
for (let i = 0; i < versions.length; i++) {
|
|
||||||
const version = versions[i];
|
|
||||||
nock_1.default('https://example.com')
|
|
||||||
.get(`/download/codeql-bundle-${version}/codeql-bundle.tar.gz`)
|
|
||||||
.replyWithFile(200, path.join(__dirname, `/../src/testdata/codeql-bundle.tar.gz`));
|
|
||||||
process.env['INPUT_TOOLS'] = `https://example.com/download/codeql-bundle-${version}/codeql-bundle.tar.gz`;
|
|
||||||
await codeql.setupCodeQL();
|
|
||||||
t.assert(toolcache.find('CodeQL', `0.0.0-${version}`));
|
|
||||||
}
|
|
||||||
const cachedVersions = toolcache.findAllVersions('CodeQL');
|
|
||||||
t.is(cachedVersions.length, 2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ava_1.default('parse codeql bundle url version', t => {
|
|
||||||
const tests = {
|
|
||||||
'20200601': '0.0.0-20200601',
|
|
||||||
'20200601.0': '0.0.0-20200601.0',
|
|
||||||
'20200601.0.0': '20200601.0.0',
|
|
||||||
'1.2.3': '1.2.3',
|
|
||||||
'1.2.3-alpha': '1.2.3-alpha',
|
|
||||||
'1.2.3-beta.1': '1.2.3-beta.1',
|
|
||||||
};
|
|
||||||
for (const [version, expectedVersion] of Object.entries(tests)) {
|
|
||||||
const url = `https://github.com/.../codeql-bundle-${version}/...`;
|
|
||||||
try {
|
|
||||||
const parsedVersion = codeql.getCodeQLURLVersion(url);
|
|
||||||
t.deepEqual(parsedVersion, expectedVersion);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
t.fail(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=codeql.test.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"codeql.test.js","sourceRoot":"","sources":["../src/codeql.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAAiD;AACjD,8CAAuB;AACvB,gDAAwB;AACxB,2CAA6B;AAE7B,iDAAmC;AACnC,mDAA2C;AAC3C,6CAA+B;AAE/B,0BAAU,CAAC,aAAI,CAAC,CAAC;AAEjB,aAAI,CAAC,8BAA8B,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IAE7C,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QAEnC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC;QAEzC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE9D,MAAM,QAAQ,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAE5B,cAAI,CAAC,qBAAqB,CAAC;iBACxB,GAAG,CAAC,2BAA2B,OAAO,uBAAuB,CAAC;iBAC9D,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uCAAuC,CAAC,CAAC,CAAC;YAGrF,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,8CAA8C,OAAO,uBAAuB,CAAC;YAE1G,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YAE3B,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;SACxD;QAED,MAAM,cAAc,GAAG,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAE3D,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,iCAAiC,EAAE,CAAC,CAAC,EAAE;IAE1C,MAAM,KAAK,GAAG;QACZ,UAAU,EAAE,gBAAgB;QAC5B,YAAY,EAAE,kBAAkB;QAChC,cAAc,EAAE,cAAc;QAC9B,OAAO,EAAE,OAAO;QAChB,aAAa,EAAE,aAAa;QAC5B,cAAc,EAAE,cAAc;KAC/B,CAAC;IAEF,KAAK,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QAC9D,MAAM,GAAG,GAAG,wCAAwC,OAAO,MAAM,CAAC;QAElE,IAAI;YACF,MAAM,aAAa,GAAG,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;YACtD,CAAC,CAAC,SAAS,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;SAC7C;QAAC,OAAO,CAAC,EAAE;YACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;SACnB;KACF;AACH,CAAC,CAAC,CAAC"}
|
|
||||||
Generated
+92
-386
@@ -12,97 +12,43 @@ const io = __importStar(require("@actions/io"));
|
|||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const yaml = __importStar(require("js-yaml"));
|
const yaml = __importStar(require("js-yaml"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const api = __importStar(require("./api-client"));
|
|
||||||
const codeql_1 = require("./codeql");
|
|
||||||
const externalQueries = __importStar(require("./external-queries"));
|
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
// Property names from the user-supplied config file.
|
|
||||||
const NAME_PROPERTY = 'name';
|
const NAME_PROPERTY = 'name';
|
||||||
const DISABLE_DEFAULT_QUERIES_PROPERTY = 'disable-default-queries';
|
const DISPLAY_DEFAULT_QUERIES_PROPERTY = 'disable-default-queries';
|
||||||
const QUERIES_PROPERTY = 'queries';
|
const QUERIES_PROPERTY = 'queries';
|
||||||
const QUERIES_USES_PROPERTY = 'uses';
|
const QUERIES_USES_PROPERTY = 'uses';
|
||||||
const PATHS_IGNORE_PROPERTY = 'paths-ignore';
|
const PATHS_IGNORE_PROPERTY = 'paths-ignore';
|
||||||
const PATHS_PROPERTY = 'paths';
|
const PATHS_PROPERTY = 'paths';
|
||||||
/**
|
class ExternalQuery {
|
||||||
* A list of queries from https://github.com/github/codeql that
|
constructor(repository, ref) {
|
||||||
* we don't want to run. Disabling them here is a quicker alternative to
|
this.path = '';
|
||||||
* disabling them in the code scanning query suites. Queries should also
|
this.repository = repository;
|
||||||
* be disabled in the suites, and removed from this list here once the
|
this.ref = ref;
|
||||||
* bundle is updated to make those suite changes live.
|
|
||||||
*
|
|
||||||
* Format is a map from language to an array of path suffixes of .ql files.
|
|
||||||
*/
|
|
||||||
const DISABLED_BUILTIN_QUERIES = {
|
|
||||||
'csharp': [
|
|
||||||
'ql/src/Security Features/CWE-937/VulnerablePackage.ql',
|
|
||||||
'ql/src/Security Features/CWE-451/MissingXFrameOptions.ql',
|
|
||||||
]
|
|
||||||
};
|
|
||||||
function queryIsDisabled(language, query) {
|
|
||||||
return (DISABLED_BUILTIN_QUERIES[language] || [])
|
|
||||||
.some(disabledQuery => query.endsWith(disabledQuery));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Asserts that the noDeclaredLanguage and multipleDeclaredLanguages fields are
|
|
||||||
* both empty and errors if they are not.
|
|
||||||
*/
|
|
||||||
function validateQueries(resolvedQueries) {
|
|
||||||
const noDeclaredLanguage = resolvedQueries.noDeclaredLanguage;
|
|
||||||
const noDeclaredLanguageQueries = Object.keys(noDeclaredLanguage);
|
|
||||||
if (noDeclaredLanguageQueries.length !== 0) {
|
|
||||||
throw new Error('The following queries do not declare a language. ' +
|
|
||||||
'Their qlpack.yml files are either missing or is invalid.\n' +
|
|
||||||
noDeclaredLanguageQueries.join('\n'));
|
|
||||||
}
|
|
||||||
const multipleDeclaredLanguages = resolvedQueries.multipleDeclaredLanguages;
|
|
||||||
const multipleDeclaredLanguagesQueries = Object.keys(multipleDeclaredLanguages);
|
|
||||||
if (multipleDeclaredLanguagesQueries.length !== 0) {
|
|
||||||
throw new Error('The following queries declare multiple languages. ' +
|
|
||||||
'Their qlpack.yml files are either missing or is invalid.\n' +
|
|
||||||
multipleDeclaredLanguagesQueries.join('\n'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
exports.ExternalQuery = ExternalQuery;
|
||||||
* Run 'codeql resolve queries' and add the results to resultMap
|
|
||||||
*/
|
|
||||||
async function runResolveQueries(resultMap, toResolve, extraSearchPath, errorOnInvalidQueries) {
|
|
||||||
const codeQl = codeql_1.getCodeQL();
|
|
||||||
const resolvedQueries = await codeQl.resolveQueries(toResolve, extraSearchPath);
|
|
||||||
for (const [language, queries] of Object.entries(resolvedQueries.byLanguage)) {
|
|
||||||
if (resultMap[language] === undefined) {
|
|
||||||
resultMap[language] = [];
|
|
||||||
}
|
|
||||||
resultMap[language].push(...Object.keys(queries).filter(q => !queryIsDisabled(language, q)));
|
|
||||||
}
|
|
||||||
if (errorOnInvalidQueries) {
|
|
||||||
validateQueries(resolvedQueries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the set of queries included by default.
|
|
||||||
*/
|
|
||||||
async function addDefaultQueries(languages, resultMap) {
|
|
||||||
const suites = languages.map(l => l + '-code-scanning.qls');
|
|
||||||
await runResolveQueries(resultMap, suites, undefined, false);
|
|
||||||
}
|
|
||||||
// The set of acceptable values for built-in suites from the codeql bundle
|
// The set of acceptable values for built-in suites from the codeql bundle
|
||||||
const builtinSuites = ['security-extended', 'security-and-quality'];
|
const builtinSuites = ['security-extended', 'security-and-quality'];
|
||||||
/**
|
class Config {
|
||||||
* Determine the set of queries associated with suiteName's suites and add them to resultMap.
|
constructor() {
|
||||||
* Throws an error if suiteName is not a valid builtin suite.
|
this.name = "";
|
||||||
*/
|
this.disableDefaultQueries = false;
|
||||||
async function addBuiltinSuiteQueries(configFile, languages, resultMap, suiteName) {
|
this.additionalQueries = [];
|
||||||
const suite = builtinSuites.find((suite) => suite === suiteName);
|
this.externalQueries = [];
|
||||||
if (!suite) {
|
this.additionalSuites = [];
|
||||||
throw new Error(getQueryUsesInvalid(configFile, suiteName));
|
this.pathsIgnore = [];
|
||||||
|
this.paths = [];
|
||||||
}
|
}
|
||||||
const suites = languages.map(l => l + '-' + suiteName + '.qls');
|
addQuery(configFile, queryUses) {
|
||||||
await runResolveQueries(resultMap, suites, undefined, false);
|
// The logic for parsing the string is based on what actions does for
|
||||||
}
|
// parsing the 'uses' actions in the workflow file
|
||||||
/**
|
queryUses = queryUses.trim();
|
||||||
* Retrieve the set of queries at localQueryPath and add them to resultMap.
|
if (queryUses === "") {
|
||||||
*/
|
throw new Error(getQueryUsesInvalid(configFile));
|
||||||
async function addLocalQueries(configFile, resultMap, localQueryPath) {
|
}
|
||||||
|
// Check for the local path case before we start trying to parse the repository name
|
||||||
|
if (queryUses.startsWith("./")) {
|
||||||
|
const localQueryPath = queryUses.slice(2);
|
||||||
// Resolve the local path against the workspace so that when this is
|
// Resolve the local path against the workspace so that when this is
|
||||||
// passed to codeql it resolves to exactly the path we expect it to resolve to.
|
// passed to codeql it resolves to exactly the path we expect it to resolve to.
|
||||||
const workspacePath = fs.realpathSync(util.getRequiredEnvParam('GITHUB_WORKSPACE'));
|
const workspacePath = fs.realpathSync(util.getRequiredEnvParam('GITHUB_WORKSPACE'));
|
||||||
@@ -117,14 +63,20 @@ async function addLocalQueries(configFile, resultMap, localQueryPath) {
|
|||||||
if (!(absoluteQueryPath + path.sep).startsWith(workspacePath + path.sep)) {
|
if (!(absoluteQueryPath + path.sep).startsWith(workspacePath + path.sep)) {
|
||||||
throw new Error(getLocalPathOutsideOfRepository(configFile, localQueryPath));
|
throw new Error(getLocalPathOutsideOfRepository(configFile, localQueryPath));
|
||||||
}
|
}
|
||||||
// Get the root of the current repo to use when resolving query dependencies
|
this.additionalQueries.push(absoluteQueryPath);
|
||||||
const rootOfRepo = util.getRequiredEnvParam('GITHUB_WORKSPACE');
|
return;
|
||||||
await runResolveQueries(resultMap, [absoluteQueryPath], rootOfRepo, true);
|
}
|
||||||
}
|
// Check for one of the builtin suites
|
||||||
/**
|
if (queryUses.indexOf('/') === -1 && queryUses.indexOf('@') === -1) {
|
||||||
* Retrieve the set of queries at the referenced remote repo and add them to resultMap.
|
const suite = builtinSuites.find((suite) => suite === queryUses);
|
||||||
*/
|
if (suite) {
|
||||||
async function addRemoteQueries(configFile, resultMap, queryUses) {
|
this.additionalSuites.push(suite);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||||
|
}
|
||||||
|
}
|
||||||
let tok = queryUses.split('@');
|
let tok = queryUses.split('@');
|
||||||
if (tok.length !== 2) {
|
if (tok.length !== 2) {
|
||||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||||
@@ -137,96 +89,27 @@ async function addRemoteQueries(configFile, resultMap, queryUses) {
|
|||||||
if (tok.length < 2) {
|
if (tok.length < 2) {
|
||||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||||
}
|
}
|
||||||
|
if (tok.length > 3) {
|
||||||
|
tok = [tok[0], tok[1], tok.slice(2).join('/')];
|
||||||
|
}
|
||||||
// Check none of the parts of the repository name are empty
|
// Check none of the parts of the repository name are empty
|
||||||
if (tok[0].trim() === '' || tok[1].trim() === '') {
|
if (tok[0].trim() === '' || tok[1].trim() === '') {
|
||||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||||
}
|
}
|
||||||
const nwo = tok[0] + '/' + tok[1];
|
let external = new ExternalQuery(tok[0] + '/' + tok[1], ref);
|
||||||
// Checkout the external repository
|
if (tok.length === 3) {
|
||||||
const rootOfRepo = await externalQueries.checkoutExternalRepository(nwo, ref);
|
external.path = tok[2];
|
||||||
const queryPath = tok.length > 2
|
}
|
||||||
? path.join(rootOfRepo, tok.slice(2).join('/'))
|
this.externalQueries.push(external);
|
||||||
: rootOfRepo;
|
}
|
||||||
await runResolveQueries(resultMap, [queryPath], rootOfRepo, true);
|
|
||||||
}
|
}
|
||||||
/**
|
exports.Config = Config;
|
||||||
* Parse a query 'uses' field to a discrete set of query files and update resultMap.
|
|
||||||
*
|
|
||||||
* The logic for parsing the string is based on what actions does for
|
|
||||||
* parsing the 'uses' actions in the workflow file. So it can handle
|
|
||||||
* local paths starting with './', or references to remote repos, or
|
|
||||||
* a finite set of hardcoded terms for builtin suites.
|
|
||||||
*/
|
|
||||||
async function parseQueryUses(configFile, languages, resultMap, queryUses) {
|
|
||||||
queryUses = queryUses.trim();
|
|
||||||
if (queryUses === "") {
|
|
||||||
throw new Error(getQueryUsesInvalid(configFile));
|
|
||||||
}
|
|
||||||
// Check for the local path case before we start trying to parse the repository name
|
|
||||||
if (queryUses.startsWith("./")) {
|
|
||||||
await addLocalQueries(configFile, resultMap, queryUses.slice(2));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check for one of the builtin suites
|
|
||||||
if (queryUses.indexOf('/') === -1 && queryUses.indexOf('@') === -1) {
|
|
||||||
await addBuiltinSuiteQueries(configFile, languages, resultMap, queryUses);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Otherwise, must be a reference to another repo
|
|
||||||
await addRemoteQueries(configFile, resultMap, queryUses);
|
|
||||||
}
|
|
||||||
// Regex validating stars in paths or paths-ignore entries.
|
|
||||||
// The intention is to only allow ** to appear when immediately
|
|
||||||
// preceded and followed by a slash.
|
|
||||||
const pathStarsRegex = /.*(?:\*\*[^/].*|\*\*$|[^/]\*\*.*)/;
|
|
||||||
// Characters that are supported by filters in workflows, but not by us.
|
|
||||||
// See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
|
|
||||||
const filterPatternCharactersRegex = /.*[\?\+\[\]!].*/;
|
|
||||||
// Checks that a paths of paths-ignore entry is valid, possibly modifying it
|
|
||||||
// to make it valid, or if not possible then throws an error.
|
|
||||||
function validateAndSanitisePath(originalPath, propertyName, configFile) {
|
|
||||||
// Take a copy so we don't modify the original path, so we can still construct error messages
|
|
||||||
let path = originalPath;
|
|
||||||
// All paths are relative to the src root, so strip off leading slashes.
|
|
||||||
while (path.charAt(0) === '/') {
|
|
||||||
path = path.substring(1);
|
|
||||||
}
|
|
||||||
// Trailing ** are redundant, so strip them off
|
|
||||||
if (path.endsWith('/**')) {
|
|
||||||
path = path.substring(0, path.length - 2);
|
|
||||||
}
|
|
||||||
// An empty path is not allowed as it's meaningless
|
|
||||||
if (path === '') {
|
|
||||||
throw new Error(getConfigFilePropertyError(configFile, propertyName, '"' + originalPath + '" is not an invalid path. ' +
|
|
||||||
'It is not necessary to include it, and it is not allowed to exclude it.'));
|
|
||||||
}
|
|
||||||
// Check for illegal uses of **
|
|
||||||
if (path.match(pathStarsRegex)) {
|
|
||||||
throw new Error(getConfigFilePropertyError(configFile, propertyName, '"' + originalPath + '" contains an invalid "**" wildcard. ' +
|
|
||||||
'They must be immediately preceeded and followed by a slash as in "/**/", or come at the start or end.'));
|
|
||||||
}
|
|
||||||
// Check for other regex characters that we don't support.
|
|
||||||
// Output a warning so the user knows, but otherwise continue normally.
|
|
||||||
if (path.match(filterPatternCharactersRegex)) {
|
|
||||||
core.warning(getConfigFilePropertyError(configFile, propertyName, '"' + originalPath + '" contains an unsupported character. ' +
|
|
||||||
'The filter pattern characters ?, +, [, ], ! are not supported and will be matched literally.'));
|
|
||||||
}
|
|
||||||
// Ban any uses of backslash for now.
|
|
||||||
// This may not play nicely with project layouts.
|
|
||||||
// This restriction can be lifted later if we determine they are ok.
|
|
||||||
if (path.indexOf('\\') !== -1) {
|
|
||||||
throw new Error(getConfigFilePropertyError(configFile, propertyName, '"' + originalPath + '" contains an "\\" character. These are not allowed in filters. ' +
|
|
||||||
'If running on windows we recommend using "/" instead for path filters.'));
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
exports.validateAndSanitisePath = validateAndSanitisePath;
|
|
||||||
function getNameInvalid(configFile) {
|
function getNameInvalid(configFile) {
|
||||||
return getConfigFilePropertyError(configFile, NAME_PROPERTY, 'must be a non-empty string');
|
return getConfigFilePropertyError(configFile, NAME_PROPERTY, 'must be a non-empty string');
|
||||||
}
|
}
|
||||||
exports.getNameInvalid = getNameInvalid;
|
exports.getNameInvalid = getNameInvalid;
|
||||||
function getDisableDefaultQueriesInvalid(configFile) {
|
function getDisableDefaultQueriesInvalid(configFile) {
|
||||||
return getConfigFilePropertyError(configFile, DISABLE_DEFAULT_QUERIES_PROPERTY, 'must be a boolean');
|
return getConfigFilePropertyError(configFile, DISPLAY_DEFAULT_QUERIES_PROPERTY, 'must be a boolean');
|
||||||
}
|
}
|
||||||
exports.getDisableDefaultQueriesInvalid = getDisableDefaultQueriesInvalid;
|
exports.getDisableDefaultQueriesInvalid = getDisableDefaultQueriesInvalid;
|
||||||
function getQueriesInvalid(configFile) {
|
function getQueriesInvalid(configFile) {
|
||||||
@@ -263,117 +146,29 @@ function getConfigFileDoesNotExistErrorMessage(configFile) {
|
|||||||
return 'The configuration file "' + configFile + '" does not exist';
|
return 'The configuration file "' + configFile + '" does not exist';
|
||||||
}
|
}
|
||||||
exports.getConfigFileDoesNotExistErrorMessage = getConfigFileDoesNotExistErrorMessage;
|
exports.getConfigFileDoesNotExistErrorMessage = getConfigFileDoesNotExistErrorMessage;
|
||||||
function getConfigFileRepoFormatInvalidMessage(configFile) {
|
|
||||||
let error = 'The configuration file "' + configFile + '" is not a supported remote file reference.';
|
|
||||||
error += ' Expected format <owner>/<repository>/<file-path>@<ref>';
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
exports.getConfigFileRepoFormatInvalidMessage = getConfigFileRepoFormatInvalidMessage;
|
|
||||||
function getConfigFileFormatInvalidMessage(configFile) {
|
|
||||||
return 'The configuration file "' + configFile + '" could not be read';
|
|
||||||
}
|
|
||||||
exports.getConfigFileFormatInvalidMessage = getConfigFileFormatInvalidMessage;
|
|
||||||
function getConfigFileDirectoryGivenMessage(configFile) {
|
|
||||||
return 'The configuration file "' + configFile + '" looks like a directory, not a file';
|
|
||||||
}
|
|
||||||
exports.getConfigFileDirectoryGivenMessage = getConfigFileDirectoryGivenMessage;
|
|
||||||
function getConfigFilePropertyError(configFile, property, error) {
|
function getConfigFilePropertyError(configFile, property, error) {
|
||||||
return 'The configuration file "' + configFile + '" is invalid: property "' + property + '" ' + error;
|
return 'The configuration file "' + configFile + '" is invalid: property "' + property + '" ' + error;
|
||||||
}
|
}
|
||||||
/**
|
function initConfig() {
|
||||||
* Gets the set of languages in the current repository
|
let configFile = core.getInput('config-file');
|
||||||
*/
|
const config = new Config();
|
||||||
async function getLanguagesInRepo() {
|
// If no config file was provided create an empty one
|
||||||
var _a;
|
if (configFile === '') {
|
||||||
// Translate between GitHub's API names for languages and ours
|
core.debug('No configuration file was provided');
|
||||||
const codeqlLanguages = {
|
return config;
|
||||||
'C': 'cpp',
|
|
||||||
'C++': 'cpp',
|
|
||||||
'C#': 'csharp',
|
|
||||||
'Go': 'go',
|
|
||||||
'Java': 'java',
|
|
||||||
'JavaScript': 'javascript',
|
|
||||||
'TypeScript': 'javascript',
|
|
||||||
'Python': 'python',
|
|
||||||
};
|
|
||||||
let repo_nwo = (_a = process.env['GITHUB_REPOSITORY']) === null || _a === void 0 ? void 0 : _a.split("/");
|
|
||||||
if (repo_nwo) {
|
|
||||||
let owner = repo_nwo[0];
|
|
||||||
let repo = repo_nwo[1];
|
|
||||||
core.debug(`GitHub repo ${owner} ${repo}`);
|
|
||||||
const response = await api.getApiClient().request("GET /repos/:owner/:repo/languages", ({
|
|
||||||
owner,
|
|
||||||
repo
|
|
||||||
}));
|
|
||||||
core.debug("Languages API response: " + JSON.stringify(response));
|
|
||||||
// The GitHub API is going to return languages in order of popularity,
|
|
||||||
// When we pick a language to autobuild we want to pick the most popular traced language
|
|
||||||
// Since sets in javascript maintain insertion order, using a set here and then splatting it
|
|
||||||
// into an array gives us an array of languages ordered by popularity
|
|
||||||
let languages = new Set();
|
|
||||||
for (let lang in response.data) {
|
|
||||||
if (lang in codeqlLanguages) {
|
|
||||||
languages.add(codeqlLanguages[lang]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return [...languages];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the languages to analyse.
|
|
||||||
*
|
|
||||||
* The result is obtained from the action input parameter 'languages' if that
|
|
||||||
* has been set, otherwise it is deduced as all languages in the repo that
|
|
||||||
* can be analysed.
|
|
||||||
*/
|
|
||||||
async function getLanguages() {
|
|
||||||
// Obtain from action input 'languages' if set
|
|
||||||
let languages = core.getInput('languages', { required: false })
|
|
||||||
.split(',')
|
|
||||||
.map(x => x.trim())
|
|
||||||
.filter(x => x.length > 0);
|
|
||||||
core.info("Languages from configuration: " + JSON.stringify(languages));
|
|
||||||
if (languages.length === 0) {
|
|
||||||
// Obtain languages as all languages in the repo that can be analysed
|
|
||||||
languages = await getLanguagesInRepo();
|
|
||||||
core.info("Automatically detected languages: " + JSON.stringify(languages));
|
|
||||||
}
|
|
||||||
return languages;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the default config for when the user has not supplied one.
|
|
||||||
*/
|
|
||||||
async function getDefaultConfig() {
|
|
||||||
const languages = await getLanguages();
|
|
||||||
const queries = {};
|
|
||||||
await addDefaultQueries(languages, queries);
|
|
||||||
return {
|
|
||||||
languages: languages,
|
|
||||||
queries: queries,
|
|
||||||
pathsIgnore: [],
|
|
||||||
paths: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
exports.getDefaultConfig = getDefaultConfig;
|
|
||||||
/**
|
|
||||||
* Load the config from the given file.
|
|
||||||
*/
|
|
||||||
async function loadConfig(configFile) {
|
|
||||||
let parsedYAML;
|
|
||||||
if (isLocal(configFile)) {
|
|
||||||
// Treat the config file as relative to the workspace
|
// Treat the config file as relative to the workspace
|
||||||
const workspacePath = util.getRequiredEnvParam('GITHUB_WORKSPACE');
|
const workspacePath = util.getRequiredEnvParam('GITHUB_WORKSPACE');
|
||||||
configFile = path.resolve(workspacePath, configFile);
|
configFile = path.resolve(workspacePath, configFile);
|
||||||
parsedYAML = getLocalConfig(configFile, workspacePath);
|
// Error if the config file is now outside of the workspace
|
||||||
|
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
||||||
|
throw new Error(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
||||||
}
|
}
|
||||||
else {
|
// Error if the file does not exist
|
||||||
parsedYAML = await getRemoteConfig(configFile);
|
if (!fs.existsSync(configFile)) {
|
||||||
|
throw new Error(getConfigFileDoesNotExistErrorMessage(configFile));
|
||||||
}
|
}
|
||||||
// Validate that the 'name' property is syntactically correct,
|
const parsedYAML = yaml.safeLoad(fs.readFileSync(configFile, 'utf8'));
|
||||||
// even though we don't use the value yet.
|
|
||||||
if (NAME_PROPERTY in parsedYAML) {
|
if (NAME_PROPERTY in parsedYAML) {
|
||||||
if (typeof parsedYAML[NAME_PROPERTY] !== "string") {
|
if (typeof parsedYAML[NAME_PROPERTY] !== "string") {
|
||||||
throw new Error(getNameInvalid(configFile));
|
throw new Error(getNameInvalid(configFile));
|
||||||
@@ -381,36 +176,24 @@ async function loadConfig(configFile) {
|
|||||||
if (parsedYAML[NAME_PROPERTY].length === 0) {
|
if (parsedYAML[NAME_PROPERTY].length === 0) {
|
||||||
throw new Error(getNameInvalid(configFile));
|
throw new Error(getNameInvalid(configFile));
|
||||||
}
|
}
|
||||||
|
config.name = parsedYAML[NAME_PROPERTY];
|
||||||
}
|
}
|
||||||
const languages = await getLanguages();
|
if (DISPLAY_DEFAULT_QUERIES_PROPERTY in parsedYAML) {
|
||||||
// If the languages parameter was not given and no languages were
|
if (typeof parsedYAML[DISPLAY_DEFAULT_QUERIES_PROPERTY] !== "boolean") {
|
||||||
// detected then fail here as this is a workflow configuration error.
|
|
||||||
if (languages.length === 0) {
|
|
||||||
throw new Error("Did not detect any languages to analyze. Please update input in workflow.");
|
|
||||||
}
|
|
||||||
const queries = {};
|
|
||||||
const pathsIgnore = [];
|
|
||||||
const paths = [];
|
|
||||||
let disableDefaultQueries = false;
|
|
||||||
if (DISABLE_DEFAULT_QUERIES_PROPERTY in parsedYAML) {
|
|
||||||
if (typeof parsedYAML[DISABLE_DEFAULT_QUERIES_PROPERTY] !== "boolean") {
|
|
||||||
throw new Error(getDisableDefaultQueriesInvalid(configFile));
|
throw new Error(getDisableDefaultQueriesInvalid(configFile));
|
||||||
}
|
}
|
||||||
disableDefaultQueries = parsedYAML[DISABLE_DEFAULT_QUERIES_PROPERTY];
|
config.disableDefaultQueries = parsedYAML[DISPLAY_DEFAULT_QUERIES_PROPERTY];
|
||||||
}
|
|
||||||
if (!disableDefaultQueries) {
|
|
||||||
await addDefaultQueries(languages, queries);
|
|
||||||
}
|
}
|
||||||
if (QUERIES_PROPERTY in parsedYAML) {
|
if (QUERIES_PROPERTY in parsedYAML) {
|
||||||
if (!(parsedYAML[QUERIES_PROPERTY] instanceof Array)) {
|
if (!(parsedYAML[QUERIES_PROPERTY] instanceof Array)) {
|
||||||
throw new Error(getQueriesInvalid(configFile));
|
throw new Error(getQueriesInvalid(configFile));
|
||||||
}
|
}
|
||||||
for (const query of parsedYAML[QUERIES_PROPERTY]) {
|
parsedYAML[QUERIES_PROPERTY].forEach(query => {
|
||||||
if (!(QUERIES_USES_PROPERTY in query) || typeof query[QUERIES_USES_PROPERTY] !== "string") {
|
if (!(QUERIES_USES_PROPERTY in query) || typeof query[QUERIES_USES_PROPERTY] !== "string") {
|
||||||
throw new Error(getQueryUsesInvalid(configFile));
|
throw new Error(getQueryUsesInvalid(configFile));
|
||||||
}
|
}
|
||||||
await parseQueryUses(configFile, languages, queries, query[QUERIES_USES_PROPERTY]);
|
config.addQuery(configFile, query[QUERIES_USES_PROPERTY]);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
if (PATHS_IGNORE_PROPERTY in parsedYAML) {
|
if (PATHS_IGNORE_PROPERTY in parsedYAML) {
|
||||||
if (!(parsedYAML[PATHS_IGNORE_PROPERTY] instanceof Array)) {
|
if (!(parsedYAML[PATHS_IGNORE_PROPERTY] instanceof Array)) {
|
||||||
@@ -420,7 +203,7 @@ async function loadConfig(configFile) {
|
|||||||
if (typeof path !== "string" || path === '') {
|
if (typeof path !== "string" || path === '') {
|
||||||
throw new Error(getPathsIgnoreInvalid(configFile));
|
throw new Error(getPathsIgnoreInvalid(configFile));
|
||||||
}
|
}
|
||||||
pathsIgnore.push(validateAndSanitisePath(path, PATHS_IGNORE_PROPERTY, configFile));
|
config.pathsIgnore.push(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (PATHS_PROPERTY in parsedYAML) {
|
if (PATHS_PROPERTY in parsedYAML) {
|
||||||
@@ -431,117 +214,40 @@ async function loadConfig(configFile) {
|
|||||||
if (typeof path !== "string" || path === '') {
|
if (typeof path !== "string" || path === '') {
|
||||||
throw new Error(getPathsInvalid(configFile));
|
throw new Error(getPathsInvalid(configFile));
|
||||||
}
|
}
|
||||||
paths.push(validateAndSanitisePath(path, PATHS_PROPERTY, configFile));
|
config.paths.push(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return { languages, queries, pathsIgnore, paths };
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Load and return the config.
|
|
||||||
*
|
|
||||||
* This will parse the config from the user input if present, or generate
|
|
||||||
* a default config. The parsed config is then stored to a known location.
|
|
||||||
*/
|
|
||||||
async function initConfig() {
|
|
||||||
const configFile = core.getInput('config-file');
|
|
||||||
let config;
|
|
||||||
// If no config file was provided create an empty one
|
|
||||||
if (configFile === '') {
|
|
||||||
core.debug('No configuration file was provided');
|
|
||||||
config = await getDefaultConfig();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
config = await loadConfig(configFile);
|
|
||||||
}
|
|
||||||
// Save the config so we can easily access it again in the future
|
|
||||||
await saveConfig(config);
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
exports.initConfig = initConfig;
|
function getConfigFolder() {
|
||||||
function isLocal(configPath) {
|
|
||||||
// If the path starts with ./, look locally
|
|
||||||
if (configPath.indexOf("./") === 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return (configPath.indexOf("@") === -1);
|
|
||||||
}
|
|
||||||
function getLocalConfig(configFile, workspacePath) {
|
|
||||||
// Error if the config file is now outside of the workspace
|
|
||||||
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
|
||||||
throw new Error(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
|
||||||
}
|
|
||||||
// Error if the file does not exist
|
|
||||||
if (!fs.existsSync(configFile)) {
|
|
||||||
throw new Error(getConfigFileDoesNotExistErrorMessage(configFile));
|
|
||||||
}
|
|
||||||
return yaml.safeLoad(fs.readFileSync(configFile, 'utf8'));
|
|
||||||
}
|
|
||||||
async function getRemoteConfig(configFile) {
|
|
||||||
// retrieve the various parts of the config location, and ensure they're present
|
|
||||||
const format = new RegExp('(?<owner>[^/]+)/(?<repo>[^/]+)/(?<path>[^@]+)@(?<ref>.*)');
|
|
||||||
const pieces = format.exec(configFile);
|
|
||||||
// 5 = 4 groups + the whole expression
|
|
||||||
if (pieces === null || pieces.groups === undefined || pieces.length < 5) {
|
|
||||||
throw new Error(getConfigFileRepoFormatInvalidMessage(configFile));
|
|
||||||
}
|
|
||||||
const response = await api.getApiClient().repos.getContents({
|
|
||||||
owner: pieces.groups.owner,
|
|
||||||
repo: pieces.groups.repo,
|
|
||||||
path: pieces.groups.path,
|
|
||||||
ref: pieces.groups.ref,
|
|
||||||
});
|
|
||||||
let fileContents;
|
|
||||||
if ("content" in response.data && response.data.content !== undefined) {
|
|
||||||
fileContents = response.data.content;
|
|
||||||
}
|
|
||||||
else if (Array.isArray(response.data)) {
|
|
||||||
throw new Error(getConfigFileDirectoryGivenMessage(configFile));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Error(getConfigFileFormatInvalidMessage(configFile));
|
|
||||||
}
|
|
||||||
return yaml.safeLoad(Buffer.from(fileContents, 'base64').toString('binary'));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the directory where the parsed config will be stored.
|
|
||||||
*/
|
|
||||||
function getPathToParsedConfigFolder() {
|
|
||||||
return util.getRequiredEnvParam('RUNNER_TEMP');
|
return util.getRequiredEnvParam('RUNNER_TEMP');
|
||||||
}
|
}
|
||||||
/**
|
function getConfigFile() {
|
||||||
* Get the file path where the parsed config will be stored.
|
return path.join(getConfigFolder(), 'config');
|
||||||
*/
|
|
||||||
function getPathToParsedConfigFile() {
|
|
||||||
return path.join(getPathToParsedConfigFolder(), 'config');
|
|
||||||
}
|
}
|
||||||
exports.getPathToParsedConfigFile = getPathToParsedConfigFile;
|
exports.getConfigFile = getConfigFile;
|
||||||
/**
|
|
||||||
* Store the given config to the path returned from getPathToParsedConfigFile.
|
|
||||||
*/
|
|
||||||
async function saveConfig(config) {
|
async function saveConfig(config) {
|
||||||
const configString = JSON.stringify(config);
|
const configString = JSON.stringify(config);
|
||||||
await io.mkdirP(getPathToParsedConfigFolder());
|
await io.mkdirP(getConfigFolder());
|
||||||
fs.writeFileSync(getPathToParsedConfigFile(), configString, 'utf8');
|
fs.writeFileSync(getConfigFile(), configString, 'utf8');
|
||||||
core.debug('Saved config:');
|
core.debug('Saved config:');
|
||||||
core.debug(configString);
|
core.debug(configString);
|
||||||
}
|
}
|
||||||
/**
|
async function loadConfig() {
|
||||||
* Get the config.
|
const configFile = getConfigFile();
|
||||||
*
|
if (fs.existsSync(configFile)) {
|
||||||
* If this is the first time in a workflow that this is being called then
|
|
||||||
* this will parse the config from the user input. The parsed config is then
|
|
||||||
* stored to a known location. On the second and further calls, this will
|
|
||||||
* return the contents of the parsed config from the known location.
|
|
||||||
*/
|
|
||||||
async function getConfig() {
|
|
||||||
const configFile = getPathToParsedConfigFile();
|
|
||||||
if (!fs.existsSync(configFile)) {
|
|
||||||
throw new Error("Config file could not be found at expected location. Has the 'init' action been called?");
|
|
||||||
}
|
|
||||||
const configString = fs.readFileSync(configFile, 'utf8');
|
const configString = fs.readFileSync(configFile, 'utf8');
|
||||||
core.debug('Loaded config:');
|
core.debug('Loaded config:');
|
||||||
core.debug(configString);
|
core.debug(configString);
|
||||||
return JSON.parse(configString);
|
return JSON.parse(configString);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const config = initConfig();
|
||||||
|
core.debug('Initialized config:');
|
||||||
|
core.debug(JSON.stringify(config));
|
||||||
|
await saveConfig(config);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.getConfig = getConfig;
|
exports.loadConfig = loadConfig;
|
||||||
//# sourceMappingURL=config-utils.js.map
|
//# sourceMappingURL=config-utils.js.map
|
||||||
File diff suppressed because one or more lines are too long
Generated
+33
-256
@@ -1,4 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
if (mod && mod.__esModule) return mod;
|
if (mod && mod.__esModule) return mod;
|
||||||
var result = {};
|
var result = {};
|
||||||
@@ -6,21 +9,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
result["default"] = mod;
|
result["default"] = mod;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const github = __importStar(require("@actions/github"));
|
|
||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const sinon_1 = __importDefault(require("sinon"));
|
|
||||||
const api = __importStar(require("./api-client"));
|
|
||||||
const CodeQL = __importStar(require("./codeql"));
|
|
||||||
const configUtils = __importStar(require("./config-utils"));
|
const configUtils = __importStar(require("./config-utils"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
testing_utils_1.silenceDebugOutput(ava_1.default);
|
||||||
function setInput(name, value) {
|
function setInput(name, value) {
|
||||||
// Transformation copied from
|
// Transformation copied from
|
||||||
// https://github.com/actions/toolkit/blob/05e39f551d33e1688f61b209ab5cdd335198f1b8/packages/core/src/core.ts#L69
|
// https://github.com/actions/toolkit/blob/05e39f551d33e1688f61b209ab5cdd335198f1b8/packages/core/src/core.ts#L69
|
||||||
@@ -32,60 +28,27 @@ function setInput(name, value) {
|
|||||||
delete process.env[envVar];
|
delete process.env[envVar];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function mockGetContents(content) {
|
|
||||||
// Passing an auth token is required, so we just use a dummy value
|
|
||||||
let client = new github.GitHub('123');
|
|
||||||
const response = {
|
|
||||||
data: content
|
|
||||||
};
|
|
||||||
const spyGetContents = sinon_1.default.stub(client.repos, "getContents").resolves(response);
|
|
||||||
sinon_1.default.stub(api, "getApiClient").value(() => client);
|
|
||||||
return spyGetContents;
|
|
||||||
}
|
|
||||||
ava_1.default("load empty config", async (t) => {
|
ava_1.default("load empty config", async (t) => {
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
setInput('config-file', undefined);
|
setInput('config-file', undefined);
|
||||||
setInput('languages', 'javascript,python');
|
const config = await configUtils.loadConfig();
|
||||||
CodeQL.setCodeQL({
|
t.deepEqual(config, new configUtils.Config());
|
||||||
resolveQueries: async function () {
|
|
||||||
return {
|
|
||||||
byLanguage: {},
|
|
||||||
noDeclaredLanguage: {},
|
|
||||||
multipleDeclaredLanguages: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const config = await configUtils.initConfig();
|
|
||||||
t.deepEqual(config, await configUtils.getDefaultConfig());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ava_1.default("loading config saves config", async (t) => {
|
ava_1.default("loading config saves config", async (t) => {
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
setInput('config-file', undefined);
|
const configFile = configUtils.getConfigFile();
|
||||||
setInput('languages', 'javascript,python');
|
|
||||||
CodeQL.setCodeQL({
|
|
||||||
resolveQueries: async function () {
|
|
||||||
return {
|
|
||||||
byLanguage: {},
|
|
||||||
noDeclaredLanguage: {},
|
|
||||||
multipleDeclaredLanguages: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// Sanity check the saved config file does not already exist
|
// Sanity check the saved config file does not already exist
|
||||||
t.false(fs.existsSync(configUtils.getPathToParsedConfigFile()));
|
t.false(fs.existsSync(configFile));
|
||||||
// Sanity check that getConfig throws before we have called initConfig
|
const config = await configUtils.loadConfig();
|
||||||
await t.throwsAsync(configUtils.getConfig);
|
|
||||||
const config1 = await configUtils.initConfig();
|
|
||||||
// The saved config file should now exist
|
// The saved config file should now exist
|
||||||
t.true(fs.existsSync(configUtils.getPathToParsedConfigFile()));
|
t.true(fs.existsSync(configFile));
|
||||||
// And that same newly-initialised config should now be returned by getConfig
|
// And the contents should parse correctly to the config that was returned
|
||||||
const config2 = await configUtils.getConfig();
|
t.deepEqual(fs.readFileSync(configFile, 'utf8'), JSON.stringify(config));
|
||||||
t.deepEqual(config1, config2);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ava_1.default("load input outside of workspace", async (t) => {
|
ava_1.default("load input outside of workspace", async (t) => {
|
||||||
@@ -94,39 +57,23 @@ ava_1.default("load input outside of workspace", async (t) => {
|
|||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
setInput('config-file', '../input');
|
setInput('config-file', '../input');
|
||||||
try {
|
try {
|
||||||
await configUtils.initConfig();
|
await configUtils.loadConfig();
|
||||||
throw new Error('initConfig did not throw error');
|
throw new Error('loadConfig did not throw error');
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
t.deepEqual(err, new Error(configUtils.getConfigFileOutsideWorkspaceErrorMessage(path.join(tmpDir, '../input'))));
|
t.deepEqual(err, new Error(configUtils.getConfigFileOutsideWorkspaceErrorMessage(path.join(tmpDir, '../input'))));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ava_1.default("load non-local input with invalid repo syntax", async (t) => {
|
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
|
||||||
// no filename given, just a repo
|
|
||||||
setInput('config-file', 'octo-org/codeql-config@main');
|
|
||||||
try {
|
|
||||||
await configUtils.initConfig();
|
|
||||||
throw new Error('initConfig did not throw error');
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
t.deepEqual(err, new Error(configUtils.getConfigFileRepoFormatInvalidMessage('octo-org/codeql-config@main')));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ava_1.default("load non-existent input", async (t) => {
|
ava_1.default("load non-existent input", async (t) => {
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
t.false(fs.existsSync(path.join(tmpDir, 'input')));
|
t.false(fs.existsSync(path.join(tmpDir, 'input')));
|
||||||
setInput('config-file', 'input');
|
setInput('config-file', 'input');
|
||||||
setInput('languages', 'javascript');
|
|
||||||
try {
|
try {
|
||||||
await configUtils.initConfig();
|
await configUtils.loadConfig();
|
||||||
throw new Error('initConfig did not throw error');
|
throw new Error('loadConfig did not throw error');
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
t.deepEqual(err, new Error(configUtils.getConfigFileDoesNotExistErrorMessage(path.join(tmpDir, 'input'))));
|
t.deepEqual(err, new Error(configUtils.getConfigFileDoesNotExistErrorMessage(path.join(tmpDir, 'input'))));
|
||||||
@@ -137,102 +84,10 @@ ava_1.default("load non-empty input", async (t) => {
|
|||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
CodeQL.setCodeQL({
|
|
||||||
resolveQueries: async function () {
|
|
||||||
return {
|
|
||||||
byLanguage: {
|
|
||||||
'javascript': {
|
|
||||||
'/foo/a.ql': {},
|
|
||||||
'/bar/b.ql': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
noDeclaredLanguage: {},
|
|
||||||
multipleDeclaredLanguages: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// Just create a generic config object with non-default values for all fields
|
// Just create a generic config object with non-default values for all fields
|
||||||
const inputFileContents = `
|
const inputFileContents = `
|
||||||
name: my config
|
name: my config
|
||||||
disable-default-queries: true
|
disable-default-queries: true
|
||||||
queries:
|
|
||||||
- uses: ./foo
|
|
||||||
paths-ignore:
|
|
||||||
- a
|
|
||||||
- b
|
|
||||||
paths:
|
|
||||||
- c/d`;
|
|
||||||
fs.mkdirSync(path.join(tmpDir, 'foo'));
|
|
||||||
// And the config we expect it to parse to
|
|
||||||
const expectedConfig = {
|
|
||||||
languages: ['javascript'],
|
|
||||||
queries: { 'javascript': ['/foo/a.ql', '/bar/b.ql'] },
|
|
||||||
pathsIgnore: ['a', 'b'],
|
|
||||||
paths: ['c/d'],
|
|
||||||
};
|
|
||||||
fs.writeFileSync(path.join(tmpDir, 'input'), inputFileContents, 'utf8');
|
|
||||||
setInput('config-file', 'input');
|
|
||||||
setInput('languages', 'javascript');
|
|
||||||
const actualConfig = await configUtils.initConfig();
|
|
||||||
// Should exactly equal the object we constructed earlier
|
|
||||||
t.deepEqual(actualConfig, expectedConfig);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ava_1.default("default queries are used", async (t) => {
|
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
|
||||||
// Check that the default behaviour is to add the default queries.
|
|
||||||
// In this case if a config file is specified but does not include
|
|
||||||
// the disable-default-queries field.
|
|
||||||
// We determine this by whether CodeQL.resolveQueries is called
|
|
||||||
// with the correct arguments.
|
|
||||||
const resolveQueriesArgs = [];
|
|
||||||
CodeQL.setCodeQL({
|
|
||||||
resolveQueries: async function (queries, extraSearchPath) {
|
|
||||||
resolveQueriesArgs.push({ queries, extraSearchPath });
|
|
||||||
return {
|
|
||||||
byLanguage: {
|
|
||||||
'javascript': {},
|
|
||||||
},
|
|
||||||
noDeclaredLanguage: {},
|
|
||||||
multipleDeclaredLanguages: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// The important point of this config is that it doesn't specify
|
|
||||||
// the disable-default-queries field.
|
|
||||||
// Any other details are hopefully irrelevant for this tetst.
|
|
||||||
const inputFileContents = `
|
|
||||||
paths:
|
|
||||||
- foo`;
|
|
||||||
fs.mkdirSync(path.join(tmpDir, 'foo'));
|
|
||||||
fs.writeFileSync(path.join(tmpDir, 'input'), inputFileContents, 'utf8');
|
|
||||||
setInput('config-file', 'input');
|
|
||||||
setInput('languages', 'javascript');
|
|
||||||
await configUtils.initConfig();
|
|
||||||
// Check resolve queries was called correctly
|
|
||||||
t.deepEqual(resolveQueriesArgs.length, 1);
|
|
||||||
t.deepEqual(resolveQueriesArgs[0].queries, ['javascript-code-scanning.qls']);
|
|
||||||
t.deepEqual(resolveQueriesArgs[0].extraSearchPath, undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ava_1.default("API client used when reading remote config", async (t) => {
|
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
|
||||||
CodeQL.setCodeQL({
|
|
||||||
resolveQueries: async function () {
|
|
||||||
return {
|
|
||||||
byLanguage: {},
|
|
||||||
noDeclaredLanguage: {},
|
|
||||||
multipleDeclaredLanguages: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const inputFileContents = `
|
|
||||||
name: my config
|
|
||||||
disable-default-queries: true
|
|
||||||
queries:
|
queries:
|
||||||
- uses: ./
|
- uses: ./
|
||||||
- uses: ./foo
|
- uses: ./foo
|
||||||
@@ -242,52 +97,21 @@ ava_1.default("API client used when reading remote config", async (t) => {
|
|||||||
- b
|
- b
|
||||||
paths:
|
paths:
|
||||||
- c/d`;
|
- c/d`;
|
||||||
const dummyResponse = {
|
fs.mkdirSync(path.join(tmpDir, 'foo'));
|
||||||
content: Buffer.from(inputFileContents).toString("base64"),
|
// And the config we expect it to parse to
|
||||||
};
|
const expectedConfig = new configUtils.Config();
|
||||||
const spyGetContents = mockGetContents(dummyResponse);
|
expectedConfig.name = 'my config';
|
||||||
// Create checkout directory for remote queries repository
|
expectedConfig.disableDefaultQueries = true;
|
||||||
fs.mkdirSync(path.join(tmpDir, 'foo/bar'), { recursive: true });
|
expectedConfig.additionalQueries.push(fs.realpathSync(tmpDir));
|
||||||
setInput('config-file', 'octo-org/codeql-config/config.yaml@main');
|
expectedConfig.additionalQueries.push(fs.realpathSync(path.join(tmpDir, 'foo')));
|
||||||
setInput('languages', 'javascript');
|
expectedConfig.externalQueries = [new configUtils.ExternalQuery('foo/bar', 'dev')];
|
||||||
await configUtils.initConfig();
|
expectedConfig.pathsIgnore = ['a', 'b'];
|
||||||
t.assert(spyGetContents.called);
|
expectedConfig.paths = ['c/d'];
|
||||||
});
|
fs.writeFileSync(path.join(tmpDir, 'input'), inputFileContents, 'utf8');
|
||||||
});
|
setInput('config-file', 'input');
|
||||||
ava_1.default("Remote config handles the case where a directory is provided", async (t) => {
|
const actualConfig = await configUtils.loadConfig();
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
// Should exactly equal the object we constructed earlier
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
t.deepEqual(actualConfig, expectedConfig);
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
|
||||||
const dummyResponse = []; // directories are returned as arrays
|
|
||||||
mockGetContents(dummyResponse);
|
|
||||||
const repoReference = 'octo-org/codeql-config/config.yaml@main';
|
|
||||||
setInput('config-file', repoReference);
|
|
||||||
try {
|
|
||||||
await configUtils.initConfig();
|
|
||||||
throw new Error('initConfig did not throw error');
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
t.deepEqual(err, new Error(configUtils.getConfigFileDirectoryGivenMessage(repoReference)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ava_1.default("Invalid format of remote config handled correctly", async (t) => {
|
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
|
||||||
const dummyResponse = {
|
|
||||||
// note no "content" property here
|
|
||||||
};
|
|
||||||
mockGetContents(dummyResponse);
|
|
||||||
const repoReference = 'octo-org/codeql-config/config.yaml@main';
|
|
||||||
setInput('config-file', repoReference);
|
|
||||||
try {
|
|
||||||
await configUtils.initConfig();
|
|
||||||
throw new Error('initConfig did not throw error');
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference)));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGenerator) {
|
function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGenerator) {
|
||||||
@@ -295,22 +119,12 @@ function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGen
|
|||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
CodeQL.setCodeQL({
|
|
||||||
resolveQueries: async function () {
|
|
||||||
return {
|
|
||||||
byLanguage: {},
|
|
||||||
noDeclaredLanguage: {},
|
|
||||||
multipleDeclaredLanguages: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const inputFile = path.join(tmpDir, 'input');
|
const inputFile = path.join(tmpDir, 'input');
|
||||||
fs.writeFileSync(inputFile, inputFileContents, 'utf8');
|
fs.writeFileSync(inputFile, inputFileContents, 'utf8');
|
||||||
setInput('config-file', 'input');
|
setInput('config-file', 'input');
|
||||||
setInput('languages', 'javascript');
|
|
||||||
try {
|
try {
|
||||||
await configUtils.initConfig();
|
await configUtils.loadConfig();
|
||||||
throw new Error('initConfig did not throw error');
|
throw new Error('loadConfig did not throw error');
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
t.deepEqual(err, new Error(expectedErrorMessageGenerator(inputFile)));
|
t.deepEqual(err, new Error(expectedErrorMessageGenerator(inputFile)));
|
||||||
@@ -347,41 +161,4 @@ doInvalidQueryUsesTest("foo@master", c => configUtils.getQueryUsesInvalid(c, "fo
|
|||||||
doInvalidQueryUsesTest("https://github.com/foo/bar@master", c => configUtils.getQueryUsesInvalid(c, "https://github.com/foo/bar@master"));
|
doInvalidQueryUsesTest("https://github.com/foo/bar@master", c => configUtils.getQueryUsesInvalid(c, "https://github.com/foo/bar@master"));
|
||||||
doInvalidQueryUsesTest("./foo", c => configUtils.getLocalPathDoesNotExist(c, "foo"));
|
doInvalidQueryUsesTest("./foo", c => configUtils.getLocalPathDoesNotExist(c, "foo"));
|
||||||
doInvalidQueryUsesTest("./..", c => configUtils.getLocalPathOutsideOfRepository(c, ".."));
|
doInvalidQueryUsesTest("./..", c => configUtils.getLocalPathOutsideOfRepository(c, ".."));
|
||||||
const validPaths = [
|
|
||||||
'foo',
|
|
||||||
'foo/',
|
|
||||||
'foo/**',
|
|
||||||
'foo/**/',
|
|
||||||
'foo/**/**',
|
|
||||||
'foo/**/bar/**/baz',
|
|
||||||
'**/',
|
|
||||||
'**/foo',
|
|
||||||
'/foo',
|
|
||||||
];
|
|
||||||
const invalidPaths = [
|
|
||||||
'a/***/b',
|
|
||||||
'a/**b',
|
|
||||||
'a/b**',
|
|
||||||
'**',
|
|
||||||
];
|
|
||||||
ava_1.default('path validations', t => {
|
|
||||||
// Dummy values to pass to validateAndSanitisePath
|
|
||||||
const propertyName = 'paths';
|
|
||||||
const configFile = './.github/codeql/config.yml';
|
|
||||||
for (const path of validPaths) {
|
|
||||||
t.truthy(configUtils.validateAndSanitisePath(path, propertyName, configFile));
|
|
||||||
}
|
|
||||||
for (const path of invalidPaths) {
|
|
||||||
t.throws(() => configUtils.validateAndSanitisePath(path, propertyName, configFile));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ava_1.default('path sanitisation', t => {
|
|
||||||
// Dummy values to pass to validateAndSanitisePath
|
|
||||||
const propertyName = 'paths';
|
|
||||||
const configFile = './.github/codeql/config.yml';
|
|
||||||
// Valid paths are not modified
|
|
||||||
t.deepEqual(configUtils.validateAndSanitisePath('foo/bar', propertyName, configFile), 'foo/bar');
|
|
||||||
// Trailing stars are stripped
|
|
||||||
t.deepEqual(configUtils.validateAndSanitisePath('foo/**', propertyName, configFile), 'foo/');
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=config-utils.test.js.map
|
//# sourceMappingURL=config-utils.test.js.map
|
||||||
File diff suppressed because one or more lines are too long
Generated
+9
-10
@@ -12,23 +12,22 @@ const exec = __importStar(require("@actions/exec"));
|
|||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
/**
|
async function checkoutExternalQueries(config) {
|
||||||
* Check out repository at the given ref, and return the directory of the checkout.
|
|
||||||
*/
|
|
||||||
async function checkoutExternalRepository(repository, ref) {
|
|
||||||
const folder = util.getRequiredEnvParam('RUNNER_TEMP');
|
const folder = util.getRequiredEnvParam('RUNNER_TEMP');
|
||||||
core.info('Checking out ' + repository);
|
for (const externalQuery of config.externalQueries) {
|
||||||
const checkoutLocation = path.join(folder, repository);
|
core.info('Checking out ' + externalQuery.repository);
|
||||||
|
const checkoutLocation = path.join(folder, externalQuery.repository);
|
||||||
if (!fs.existsSync(checkoutLocation)) {
|
if (!fs.existsSync(checkoutLocation)) {
|
||||||
const repoURL = 'https://github.com/' + repository + '.git';
|
const repoURL = 'https://github.com/' + externalQuery.repository + '.git';
|
||||||
await exec.exec('git', ['clone', repoURL, checkoutLocation]);
|
await exec.exec('git', ['clone', repoURL, checkoutLocation]);
|
||||||
await exec.exec('git', [
|
await exec.exec('git', [
|
||||||
'--work-tree=' + checkoutLocation,
|
'--work-tree=' + checkoutLocation,
|
||||||
'--git-dir=' + checkoutLocation + '/.git',
|
'--git-dir=' + checkoutLocation + '/.git',
|
||||||
'checkout', ref,
|
'checkout', externalQuery.ref,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return checkoutLocation;
|
config.additionalQueries.push(path.join(checkoutLocation, externalQuery.path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.checkoutExternalRepository = checkoutExternalRepository;
|
exports.checkoutExternalQueries = checkoutExternalQueries;
|
||||||
//# sourceMappingURL=external-queries.js.map
|
//# sourceMappingURL=external-queries.js.map
|
||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"external-queries.js","sourceRoot":"","sources":["../src/external-queries.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAsC;AACtC,oDAAsC;AACtC,uCAAyB;AACzB,2CAA6B;AAE7B,6CAA+B;AAE/B;;GAEG;AACI,KAAK,UAAU,0BAA0B,CAAC,UAAkB,EAAE,GAAW;IAC9E,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAEvD,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC,CAAC;IAExC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;QACpC,MAAM,OAAO,GAAG,qBAAqB,GAAG,UAAU,GAAG,MAAM,CAAC;QAC5D,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;YACrB,cAAc,GAAG,gBAAgB;YACjC,YAAY,GAAG,gBAAgB,GAAG,OAAO;YACzC,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;KACJ;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAjBD,gEAiBC"}
|
{"version":3,"file":"external-queries.js","sourceRoot":"","sources":["../src/external-queries.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAsC;AACtC,oDAAsC;AACtC,uCAAyB;AACzB,2CAA6B;AAG7B,6CAA+B;AAExB,KAAK,UAAU,uBAAuB,CAAC,MAA0B;IACtE,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAEvD,KAAK,MAAM,aAAa,IAAI,MAAM,CAAC,eAAe,EAAE;QAClD,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAEtD,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QACrE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;YACpC,MAAM,OAAO,GAAG,qBAAqB,GAAG,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC;YAC1E,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;YAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACrB,cAAc,GAAG,gBAAgB;gBACjC,YAAY,GAAG,gBAAgB,GAAG,OAAO;gBACzC,UAAU,EAAE,aAAa,CAAC,GAAG;aAC9B,CAAC,CAAC;SACJ;QAED,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;KAChF;AACH,CAAC;AAnBD,0DAmBC"}
|
||||||
Generated
+8
-3
@@ -13,15 +13,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
|
const configUtils = __importStar(require("./config-utils"));
|
||||||
const externalQueries = __importStar(require("./external-queries"));
|
const externalQueries = __importStar(require("./external-queries"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
testing_utils_1.silenceDebugOutput(ava_1.default);
|
||||||
ava_1.default("checkoutExternalQueries", async (t) => {
|
ava_1.default("checkoutExternalQueries", async (t) => {
|
||||||
|
let config = new configUtils.Config();
|
||||||
|
config.externalQueries = [
|
||||||
|
new configUtils.ExternalQuery("github/codeql-go", "df4c6869212341b601005567381944ed90906b6b"),
|
||||||
|
];
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env["RUNNER_TEMP"] = tmpDir;
|
process.env["RUNNER_TEMP"] = tmpDir;
|
||||||
await externalQueries.checkoutExternalRepository("github/codeql-go", "df4c6869212341b601005567381944ed90906b6b");
|
await externalQueries.checkoutExternalQueries(config);
|
||||||
// COPYRIGHT file existed in df4c6869212341b601005567381944ed90906b6b but not in the default branch
|
// COPYRIGHT file existed in df4c6869212341b601005567381944ed90906b6b but not in master
|
||||||
t.true(fs.existsSync(path.join(tmpDir, "github", "codeql-go", "COPYRIGHT")));
|
t.true(fs.existsSync(path.join(tmpDir, "github", "codeql-go", "COPYRIGHT")));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"external-queries.test.js","sourceRoot":"","sources":["../src/external-queries.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AACvB,uCAAyB;AACzB,2CAA6B;AAE7B,oEAAsD;AACtD,mDAA2C;AAC3C,6CAA+B;AAE/B,0BAAU,CAAC,aAAI,CAAC,CAAC;AAEjB,aAAI,CAAC,yBAAyB,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACxC,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QACnC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;QACpC,MAAM,eAAe,CAAC,0BAA0B,CAAC,kBAAkB,EAAE,0CAA0C,CAAC,CAAC;QAEjH,mGAAmG;QACnG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
{"version":3,"file":"external-queries.test.js","sourceRoot":"","sources":["../src/external-queries.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AACvB,uCAAyB;AACzB,2CAA6B;AAE7B,4DAA8C;AAC9C,oEAAsD;AACtD,mDAAmD;AACnD,6CAA+B;AAE/B,kCAAkB,CAAC,aAAI,CAAC,CAAC;AAEzB,aAAI,CAAC,yBAAyB,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACxC,IAAI,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;IACtC,MAAM,CAAC,eAAe,GAAG;QACvB,IAAI,WAAW,CAAC,aAAa,CAAC,kBAAkB,EAAE,0CAA0C,CAAC;KAC9F,CAAC;IAEF,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;QACnC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;QACpC,MAAM,eAAe,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAEtD,uFAAuF;QACvF,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
||||||
Generated
+114
-38
@@ -12,17 +12,63 @@ const exec = __importStar(require("@actions/exec"));
|
|||||||
const io = __importStar(require("@actions/io"));
|
const io = __importStar(require("@actions/io"));
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const codeql_1 = require("./codeql");
|
|
||||||
const configUtils = __importStar(require("./config-utils"));
|
const configUtils = __importStar(require("./config-utils"));
|
||||||
|
const externalQueries = __importStar(require("./external-queries"));
|
||||||
const sharedEnv = __importStar(require("./shared-environment"));
|
const sharedEnv = __importStar(require("./shared-environment"));
|
||||||
const upload_lib = __importStar(require("./upload-lib"));
|
const upload_lib = __importStar(require("./upload-lib"));
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
async function setupPythonExtractor() {
|
/**
|
||||||
const codeqlPython = process.env["CODEQL_PYTHON"];
|
* A list of queries from https://github.com/github/codeql that
|
||||||
if (codeqlPython === undefined || codeqlPython.length === 0) {
|
* we don't want to run. Disabling them here is a quicker alternative to
|
||||||
// If CODEQL_PYTHON is not set, no dependencies were installed, so we don't need to do anything
|
* disabling them in the code scanning query suites. Queries should also
|
||||||
return;
|
* be disabled in the suites, and removed from this list here once the
|
||||||
|
* bundle is updated to make those suite changes live.
|
||||||
|
*
|
||||||
|
* Format is a map from language to an array of path suffixes of .ql files.
|
||||||
|
*/
|
||||||
|
const DISABLED_BUILTIN_QUERIES = {
|
||||||
|
'csharp': [
|
||||||
|
'ql/src/Security Features/CWE-937/VulnerablePackage.ql',
|
||||||
|
'ql/src/Security Features/CWE-451/MissingXFrameOptions.ql',
|
||||||
|
]
|
||||||
|
};
|
||||||
|
function queryIsDisabled(language, query) {
|
||||||
|
return (DISABLED_BUILTIN_QUERIES[language] || [])
|
||||||
|
.some(disabledQuery => query.endsWith(disabledQuery));
|
||||||
|
}
|
||||||
|
async function createdDBForScannedLanguages(codeqlCmd, databaseFolder) {
|
||||||
|
const scannedLanguages = process.env[sharedEnv.CODEQL_ACTION_SCANNED_LANGUAGES];
|
||||||
|
if (scannedLanguages) {
|
||||||
|
for (const language of scannedLanguages.split(',')) {
|
||||||
|
core.startGroup('Extracting ' + language);
|
||||||
|
// Get extractor location
|
||||||
|
let extractorPath = '';
|
||||||
|
await exec.exec(codeqlCmd, ['resolve', 'extractor', '--format=json', '--language=' + language], {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => { extractorPath += data.toString(); },
|
||||||
|
stderr: (data) => { process.stderr.write(data); }
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
// Set trace command
|
||||||
|
const ext = process.platform === 'win32' ? '.cmd' : '.sh';
|
||||||
|
const traceCommand = path.resolve(JSON.parse(extractorPath), 'tools', 'autobuild' + ext);
|
||||||
|
// Run trace command
|
||||||
|
await exec.exec(codeqlCmd, ['database', 'trace-command', path.join(databaseFolder, language), '--', traceCommand]);
|
||||||
|
core.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function finalizeDatabaseCreation(codeqlCmd, databaseFolder) {
|
||||||
|
await createdDBForScannedLanguages(codeqlCmd, databaseFolder);
|
||||||
|
const languages = process.env[sharedEnv.CODEQL_ACTION_LANGUAGES] || '';
|
||||||
|
for (const language of languages.split(',')) {
|
||||||
|
core.startGroup('Finalizing ' + language);
|
||||||
|
await exec.exec(codeqlCmd, ['database', 'finalize', path.join(databaseFolder, language)]);
|
||||||
|
core.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function runResolveQueries(codeqlCmd, queries) {
|
||||||
let output = '';
|
let output = '';
|
||||||
const options = {
|
const options = {
|
||||||
listeners: {
|
listeners: {
|
||||||
@@ -31,43 +77,61 @@ async function setupPythonExtractor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
await exec.exec(codeqlPython, ['-c', 'import os; import pip; print(os.path.dirname(os.path.dirname(pip.__file__)))'], options);
|
await exec.exec(codeqlCmd, [
|
||||||
core.info('Setting LGTM_INDEX_IMPORT_PATH=' + output);
|
'resolve',
|
||||||
process.env['LGTM_INDEX_IMPORT_PATH'] = output;
|
'queries',
|
||||||
output = '';
|
...queries,
|
||||||
await exec.exec(codeqlPython, ['-c', 'import sys; print(sys.version_info[0])'], options);
|
'--format=bylanguage'
|
||||||
core.info('Setting LGTM_PYTHON_SETUP_VERSION=' + output);
|
], options);
|
||||||
process.env['LGTM_PYTHON_SETUP_VERSION'] = output;
|
return JSON.parse(output);
|
||||||
}
|
}
|
||||||
async function createdDBForScannedLanguages(databaseFolder) {
|
async function resolveQueryLanguages(codeqlCmd, config) {
|
||||||
const scannedLanguages = process.env[sharedEnv.CODEQL_ACTION_SCANNED_LANGUAGES];
|
let res = new Map();
|
||||||
if (scannedLanguages) {
|
if (!config.disableDefaultQueries || config.additionalSuites.length !== 0) {
|
||||||
const codeql = codeql_1.getCodeQL();
|
const suites = [];
|
||||||
for (const language of scannedLanguages.split(',')) {
|
for (const language of await util.getLanguages()) {
|
||||||
core.startGroup('Extracting ' + language);
|
if (!config.disableDefaultQueries) {
|
||||||
if (language === 'python') {
|
suites.push(language + '-code-scanning.qls');
|
||||||
await setupPythonExtractor();
|
|
||||||
}
|
}
|
||||||
await codeql.extractScannedLanguage(path.join(databaseFolder, language), language);
|
for (const additionalSuite of config.additionalSuites) {
|
||||||
core.endGroup();
|
suites.push(language + '-' + additionalSuite + '.qls');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
const resolveQueriesOutputObject = await runResolveQueries(codeqlCmd, suites);
|
||||||
async function finalizeDatabaseCreation(databaseFolder, config) {
|
for (const [language, queries] of Object.entries(resolveQueriesOutputObject.byLanguage)) {
|
||||||
await createdDBForScannedLanguages(databaseFolder);
|
if (res[language] === undefined) {
|
||||||
const codeql = codeql_1.getCodeQL();
|
res[language] = [];
|
||||||
for (const language of config.languages) {
|
|
||||||
core.startGroup('Finalizing ' + language);
|
|
||||||
await codeql.finalizeDatabase(path.join(databaseFolder, language));
|
|
||||||
core.endGroup();
|
|
||||||
}
|
}
|
||||||
|
res[language].push(...Object.keys(queries).filter(q => !queryIsDisabled(language, q)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config.additionalQueries.length !== 0) {
|
||||||
|
const resolveQueriesOutputObject = await runResolveQueries(codeqlCmd, config.additionalQueries);
|
||||||
|
for (const [language, queries] of Object.entries(resolveQueriesOutputObject.byLanguage)) {
|
||||||
|
if (res[language] === undefined) {
|
||||||
|
res[language] = [];
|
||||||
|
}
|
||||||
|
res[language].push(...Object.keys(queries));
|
||||||
|
}
|
||||||
|
const noDeclaredLanguage = resolveQueriesOutputObject.noDeclaredLanguage;
|
||||||
|
const noDeclaredLanguageQueries = Object.keys(noDeclaredLanguage);
|
||||||
|
if (noDeclaredLanguageQueries.length !== 0) {
|
||||||
|
throw new Error('Some queries do not declare a language, their qlpack.yml file is missing or is invalid');
|
||||||
|
}
|
||||||
|
const multipleDeclaredLanguages = resolveQueriesOutputObject.multipleDeclaredLanguages;
|
||||||
|
const multipleDeclaredLanguagesQueries = Object.keys(multipleDeclaredLanguages);
|
||||||
|
if (multipleDeclaredLanguagesQueries.length !== 0) {
|
||||||
|
throw new Error('Some queries declare multiple languages, their qlpack.yml file is missing or is invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
// Runs queries and creates sarif files in the given folder
|
// Runs queries and creates sarif files in the given folder
|
||||||
async function runQueries(databaseFolder, sarifFolder, config) {
|
async function runQueries(codeqlCmd, databaseFolder, sarifFolder, config) {
|
||||||
const codeql = codeql_1.getCodeQL();
|
const queriesPerLanguage = await resolveQueryLanguages(codeqlCmd, config);
|
||||||
for (let database of fs.readdirSync(databaseFolder)) {
|
for (let database of fs.readdirSync(databaseFolder)) {
|
||||||
core.startGroup('Analyzing ' + database);
|
core.startGroup('Analyzing ' + database);
|
||||||
const queries = config.queries[database] || [];
|
const queries = queriesPerLanguage[database] || [];
|
||||||
if (queries.length === 0) {
|
if (queries.length === 0) {
|
||||||
throw new Error('Unable to analyse ' + database + ' as no queries were selected for this language');
|
throw new Error('Unable to analyse ' + database + ' as no queries were selected for this language');
|
||||||
}
|
}
|
||||||
@@ -78,7 +142,17 @@ async function runQueries(databaseFolder, sarifFolder, config) {
|
|||||||
fs.writeFileSync(querySuite, querySuiteContents);
|
fs.writeFileSync(querySuite, querySuiteContents);
|
||||||
core.debug('Query suite file for ' + database + '...\n' + querySuiteContents);
|
core.debug('Query suite file for ' + database + '...\n' + querySuiteContents);
|
||||||
const sarifFile = path.join(sarifFolder, database + '.sarif');
|
const sarifFile = path.join(sarifFolder, database + '.sarif');
|
||||||
await codeql.databaseAnalyze(path.join(databaseFolder, database), sarifFile, querySuite);
|
await exec.exec(codeqlCmd, [
|
||||||
|
'database',
|
||||||
|
'analyze',
|
||||||
|
util.getMemoryFlag(),
|
||||||
|
util.getThreadsFlag(),
|
||||||
|
path.join(databaseFolder, database),
|
||||||
|
'--format=sarif-latest',
|
||||||
|
'--output=' + sarifFile,
|
||||||
|
'--no-sarif-add-snippets',
|
||||||
|
querySuite
|
||||||
|
]);
|
||||||
core.debug('SARIF results for database ' + database + ' created at "' + sarifFile + '"');
|
core.debug('SARIF results for database ' + database + ' created at "' + sarifFile + '"');
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
}
|
}
|
||||||
@@ -88,16 +162,18 @@ async function run() {
|
|||||||
if (util.should_abort('finish', true) || !await util.reportActionStarting('finish')) {
|
if (util.should_abort('finish', true) || !await util.reportActionStarting('finish')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const config = await configUtils.getConfig();
|
const config = await configUtils.loadConfig();
|
||||||
core.exportVariable(sharedEnv.ODASA_TRACER_CONFIGURATION, '');
|
core.exportVariable(sharedEnv.ODASA_TRACER_CONFIGURATION, '');
|
||||||
delete process.env[sharedEnv.ODASA_TRACER_CONFIGURATION];
|
delete process.env[sharedEnv.ODASA_TRACER_CONFIGURATION];
|
||||||
|
const codeqlCmd = util.getRequiredEnvParam(sharedEnv.CODEQL_ACTION_CMD);
|
||||||
const databaseFolder = util.getRequiredEnvParam(sharedEnv.CODEQL_ACTION_DATABASE_DIR);
|
const databaseFolder = util.getRequiredEnvParam(sharedEnv.CODEQL_ACTION_DATABASE_DIR);
|
||||||
const sarifFolder = core.getInput('output');
|
const sarifFolder = core.getInput('output');
|
||||||
await io.mkdirP(sarifFolder);
|
await io.mkdirP(sarifFolder);
|
||||||
core.info('Finalizing database creation');
|
core.info('Finalizing database creation');
|
||||||
await finalizeDatabaseCreation(databaseFolder, config);
|
await finalizeDatabaseCreation(codeqlCmd, databaseFolder);
|
||||||
|
await externalQueries.checkoutExternalQueries(config);
|
||||||
core.info('Analyzing database');
|
core.info('Analyzing database');
|
||||||
await runQueries(databaseFolder, sarifFolder, config);
|
await runQueries(codeqlCmd, databaseFolder, sarifFolder, config);
|
||||||
if ('true' === core.getInput('upload')) {
|
if ('true' === core.getInput('upload')) {
|
||||||
if (!await upload_lib.upload(sarifFolder)) {
|
if (!await upload_lib.upload(sarifFolder)) {
|
||||||
await util.reportActionFailed('finish', 'upload');
|
await util.reportActionFailed('finish', 'upload');
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+1
-1
@@ -15,7 +15,7 @@ const fs = __importStar(require("fs"));
|
|||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const fingerprints = __importStar(require("./fingerprints"));
|
const fingerprints = __importStar(require("./fingerprints"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
testing_utils_1.silenceDebugOutput(ava_1.default);
|
||||||
function testHash(t, input, expectedHashes) {
|
function testHash(t, input, expectedHashes) {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
let callback = function (lineNumber, hash) {
|
let callback = function (lineNumber, hash) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+33
-56
@@ -10,12 +10,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const exec = __importStar(require("@actions/exec"));
|
const exec = __importStar(require("@actions/exec"));
|
||||||
const io = __importStar(require("@actions/io"));
|
const io = __importStar(require("@actions/io"));
|
||||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const analysisPaths = __importStar(require("./analysis-paths"));
|
const analysisPaths = __importStar(require("./analysis-paths"));
|
||||||
const codeql_1 = require("./codeql");
|
|
||||||
const configUtils = __importStar(require("./config-utils"));
|
const configUtils = __importStar(require("./config-utils"));
|
||||||
|
const setuptools = __importStar(require("./setup-tools"));
|
||||||
const sharedEnv = __importStar(require("./shared-environment"));
|
const sharedEnv = __importStar(require("./shared-environment"));
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
const CRITICAL_TRACER_VARS = new Set(['SEMMLE_PRELOAD_libtrace',
|
const CRITICAL_TRACER_VARS = new Set(['SEMMLE_PRELOAD_libtrace',
|
||||||
@@ -29,7 +28,12 @@ const CRITICAL_TRACER_VARS = new Set(['SEMMLE_PRELOAD_libtrace',
|
|||||||
'SEMMLE_JAVA_TOOL_OPTIONS'
|
'SEMMLE_JAVA_TOOL_OPTIONS'
|
||||||
]);
|
]);
|
||||||
async function tracerConfig(codeql, database, compilerSpec) {
|
async function tracerConfig(codeql, database, compilerSpec) {
|
||||||
const env = await codeql.getTracerEnv(database, compilerSpec);
|
const compilerSpecArg = compilerSpec ? ["--compiler-spec=" + compilerSpec] : [];
|
||||||
|
let envFile = path.resolve(database, 'working', 'env.tmp');
|
||||||
|
await exec.exec(codeql.cmd, ['database', 'trace-command', database,
|
||||||
|
...compilerSpecArg,
|
||||||
|
process.execPath, path.resolve(__dirname, 'tracer-env.js'), envFile]);
|
||||||
|
const env = JSON.parse(fs.readFileSync(envFile, 'utf-8'));
|
||||||
const config = env['ODASA_TRACER_CONFIGURATION'];
|
const config = env['ODASA_TRACER_CONFIGURATION'];
|
||||||
const info = { spec: config, env: {} };
|
const info = { spec: config, env: {} };
|
||||||
// Extract critical tracer variables from the environment
|
// Extract critical tracer variables from the environment
|
||||||
@@ -122,55 +126,21 @@ function concatTracerConfigs(configs) {
|
|||||||
fs.writeFileSync(envPath, buffer);
|
fs.writeFileSync(envPath, buffer);
|
||||||
return { env, spec };
|
return { env, spec };
|
||||||
}
|
}
|
||||||
async function installPythonDeps(codeql) {
|
|
||||||
core.startGroup('Setup Python dependencies');
|
|
||||||
let scriptsFolder = '';
|
|
||||||
try {
|
|
||||||
const repoPath = await toolcache.downloadTool('https://github.com/Daverlo/codeql-python-autobuild/archive/master.zip');
|
|
||||||
const extracted = await toolcache.extractZip(repoPath);
|
|
||||||
scriptsFolder = path.join(extracted, 'codeql-python-autobuild-master');
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// The download should not fail, but in case it fails we just abort trying to setup the python deps
|
|
||||||
core.warning('Unable to download and extract the scripts needed for installing the python dependecies');
|
|
||||||
core.endGroup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Setup tools
|
|
||||||
try {
|
|
||||||
await exec.exec(path.join(scriptsFolder, 'install_tools.sh'));
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// This script tries to install some needed tools in the runner. It should not fail, but if it does
|
|
||||||
// we just abort the process without failing the action
|
|
||||||
core.warning('Unable to download and extract the scripts needed for installing the python dependecies');
|
|
||||||
core.endGroup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Install dependencies
|
|
||||||
try {
|
|
||||||
await exec.exec(path.join(scriptsFolder, 'auto_install_packages.py'), [codeql.getDir()]);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
core.endGroup();
|
|
||||||
throw new Error('We were unable to install your python dependencies. You can call this action with "setup-python-dependencies: false" to disable this process');
|
|
||||||
}
|
|
||||||
core.endGroup();
|
|
||||||
}
|
|
||||||
async function run() {
|
async function run() {
|
||||||
let config;
|
let languages;
|
||||||
let codeql;
|
|
||||||
try {
|
try {
|
||||||
if (util.should_abort('init', false) || !await util.reportActionStarting('init')) {
|
if (util.should_abort('init', false) || !await util.reportActionStarting('init')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.startGroup('Setup CodeQL tools');
|
|
||||||
codeql = await codeql_1.setupCodeQL();
|
|
||||||
await codeql.printVersion();
|
|
||||||
core.endGroup();
|
|
||||||
core.startGroup('Load language configuration');
|
core.startGroup('Load language configuration');
|
||||||
config = await configUtils.initConfig();
|
const config = await configUtils.loadConfig();
|
||||||
analysisPaths.includeAndExcludeAnalysisPaths(config);
|
languages = await util.getLanguages();
|
||||||
|
// If the languages parameter was not given and no languages were
|
||||||
|
// detected then fail here as this is a workflow configuration error.
|
||||||
|
if (languages.length === 0) {
|
||||||
|
throw new Error("Did not detect any languages to analyze. Please update input in workflow.");
|
||||||
|
}
|
||||||
|
analysisPaths.includeAndExcludeAnalysisPaths(config, languages);
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
@@ -180,16 +150,16 @@ async function run() {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const sourceRoot = path.resolve();
|
const sourceRoot = path.resolve();
|
||||||
|
core.startGroup('Setup CodeQL tools');
|
||||||
|
const codeqlSetup = await setuptools.setupCodeQL();
|
||||||
|
await exec.exec(codeqlSetup.cmd, ['version', '--format=json']);
|
||||||
|
core.endGroup();
|
||||||
// Forward Go flags
|
// Forward Go flags
|
||||||
const goFlags = process.env['GOFLAGS'];
|
const goFlags = process.env['GOFLAGS'];
|
||||||
if (goFlags) {
|
if (goFlags) {
|
||||||
core.exportVariable('GOFLAGS', goFlags);
|
core.exportVariable('GOFLAGS', goFlags);
|
||||||
core.warning("Passing the GOFLAGS env parameter to the init action is deprecated. Please move this to the analyze action.");
|
core.warning("Passing the GOFLAGS env parameter to the init action is deprecated. Please move this to the analyze action.");
|
||||||
}
|
}
|
||||||
const setupPythonDependencies = core.getInput('setup-python-dependencies', { required: true });
|
|
||||||
if (config.languages.includes('python') && setupPythonDependencies === 'true') {
|
|
||||||
await installPythonDeps(codeql);
|
|
||||||
}
|
|
||||||
// Setup CODEQL_RAM flag (todo improve this https://github.com/github/dsp-code-scanning/issues/935)
|
// Setup CODEQL_RAM flag (todo improve this https://github.com/github/dsp-code-scanning/issues/935)
|
||||||
const codeqlRam = process.env['CODEQL_RAM'] || '6500';
|
const codeqlRam = process.env['CODEQL_RAM'] || '6500';
|
||||||
core.exportVariable('CODEQL_RAM', codeqlRam);
|
core.exportVariable('CODEQL_RAM', codeqlRam);
|
||||||
@@ -198,13 +168,19 @@ async function run() {
|
|||||||
let tracedLanguages = {};
|
let tracedLanguages = {};
|
||||||
let scannedLanguages = [];
|
let scannedLanguages = [];
|
||||||
// TODO: replace this code once CodeQL supports multi-language tracing
|
// TODO: replace this code once CodeQL supports multi-language tracing
|
||||||
for (let language of config.languages) {
|
for (let language of languages) {
|
||||||
const languageDatabase = path.join(databaseFolder, language);
|
const languageDatabase = path.join(databaseFolder, language);
|
||||||
// Init language database
|
// Init language database
|
||||||
await codeql.databaseInit(languageDatabase, language, sourceRoot);
|
await exec.exec(codeqlSetup.cmd, [
|
||||||
|
'database',
|
||||||
|
'init',
|
||||||
|
languageDatabase,
|
||||||
|
'--language=' + language,
|
||||||
|
'--source-root=' + sourceRoot,
|
||||||
|
]);
|
||||||
// TODO: add better detection of 'traced languages' instead of using a hard coded list
|
// TODO: add better detection of 'traced languages' instead of using a hard coded list
|
||||||
if (['cpp', 'java', 'csharp'].includes(language)) {
|
if (['cpp', 'java', 'csharp'].includes(language)) {
|
||||||
const config = await tracerConfig(codeql, languageDatabase);
|
const config = await tracerConfig(codeqlSetup, languageDatabase);
|
||||||
tracedLanguages[language] = config;
|
tracedLanguages[language] = config;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -220,16 +196,16 @@ async function run() {
|
|||||||
}
|
}
|
||||||
core.exportVariable('ODASA_TRACER_CONFIGURATION', mainTracerConfig.spec);
|
core.exportVariable('ODASA_TRACER_CONFIGURATION', mainTracerConfig.spec);
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
core.exportVariable('DYLD_INSERT_LIBRARIES', path.join(codeql.getDir(), 'tools', 'osx64', 'libtrace.dylib'));
|
core.exportVariable('DYLD_INSERT_LIBRARIES', path.join(codeqlSetup.tools, 'osx64', 'libtrace.dylib'));
|
||||||
}
|
}
|
||||||
else if (process.platform === 'win32') {
|
else if (process.platform === 'win32') {
|
||||||
await exec.exec('powershell', [
|
await exec.exec('powershell', [
|
||||||
path.resolve(__dirname, '..', 'src', 'inject-tracer.ps1'),
|
path.resolve(__dirname, '..', 'src', 'inject-tracer.ps1'),
|
||||||
path.resolve(codeql.getDir(), 'tools', 'win64', 'tracer.exe'),
|
path.resolve(codeqlSetup.tools, 'win64', 'tracer.exe'),
|
||||||
], { env: { 'ODASA_TRACER_CONFIGURATION': mainTracerConfig.spec } });
|
], { env: { 'ODASA_TRACER_CONFIGURATION': mainTracerConfig.spec } });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.exportVariable('LD_PRELOAD', path.join(codeql.getDir(), 'tools', 'linux64', '${LIB}trace.so'));
|
core.exportVariable('LD_PRELOAD', path.join(codeqlSetup.tools, 'linux64', '${LIB}trace.so'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,6 +213,7 @@ async function run() {
|
|||||||
core.exportVariable(sharedEnv.CODEQL_ACTION_TRACED_LANGUAGES, tracedLanguageKeys.join(','));
|
core.exportVariable(sharedEnv.CODEQL_ACTION_TRACED_LANGUAGES, tracedLanguageKeys.join(','));
|
||||||
// TODO: make this a "private" environment variable of the action
|
// TODO: make this a "private" environment variable of the action
|
||||||
core.exportVariable(sharedEnv.CODEQL_ACTION_DATABASE_DIR, databaseFolder);
|
core.exportVariable(sharedEnv.CODEQL_ACTION_DATABASE_DIR, databaseFolder);
|
||||||
|
core.exportVariable(sharedEnv.CODEQL_ACTION_CMD, codeqlSetup.cmd);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+2
@@ -1,6 +1,8 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.CODEQL_ACTION_CMD = 'CODEQL_ACTION_CMD';
|
||||||
exports.CODEQL_ACTION_DATABASE_DIR = 'CODEQL_ACTION_DATABASE_DIR';
|
exports.CODEQL_ACTION_DATABASE_DIR = 'CODEQL_ACTION_DATABASE_DIR';
|
||||||
|
exports.CODEQL_ACTION_LANGUAGES = 'CODEQL_ACTION_LANGUAGES';
|
||||||
exports.CODEQL_ACTION_ANALYSIS_KEY = 'CODEQL_ACTION_ANALYSIS_KEY';
|
exports.CODEQL_ACTION_ANALYSIS_KEY = 'CODEQL_ACTION_ANALYSIS_KEY';
|
||||||
exports.ODASA_TRACER_CONFIGURATION = 'ODASA_TRACER_CONFIGURATION';
|
exports.ODASA_TRACER_CONFIGURATION = 'ODASA_TRACER_CONFIGURATION';
|
||||||
exports.CODEQL_ACTION_SCANNED_LANGUAGES = 'CODEQL_ACTION_SCANNED_LANGUAGES';
|
exports.CODEQL_ACTION_SCANNED_LANGUAGES = 'CODEQL_ACTION_SCANNED_LANGUAGES';
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"shared-environment.js","sourceRoot":"","sources":["../src/shared-environment.ts"],"names":[],"mappings":";;AAAa,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAC1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAC1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAC1D,QAAA,+BAA+B,GAAG,iCAAiC,CAAC;AACpE,QAAA,8BAA8B,GAAG,gCAAgC,CAAC;AAC/E,wEAAwE;AACxE,2EAA2E;AAC3E,4EAA4E;AAC5E,2EAA2E;AAC3E,+BAA+B;AAClB,QAAA,wBAAwB,GAAG,0BAA0B,CAAC;AACnE,wDAAwD;AAC3C,QAAA,4BAA4B,GAAG,8BAA8B,CAAC"}
|
{"version":3,"file":"shared-environment.js","sourceRoot":"","sources":["../src/shared-environment.ts"],"names":[],"mappings":";;AAAa,QAAA,iBAAiB,GAAG,mBAAmB,CAAC;AACxC,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAC1D,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AACpD,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAC1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAC1D,QAAA,+BAA+B,GAAG,iCAAiC,CAAC;AACpE,QAAA,8BAA8B,GAAG,gCAAgC,CAAC;AAC/E,wEAAwE;AACxE,2EAA2E;AAC3E,4EAA4E;AAC5E,2EAA2E;AAC3E,+BAA+B;AAClB,QAAA,wBAAwB,GAAG,0BAA0B,CAAC;AACnE,wDAAwD;AAC3C,QAAA,4BAA4B,GAAG,8BAA8B,CAAC"}
|
||||||
Generated
+2
-29
@@ -1,17 +1,5 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const sinon_1 = __importDefault(require("sinon"));
|
|
||||||
const CodeQL = __importStar(require("./codeql"));
|
|
||||||
function wrapOutput(context) {
|
function wrapOutput(context) {
|
||||||
// Function signature taken from Socket.write.
|
// Function signature taken from Socket.write.
|
||||||
// Note there are two overloads:
|
// Note there are two overloads:
|
||||||
@@ -37,13 +25,9 @@ function wrapOutput(context) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function setupTests(test) {
|
function silenceDebugOutput(test) {
|
||||||
const typedTest = test;
|
const typedTest = test;
|
||||||
typedTest.beforeEach(t => {
|
typedTest.beforeEach(t => {
|
||||||
// Set an empty CodeQL object so that all method calls will fail
|
|
||||||
// unless the test explicitly sets one up.
|
|
||||||
CodeQL.setCodeQL({});
|
|
||||||
// Replace stdout and stderr so we can record output during tests
|
|
||||||
t.context.testOutput = "";
|
t.context.testOutput = "";
|
||||||
const processStdoutWrite = process.stdout.write.bind(process.stdout);
|
const processStdoutWrite = process.stdout.write.bind(process.stdout);
|
||||||
t.context.stdoutWrite = processStdoutWrite;
|
t.context.stdoutWrite = processStdoutWrite;
|
||||||
@@ -51,25 +35,14 @@ function setupTests(test) {
|
|||||||
const processStderrWrite = process.stderr.write.bind(process.stderr);
|
const processStderrWrite = process.stderr.write.bind(process.stderr);
|
||||||
t.context.stderrWrite = processStderrWrite;
|
t.context.stderrWrite = processStderrWrite;
|
||||||
process.stderr.write = wrapOutput(t.context);
|
process.stderr.write = wrapOutput(t.context);
|
||||||
// Many tests modify environment variables. Take a copy now so that
|
|
||||||
// we reset them after the test to keep tests independent of each other.
|
|
||||||
// process.env only has strings fields, so a shallow copy is fine.
|
|
||||||
t.context.env = {};
|
|
||||||
Object.assign(t.context.env, process.env);
|
|
||||||
});
|
});
|
||||||
typedTest.afterEach.always(t => {
|
typedTest.afterEach.always(t => {
|
||||||
// Restore stdout and stderr
|
|
||||||
// The captured output is only replayed if the test failed
|
|
||||||
process.stdout.write = t.context.stdoutWrite;
|
process.stdout.write = t.context.stdoutWrite;
|
||||||
process.stderr.write = t.context.stderrWrite;
|
process.stderr.write = t.context.stderrWrite;
|
||||||
if (!t.passed) {
|
if (!t.passed) {
|
||||||
process.stdout.write(t.context.testOutput);
|
process.stdout.write(t.context.testOutput);
|
||||||
}
|
}
|
||||||
// Undo any modifications made by sinon
|
|
||||||
sinon_1.default.restore();
|
|
||||||
// Undo any modifications to the env
|
|
||||||
process.env = t.context.env;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.setupTests = setupTests;
|
exports.silenceDebugOutput = silenceDebugOutput;
|
||||||
//# sourceMappingURL=testing-utils.js.map
|
//# sourceMappingURL=testing-utils.js.map
|
||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"testing-utils.js","sourceRoot":"","sources":["../src/testing-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,kDAA0B;AAE1B,iDAAmC;AAInC,SAAS,UAAU,CAAC,OAAoB;IACtC,8CAA8C;IAC9C,gCAAgC;IAChC,2EAA2E;IAC3E,2FAA2F;IAC3F,OAAO,CAAC,KAA0B,EAAE,QAAiB,EAAE,EAA0B,EAAW,EAAE;QAC5F,2CAA2C;QAC3C,IAAI,EAAE,KAAK,SAAS,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;YACtD,EAAE,GAAG,QAAQ,CAAC;YACd,QAAQ,GAAG,SAAS,CAAC;SACtB;QAED,oBAAoB;QACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC;SAC7B;aAAM;YACL,OAAO,CAAC,UAAU,IAAI,IAAI,WAAW,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SAC1E;QAED,iDAAiD;QACjD,IAAI,EAAE,KAAK,SAAS,IAAI,OAAO,EAAE,KAAK,UAAU,EAAE;YAChD,EAAE,EAAE,CAAC;SACN;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,UAAU,CAAC,IAAwB;IACjD,MAAM,SAAS,GAAG,IAAkC,CAAC;IAErD,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;QACvB,gEAAgE;QAChE,0CAA0C;QAC1C,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAErB,iEAAiE;QACjE,CAAC,CAAC,OAAO,CAAC,UAAU,GAAG,EAAE,CAAC;QAC1B,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrE,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,kBAAkB,CAAC;QAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAQ,CAAC;QACpD,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrE,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,kBAAkB,CAAC;QAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAQ,CAAC;QAEpD,mEAAmE;QACnE,wEAAwE;QACxE,kEAAkE;QAClE,CAAC,CAAC,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;QACnB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QAC7B,4BAA4B;QAC5B,0DAA0D;QAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAC7C,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;SAC5C;QAED,uCAAuC;QACvC,eAAK,CAAC,OAAO,EAAE,CAAC;QAEhB,oCAAoC;QACpC,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC;AAvCD,gCAuCC"}
|
{"version":3,"file":"testing-utils.js","sourceRoot":"","sources":["../src/testing-utils.ts"],"names":[],"mappings":";;AAIA,SAAS,UAAU,CAAC,OAAoB;IACtC,8CAA8C;IAC9C,gCAAgC;IAChC,2EAA2E;IAC3E,2FAA2F;IAC3F,OAAO,CAAC,KAA0B,EAAE,QAAiB,EAAE,EAA0B,EAAW,EAAE;QAC5F,2CAA2C;QAC3C,IAAI,EAAE,KAAK,SAAS,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;YACtD,EAAE,GAAG,QAAQ,CAAC;YACd,QAAQ,GAAG,SAAS,CAAC;SACtB;QAED,oBAAoB;QACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC;SAC7B;aAAM;YACL,OAAO,CAAC,UAAU,IAAI,IAAI,WAAW,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SAC1E;QAED,iDAAiD;QACjD,IAAI,EAAE,KAAK,SAAS,IAAI,OAAO,EAAE,KAAK,UAAU,EAAE;YAChD,EAAE,EAAE,CAAC;SACN;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,IAAwB;IACzD,MAAM,SAAS,GAAG,IAAkC,CAAC;IAErD,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;QACvB,CAAC,CAAC,OAAO,CAAC,UAAU,GAAG,EAAE,CAAC;QAE1B,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrE,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,kBAAkB,CAAC;QAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAQ,CAAC;QAEpD,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrE,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,kBAAkB,CAAC;QAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAQ,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAE7C,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;SAC5C;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAvBD,gDAuBC"}
|
||||||
Generated
+13
-13
@@ -11,12 +11,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
|
const http = __importStar(require("@actions/http-client"));
|
||||||
|
const auth = __importStar(require("@actions/http-client/auth"));
|
||||||
const file_url_1 = __importDefault(require("file-url"));
|
const file_url_1 = __importDefault(require("file-url"));
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const jsonschema = __importStar(require("jsonschema"));
|
const jsonschema = __importStar(require("jsonschema"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const zlib_1 = __importDefault(require("zlib"));
|
const zlib_1 = __importDefault(require("zlib"));
|
||||||
const api = __importStar(require("./api-client"));
|
|
||||||
const fingerprints = __importStar(require("./fingerprints"));
|
const fingerprints = __importStar(require("./fingerprints"));
|
||||||
const sharedEnv = __importStar(require("./shared-environment"));
|
const sharedEnv = __importStar(require("./shared-environment"));
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
@@ -50,28 +51,27 @@ async function uploadPayload(payload) {
|
|||||||
if (testMode) {
|
if (testMode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const [owner, repo] = util.getRequiredEnvParam("GITHUB_REPOSITORY").split("/");
|
const githubToken = core.getInput('token');
|
||||||
|
const ph = new auth.BearerCredentialHandler(githubToken);
|
||||||
|
const client = new http.HttpClient('Code Scanning : Upload SARIF', [ph]);
|
||||||
|
const url = 'https://api.github.com/repos/' + process.env['GITHUB_REPOSITORY'] + '/code-scanning/analysis';
|
||||||
// Make up to 4 attempts to upload, and sleep for these
|
// Make up to 4 attempts to upload, and sleep for these
|
||||||
// number of seconds between each attempt.
|
// number of seconds between each attempt.
|
||||||
// We don't want to backoff too much to avoid wasting action
|
// We don't want to backoff too much to avoid wasting action
|
||||||
// minutes, but just waiting a little bit could maybe help.
|
// minutes, but just waiting a little bit could maybe help.
|
||||||
const backoffPeriods = [1, 5, 15];
|
const backoffPeriods = [1, 5, 15];
|
||||||
for (let attempt = 0; attempt <= backoffPeriods.length; attempt++) {
|
for (let attempt = 0; attempt <= backoffPeriods.length; attempt++) {
|
||||||
const response = await api.getApiClient().request("PUT /repos/:owner/:repo/code-scanning/analysis", ({
|
const res = await client.put(url, payload);
|
||||||
owner: owner,
|
core.debug('response status: ' + res.message.statusCode);
|
||||||
repo: repo,
|
const statusCode = res.message.statusCode;
|
||||||
data: payload,
|
|
||||||
}));
|
|
||||||
core.debug('response status: ' + response.status);
|
|
||||||
const statusCode = response.status;
|
|
||||||
if (statusCode === 202) {
|
if (statusCode === 202) {
|
||||||
core.info("Successfully uploaded results");
|
core.info("Successfully uploaded results");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const requestID = response.headers["x-github-request-id"];
|
const requestID = res.message.headers["x-github-request-id"];
|
||||||
// On any other status code that's not 5xx mark the upload as failed
|
// On any other status code that's not 5xx mark the upload as failed
|
||||||
if (!statusCode || statusCode < 500 || statusCode >= 600) {
|
if (!statusCode || statusCode < 500 || statusCode >= 600) {
|
||||||
core.setFailed('Upload failed (' + requestID + '): (' + statusCode + ') ' + JSON.stringify(response.data));
|
core.setFailed('Upload failed (' + requestID + '): (' + statusCode + ') ' + await res.readBody());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// On a 5xx status code we may retry the request
|
// On a 5xx status code we may retry the request
|
||||||
@@ -79,7 +79,7 @@ async function uploadPayload(payload) {
|
|||||||
// Log the failure as a warning but don't mark the action as failed yet
|
// Log the failure as a warning but don't mark the action as failed yet
|
||||||
core.warning('Upload attempt (' + (attempt + 1) + ' of ' + (backoffPeriods.length + 1) +
|
core.warning('Upload attempt (' + (attempt + 1) + ' of ' + (backoffPeriods.length + 1) +
|
||||||
') failed (' + requestID + '). Retrying in ' + backoffPeriods[attempt] +
|
') failed (' + requestID + '). Retrying in ' + backoffPeriods[attempt] +
|
||||||
' seconds: (' + statusCode + ') ' + JSON.stringify(response.data));
|
' seconds: (' + statusCode + ') ' + await res.readBody());
|
||||||
// Sleep for the backoff period
|
// Sleep for the backoff period
|
||||||
await new Promise(r => setTimeout(r, backoffPeriods[attempt] * 1000));
|
await new Promise(r => setTimeout(r, backoffPeriods[attempt] * 1000));
|
||||||
continue;
|
continue;
|
||||||
@@ -88,7 +88,7 @@ async function uploadPayload(payload) {
|
|||||||
// If the upload fails with 5xx then we assume it is a temporary problem
|
// If the upload fails with 5xx then we assume it is a temporary problem
|
||||||
// and not an error that the user has caused or can fix.
|
// and not an error that the user has caused or can fix.
|
||||||
// We avoid marking the job as failed to avoid breaking CI workflows.
|
// We avoid marking the job as failed to avoid breaking CI workflows.
|
||||||
core.error('Upload failed (' + requestID + '): (' + statusCode + ') ' + JSON.stringify(response.data));
|
core.error('Upload failed (' + requestID + '): (' + statusCode + ') ' + await res.readBody());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+1
-1
@@ -13,7 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
const uploadLib = __importStar(require("./upload-lib"));
|
const uploadLib = __importStar(require("./upload-lib"));
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
testing_utils_1.silenceDebugOutput(ava_1.default);
|
||||||
ava_1.default('validateSarifFileSchema - valid', t => {
|
ava_1.default('validateSarifFileSchema - valid', t => {
|
||||||
const inputFile = __dirname + '/../src/testdata/valid-sarif.sarif';
|
const inputFile = __dirname + '/../src/testdata/valid-sarif.sarif';
|
||||||
t.true(uploadLib.validateSarifFileSchema(inputFile));
|
t.true(uploadLib.validateSarifFileSchema(inputFile));
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"upload-lib.test.js","sourceRoot":"","sources":["../src/upload-lib.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AAEvB,mDAA2C;AAC3C,wDAA0C;AAE1C,0BAAU,CAAC,aAAI,CAAC,CAAC;AAEjB,aAAI,CAAC,iCAAiC,EAAE,CAAC,CAAC,EAAE;IAC1C,MAAM,SAAS,GAAG,SAAS,GAAG,oCAAoC,CAAC;IACnE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,mCAAmC,EAAE,CAAC,CAAC,EAAE;IAC5C,MAAM,SAAS,GAAG,SAAS,GAAG,sCAAsC,CAAC;IACrE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,iFAAiF;IACjF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
{"version":3,"file":"upload-lib.test.js","sourceRoot":"","sources":["../src/upload-lib.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AAEvB,mDAAmD;AACnD,wDAA0C;AAE1C,kCAAkB,CAAC,aAAI,CAAC,CAAC;AAEzB,aAAI,CAAC,iCAAiC,EAAE,CAAC,CAAC,EAAE;IAC1C,MAAM,SAAS,GAAG,SAAS,GAAG,oCAAoC,CAAC;IACnE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,mCAAmC,EAAE,CAAC,CAAC,EAAE;IAC5C,MAAM,SAAS,GAAG,SAAS,GAAG,sCAAsC,CAAC;IACrE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,iFAAiF;IACjF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
||||||
Generated
+111
-45
@@ -6,14 +6,19 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
result["default"] = mod;
|
result["default"] = mod;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const exec = __importStar(require("@actions/exec"));
|
const exec = __importStar(require("@actions/exec"));
|
||||||
|
const http = __importStar(require("@actions/http-client"));
|
||||||
|
const auth = __importStar(require("@actions/http-client/auth"));
|
||||||
|
const octokit = __importStar(require("@octokit/rest"));
|
||||||
|
const console_log_level_1 = __importDefault(require("console-log-level"));
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const os = __importStar(require("os"));
|
const os = __importStar(require("os"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const api = __importStar(require("./api-client"));
|
|
||||||
const configUtils = __importStar(require("./config-utils"));
|
|
||||||
const sharedEnv = __importStar(require("./shared-environment"));
|
const sharedEnv = __importStar(require("./shared-environment"));
|
||||||
/**
|
/**
|
||||||
* Should the current action be aborted?
|
* Should the current action be aborted?
|
||||||
@@ -42,25 +47,99 @@ exports.should_abort = should_abort;
|
|||||||
*/
|
*/
|
||||||
function getRequiredEnvParam(paramName) {
|
function getRequiredEnvParam(paramName) {
|
||||||
const value = process.env[paramName];
|
const value = process.env[paramName];
|
||||||
if (value === undefined || value.length === 0) {
|
if (value === undefined) {
|
||||||
throw new Error(paramName + ' environment variable must be set');
|
throw new Error(paramName + ' environment variable must be set');
|
||||||
}
|
}
|
||||||
core.debug(paramName + '=' + value);
|
core.debug(paramName + '=' + value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
exports.getRequiredEnvParam = getRequiredEnvParam;
|
exports.getRequiredEnvParam = getRequiredEnvParam;
|
||||||
|
/**
|
||||||
|
* Gets the set of languages in the current repository
|
||||||
|
*/
|
||||||
|
async function getLanguagesInRepo() {
|
||||||
|
var _a;
|
||||||
|
// Translate between GitHub's API names for languages and ours
|
||||||
|
const codeqlLanguages = {
|
||||||
|
'C': 'cpp',
|
||||||
|
'C++': 'cpp',
|
||||||
|
'C#': 'csharp',
|
||||||
|
'Go': 'go',
|
||||||
|
'Java': 'java',
|
||||||
|
'JavaScript': 'javascript',
|
||||||
|
'TypeScript': 'javascript',
|
||||||
|
'Python': 'python',
|
||||||
|
};
|
||||||
|
let repo_nwo = (_a = process.env['GITHUB_REPOSITORY']) === null || _a === void 0 ? void 0 : _a.split("/");
|
||||||
|
if (repo_nwo) {
|
||||||
|
let owner = repo_nwo[0];
|
||||||
|
let repo = repo_nwo[1];
|
||||||
|
core.debug(`GitHub repo ${owner} ${repo}`);
|
||||||
|
let ok = new octokit.Octokit({
|
||||||
|
auth: core.getInput('token'),
|
||||||
|
userAgent: "CodeQL Action",
|
||||||
|
log: console_log_level_1.default({ level: "debug" })
|
||||||
|
});
|
||||||
|
const response = await ok.request("GET /repos/:owner/:repo/languages", ({
|
||||||
|
owner,
|
||||||
|
repo
|
||||||
|
}));
|
||||||
|
core.debug("Languages API response: " + JSON.stringify(response));
|
||||||
|
// The GitHub API is going to return languages in order of popularity,
|
||||||
|
// When we pick a language to autobuild we want to pick the most popular traced language
|
||||||
|
// Since sets in javascript maintain insertion order, using a set here and then splatting it
|
||||||
|
// into an array gives us an array of languages ordered by popularity
|
||||||
|
let languages = new Set();
|
||||||
|
for (let lang in response.data) {
|
||||||
|
if (lang in codeqlLanguages) {
|
||||||
|
languages.add(codeqlLanguages[lang]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [...languages];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the languages to analyse.
|
||||||
|
*
|
||||||
|
* The result is obtained from the environment parameter CODEQL_ACTION_LANGUAGES
|
||||||
|
* if that has been set, otherwise it is obtained from the action input parameter
|
||||||
|
* 'languages' if that has been set, otherwise it is deduced as all languages in the
|
||||||
|
* repo that can be analysed.
|
||||||
|
*
|
||||||
|
* If the languages are obtained from either of the second choices, the
|
||||||
|
* CODEQL_ACTION_LANGUAGES environment variable will be exported with the
|
||||||
|
* deduced list.
|
||||||
|
*/
|
||||||
|
async function getLanguages() {
|
||||||
|
// Obtain from CODEQL_ACTION_LANGUAGES if set
|
||||||
|
const langsVar = process.env[sharedEnv.CODEQL_ACTION_LANGUAGES];
|
||||||
|
if (langsVar) {
|
||||||
|
return langsVar.split(',')
|
||||||
|
.map(x => x.trim())
|
||||||
|
.filter(x => x.length > 0);
|
||||||
|
}
|
||||||
|
// Obtain from action input 'languages' if set
|
||||||
|
let languages = core.getInput('languages', { required: false })
|
||||||
|
.split(',')
|
||||||
|
.map(x => x.trim())
|
||||||
|
.filter(x => x.length > 0);
|
||||||
|
core.info("Languages from configuration: " + JSON.stringify(languages));
|
||||||
|
if (languages.length === 0) {
|
||||||
|
// Obtain languages as all languages in the repo that can be analysed
|
||||||
|
languages = await getLanguagesInRepo();
|
||||||
|
core.info("Automatically detected languages: " + JSON.stringify(languages));
|
||||||
|
}
|
||||||
|
core.exportVariable(sharedEnv.CODEQL_ACTION_LANGUAGES, languages.join(','));
|
||||||
|
return languages;
|
||||||
|
}
|
||||||
|
exports.getLanguages = getLanguages;
|
||||||
/**
|
/**
|
||||||
* Gets the SHA of the commit that is currently checked out.
|
* Gets the SHA of the commit that is currently checked out.
|
||||||
*/
|
*/
|
||||||
async function getCommitOid() {
|
async function getCommitOid() {
|
||||||
// Try to use git to get the current commit SHA. If that fails then
|
|
||||||
// log but otherwise silently fall back to using the SHA from the environment.
|
|
||||||
// The only time these two values will differ is during analysis of a PR when
|
|
||||||
// the workflow has changed the current commit to the head commit instead of
|
|
||||||
// the merge commit, which must mean that git is available.
|
|
||||||
// Even if this does go wrong, it's not a huge problem for the alerts to
|
|
||||||
// reported on the merge commit.
|
|
||||||
try {
|
|
||||||
let commitOid = '';
|
let commitOid = '';
|
||||||
await exec.exec('git', ['rev-parse', 'HEAD'], {
|
await exec.exec('git', ['rev-parse', 'HEAD'], {
|
||||||
silent: true,
|
silent: true,
|
||||||
@@ -70,11 +149,6 @@ async function getCommitOid() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return commitOid.trim();
|
return commitOid.trim();
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
core.info("Failed to call git to get current commit. Continuing with data from environment: " + e);
|
|
||||||
return getRequiredEnvParam('GITHUB_SHA');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exports.getCommitOid = getCommitOid;
|
exports.getCommitOid = getCommitOid;
|
||||||
/**
|
/**
|
||||||
@@ -84,15 +158,19 @@ async function getWorkflowPath() {
|
|||||||
const repo_nwo = getRequiredEnvParam('GITHUB_REPOSITORY').split("/");
|
const repo_nwo = getRequiredEnvParam('GITHUB_REPOSITORY').split("/");
|
||||||
const owner = repo_nwo[0];
|
const owner = repo_nwo[0];
|
||||||
const repo = repo_nwo[1];
|
const repo = repo_nwo[1];
|
||||||
const run_id = Number(getRequiredEnvParam('GITHUB_RUN_ID'));
|
const run_id = getRequiredEnvParam('GITHUB_RUN_ID');
|
||||||
const apiClient = api.getApiClient();
|
const ok = new octokit.Octokit({
|
||||||
const runsResponse = await apiClient.request('GET /repos/:owner/:repo/actions/runs/:run_id', {
|
auth: core.getInput('token'),
|
||||||
|
userAgent: "CodeQL Action",
|
||||||
|
log: console_log_level_1.default({ level: 'debug' })
|
||||||
|
});
|
||||||
|
const runsResponse = await ok.request('GET /repos/:owner/:repo/actions/runs/:run_id', {
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
run_id
|
run_id
|
||||||
});
|
});
|
||||||
const workflowUrl = runsResponse.data.workflow_url;
|
const workflowUrl = runsResponse.data.workflow_url;
|
||||||
const workflowResponse = await apiClient.request('GET ' + workflowUrl);
|
const workflowResponse = await ok.request('GET ' + workflowUrl);
|
||||||
return workflowResponse.data.path;
|
return workflowResponse.data.path;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -143,18 +221,6 @@ exports.getRef = getRef;
|
|||||||
* @param exception Exception (only supply if status is 'failure')
|
* @param exception Exception (only supply if status is 'failure')
|
||||||
*/
|
*/
|
||||||
async function createStatusReport(actionName, status, cause, exception) {
|
async function createStatusReport(actionName, status, cause, exception) {
|
||||||
var _a, _b;
|
|
||||||
// If this is not the init action starting up or aborting then try to load the config.
|
|
||||||
// If it fails then carry because it's important to still send the status report.
|
|
||||||
let config = undefined;
|
|
||||||
if (actionName !== 'init' || (status !== 'starting' && status !== 'aborted')) {
|
|
||||||
try {
|
|
||||||
config = await configUtils.getConfig();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
core.error('Unable to load config: ' + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const commitOid = process.env['GITHUB_SHA'] || '';
|
const commitOid = process.env['GITHUB_SHA'] || '';
|
||||||
const ref = getRef();
|
const ref = getRef();
|
||||||
const workflowRunIDStr = process.env['GITHUB_RUN_ID'];
|
const workflowRunIDStr = process.env['GITHUB_RUN_ID'];
|
||||||
@@ -164,15 +230,13 @@ async function createStatusReport(actionName, status, cause, exception) {
|
|||||||
}
|
}
|
||||||
const workflowName = process.env['GITHUB_WORKFLOW'] || '';
|
const workflowName = process.env['GITHUB_WORKFLOW'] || '';
|
||||||
const jobName = process.env['GITHUB_JOB'] || '';
|
const jobName = process.env['GITHUB_JOB'] || '';
|
||||||
const analysis_key = await getAnalysisKey();
|
const languages = (await getLanguages()).sort().join(',');
|
||||||
const languages = ((_b = (_a = config) === null || _a === void 0 ? void 0 : _a.languages) === null || _b === void 0 ? void 0 : _b.join(',')) || "";
|
|
||||||
const startedAt = process.env[sharedEnv.CODEQL_ACTION_STARTED_AT] || new Date().toISOString();
|
const startedAt = process.env[sharedEnv.CODEQL_ACTION_STARTED_AT] || new Date().toISOString();
|
||||||
core.exportVariable(sharedEnv.CODEQL_ACTION_STARTED_AT, startedAt);
|
core.exportVariable(sharedEnv.CODEQL_ACTION_STARTED_AT, startedAt);
|
||||||
let statusReport = {
|
let statusReport = {
|
||||||
workflow_run_id: workflowRunID,
|
workflow_run_id: workflowRunID,
|
||||||
workflow_name: workflowName,
|
workflow_name: workflowName,
|
||||||
job_name: jobName,
|
job_name: jobName,
|
||||||
analysis_key: analysis_key,
|
|
||||||
languages: languages,
|
languages: languages,
|
||||||
commit_oid: commitOid,
|
commit_oid: commitOid,
|
||||||
ref: ref,
|
ref: ref,
|
||||||
@@ -188,7 +252,7 @@ async function createStatusReport(actionName, status, cause, exception) {
|
|||||||
if (exception) {
|
if (exception) {
|
||||||
statusReport.exception = exception;
|
statusReport.exception = exception;
|
||||||
}
|
}
|
||||||
if (status === 'success' || status === 'failure' || status === 'aborted') {
|
if (status === 'success' || status === 'failure') {
|
||||||
statusReport.completed_at = new Date().toISOString();
|
statusReport.completed_at = new Date().toISOString();
|
||||||
}
|
}
|
||||||
let matrix = core.getInput('matrix');
|
let matrix = core.getInput('matrix');
|
||||||
@@ -200,19 +264,21 @@ async function createStatusReport(actionName, status, cause, exception) {
|
|||||||
/**
|
/**
|
||||||
* Send a status report to the code_scanning/analysis/status endpoint.
|
* Send a status report to the code_scanning/analysis/status endpoint.
|
||||||
*
|
*
|
||||||
* Returns the status code of the response to the status request.
|
* Returns the status code of the response to the status request, or
|
||||||
|
* undefined if the given statusReport is undefined or no response was
|
||||||
|
* received.
|
||||||
*/
|
*/
|
||||||
async function sendStatusReport(statusReport) {
|
async function sendStatusReport(statusReport) {
|
||||||
|
var _a;
|
||||||
const statusReportJSON = JSON.stringify(statusReport);
|
const statusReportJSON = JSON.stringify(statusReport);
|
||||||
core.debug('Sending status report: ' + statusReportJSON);
|
core.debug('Sending status report: ' + statusReportJSON);
|
||||||
const nwo = getRequiredEnvParam("GITHUB_REPOSITORY");
|
const githubToken = core.getInput('token');
|
||||||
const [owner, repo] = nwo.split("/");
|
const ph = new auth.BearerCredentialHandler(githubToken);
|
||||||
const statusResponse = await api.getApiClient().request('PUT /repos/:owner/:repo/code-scanning/analysis/status', {
|
const client = new http.HttpClient('Code Scanning : Status Report', [ph]);
|
||||||
owner: owner,
|
const url = 'https://api.github.com/repos/' + process.env['GITHUB_REPOSITORY']
|
||||||
repo: repo,
|
+ '/code-scanning/analysis/status';
|
||||||
data: statusReportJSON,
|
const res = await client.put(url, statusReportJSON);
|
||||||
});
|
return (_a = res.message) === null || _a === void 0 ? void 0 : _a.statusCode;
|
||||||
return statusResponse.status;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Send a status report that an action is starting.
|
* Send a status report that an action is starting.
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+5
-7
@@ -15,7 +15,7 @@ const fs = __importStar(require("fs"));
|
|||||||
const os = __importStar(require("os"));
|
const os = __importStar(require("os"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
testing_utils_1.setupTests(ava_1.default);
|
testing_utils_1.silenceDebugOutput(ava_1.default);
|
||||||
ava_1.default('getToolNames', t => {
|
ava_1.default('getToolNames', t => {
|
||||||
const input = fs.readFileSync(__dirname + '/../src/testdata/tool-names.sarif', 'utf8');
|
const input = fs.readFileSync(__dirname + '/../src/testdata/tool-names.sarif', 'utf8');
|
||||||
const toolNames = util.getToolNames(input);
|
const toolNames = util.getToolNames(input);
|
||||||
@@ -53,12 +53,10 @@ ava_1.default('getThreadsFlag() should return the correct --threads flag', t =>
|
|||||||
t.deepEqual(flag, expectedFlag);
|
t.deepEqual(flag, expectedFlag);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ava_1.default('getThreadsFlag() throws if the threads input is not an integer', t => {
|
ava_1.default('getThreadsFlag() throws if the ram input is < 0 or NaN', t => {
|
||||||
process.env['INPUT_THREADS'] = "hello!";
|
for (const input of ["hello!"]) {
|
||||||
|
process.env['INPUT_THREADS'] = input;
|
||||||
t.throws(util.getThreadsFlag);
|
t.throws(util.getThreadsFlag);
|
||||||
});
|
}
|
||||||
ava_1.default('getRef() throws on the empty string', t => {
|
|
||||||
process.env["GITHUB_REF"] = "";
|
|
||||||
t.throws(util.getRef);
|
|
||||||
});
|
});
|
||||||
//# sourceMappingURL=util.test.js.map
|
//# sourceMappingURL=util.test.js.map
|
||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"util.test.js","sourceRoot":"","sources":["../src/util.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AACvB,uCAAyB;AACzB,uCAAyB;AAEzB,mDAA2C;AAC3C,6CAA+B;AAE/B,0BAAU,CAAC,aAAI,CAAC,CAAC;AAEjB,aAAI,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE;IACvB,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,GAAG,mCAAmC,EAAE,MAAM,CAAC,CAAC;IACvF,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,+BAA+B,EAAE,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,sDAAsD,EAAE,CAAC,CAAC,EAAE;IAE/D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;IAE3D,MAAM,KAAK,GAAG;QACZ,EAAE,EAAE,SAAS,QAAQ,GAAG,GAAG,EAAE;QAC7B,KAAK,EAAE,WAAW;KACnB,CAAC;IAEF,KAAK,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QAEzD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;QAEjC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;KACjC;AACH,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,uDAAuD,EAAE,CAAC,CAAC,EAAE;IAChE,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;QACpC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;QACjC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;KAC9B;AACH,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,2DAA2D,EAAE,CAAC,CAAC,EAAE;IAEpE,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAEjC,MAAM,KAAK,GAAG;QACZ,GAAG,EAAE,aAAa;QAClB,GAAG,EAAE,aAAa;QAClB,CAAC,GAAG,OAAO,GAAG,CAAC,EAAE,CAAC,EAAE,aAAa,OAAO,EAAE;QAC1C,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,OAAO,EAAE;KAC7C,CAAC;IAEF,KAAK,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QAEzD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC;QAErC,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACnC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;KACjC;AACH,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,gEAAgE,EAAE,CAAC,CAAC,EAAE;IACzE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAC;IACxC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,qCAAqC,EAAE,CAAC,CAAC,EAAE;IAC9C,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC"}
|
{"version":3,"file":"util.test.js","sourceRoot":"","sources":["../src/util.test.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAuB;AACvB,uCAAyB;AACzB,uCAAyB;AAEzB,mDAAmD;AACnD,6CAA+B;AAE/B,kCAAkB,CAAC,aAAI,CAAC,CAAC;AAEzB,aAAI,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE;IACvB,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,GAAG,mCAAmC,EAAE,MAAM,CAAC,CAAC;IACvF,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,+BAA+B,EAAE,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,sDAAsD,EAAE,CAAC,CAAC,EAAE;IAE/D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;IAE3D,MAAM,KAAK,GAAG;QACZ,EAAE,EAAE,SAAS,QAAQ,GAAG,GAAG,EAAE;QAC7B,KAAK,EAAE,WAAW;KACnB,CAAC;IAEF,KAAK,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QAEzD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;QAEjC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;KACjC;AACH,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,uDAAuD,EAAE,CAAC,CAAC,EAAE;IAChE,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;QACpC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;QACjC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;KAC9B;AACH,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,2DAA2D,EAAE,CAAC,CAAC,EAAE;IAEpE,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAEjC,MAAM,KAAK,GAAG;QACZ,GAAG,EAAE,aAAa;QAClB,GAAG,EAAE,aAAa;QAClB,CAAC,GAAG,OAAO,GAAG,CAAC,EAAE,CAAC,EAAE,aAAa,OAAO,EAAE;QAC1C,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,OAAO,EAAE;KAC7C,CAAC;IAEF,KAAK,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QAEzD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC;QAErC,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACnC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;KACjC;AACH,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,wDAAwD,EAAE,CAAC,CAAC,EAAE;IACjE,KAAK,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC;QACrC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KAC/B;AACH,CAAC,CAAC,CAAC"}
|
||||||
-74
@@ -1,74 +0,0 @@
|
|||||||
# `@actions/github`
|
|
||||||
|
|
||||||
> A hydrated Octokit client.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Returns an authenticated Octokit client that follows the machine [proxy settings](https://help.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners). See https://octokit.github.io/rest.js for the API.
|
|
||||||
|
|
||||||
```js
|
|
||||||
const github = require('@actions/github');
|
|
||||||
const core = require('@actions/core');
|
|
||||||
|
|
||||||
async function run() {
|
|
||||||
// This should be a token with access to your repository scoped in as a secret.
|
|
||||||
// The YML workflow will need to set myToken with the GitHub Secret Token
|
|
||||||
// myToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
// https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#about-the-github_token-secret
|
|
||||||
const myToken = core.getInput('myToken');
|
|
||||||
|
|
||||||
const octokit = new github.GitHub(myToken);
|
|
||||||
|
|
||||||
const { data: pullRequest } = await octokit.pulls.get({
|
|
||||||
owner: 'octokit',
|
|
||||||
repo: 'rest.js',
|
|
||||||
pull_number: 123,
|
|
||||||
mediaType: {
|
|
||||||
format: 'diff'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(pullRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
run();
|
|
||||||
```
|
|
||||||
|
|
||||||
You can pass client options, as specified by [Octokit](https://octokit.github.io/rest.js/), as a second argument to the `GitHub` constructor.
|
|
||||||
|
|
||||||
You can also make GraphQL requests. See https://github.com/octokit/graphql.js for the API.
|
|
||||||
|
|
||||||
```js
|
|
||||||
const result = await octokit.graphql(query, variables);
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, you can get the context of the current action:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const github = require('@actions/github');
|
|
||||||
|
|
||||||
const context = github.context;
|
|
||||||
|
|
||||||
const newIssue = await octokit.issues.create({
|
|
||||||
...context.repo,
|
|
||||||
title: 'New issue!',
|
|
||||||
body: 'Hello Universe!'
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Webhook payload typescript definitions
|
|
||||||
|
|
||||||
The npm module `@octokit/webhooks` provides type definitions for the response payloads. You can cast the payload to these types for better type information.
|
|
||||||
|
|
||||||
First, install the npm module `npm install @octokit/webhooks`
|
|
||||||
|
|
||||||
Then, assert the type based on the eventName
|
|
||||||
```ts
|
|
||||||
import * as core from '@actions/core'
|
|
||||||
import * as github from '@actions/github'
|
|
||||||
import * as Webhooks from '@octokit/webhooks'
|
|
||||||
if (github.context.eventName === 'push') {
|
|
||||||
const pushPayload = github.context.payload as Webhooks.WebhookPayloadPush
|
|
||||||
core.info(`The head commit is: ${pushPayload.head}`)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
-26
@@ -1,26 +0,0 @@
|
|||||||
import { WebhookPayload } from './interfaces';
|
|
||||||
export declare class Context {
|
|
||||||
/**
|
|
||||||
* Webhook payload object that triggered the workflow
|
|
||||||
*/
|
|
||||||
payload: WebhookPayload;
|
|
||||||
eventName: string;
|
|
||||||
sha: string;
|
|
||||||
ref: string;
|
|
||||||
workflow: string;
|
|
||||||
action: string;
|
|
||||||
actor: string;
|
|
||||||
/**
|
|
||||||
* Hydrate the context from the environment
|
|
||||||
*/
|
|
||||||
constructor();
|
|
||||||
get issue(): {
|
|
||||||
owner: string;
|
|
||||||
repo: string;
|
|
||||||
number: number;
|
|
||||||
};
|
|
||||||
get repo(): {
|
|
||||||
owner: string;
|
|
||||||
repo: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
-46
@@ -1,46 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const fs_1 = require("fs");
|
|
||||||
const os_1 = require("os");
|
|
||||||
class Context {
|
|
||||||
/**
|
|
||||||
* Hydrate the context from the environment
|
|
||||||
*/
|
|
||||||
constructor() {
|
|
||||||
this.payload = {};
|
|
||||||
if (process.env.GITHUB_EVENT_PATH) {
|
|
||||||
if (fs_1.existsSync(process.env.GITHUB_EVENT_PATH)) {
|
|
||||||
this.payload = JSON.parse(fs_1.readFileSync(process.env.GITHUB_EVENT_PATH, { encoding: 'utf8' }));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const path = process.env.GITHUB_EVENT_PATH;
|
|
||||||
process.stdout.write(`GITHUB_EVENT_PATH ${path} does not exist${os_1.EOL}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.eventName = process.env.GITHUB_EVENT_NAME;
|
|
||||||
this.sha = process.env.GITHUB_SHA;
|
|
||||||
this.ref = process.env.GITHUB_REF;
|
|
||||||
this.workflow = process.env.GITHUB_WORKFLOW;
|
|
||||||
this.action = process.env.GITHUB_ACTION;
|
|
||||||
this.actor = process.env.GITHUB_ACTOR;
|
|
||||||
}
|
|
||||||
get issue() {
|
|
||||||
const payload = this.payload;
|
|
||||||
return Object.assign(Object.assign({}, this.repo), { number: (payload.issue || payload.pull_request || payload).number });
|
|
||||||
}
|
|
||||||
get repo() {
|
|
||||||
if (process.env.GITHUB_REPOSITORY) {
|
|
||||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
|
|
||||||
return { owner, repo };
|
|
||||||
}
|
|
||||||
if (this.payload.repository) {
|
|
||||||
return {
|
|
||||||
owner: this.payload.repository.owner.login,
|
|
||||||
repo: this.payload.repository.name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
throw new Error("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.Context = Context;
|
|
||||||
//# sourceMappingURL=context.js.map
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;AAEA,2BAA2C;AAC3C,2BAAsB;AAEtB,MAAa,OAAO;IAalB;;OAEG;IACH;QACE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACjB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE;YACjC,IAAI,eAAU,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE;gBAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CACvB,iBAAY,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAC,QAAQ,EAAE,MAAM,EAAC,CAAC,CAChE,CAAA;aACF;iBAAM;gBACL,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;gBAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,IAAI,kBAAkB,QAAG,EAAE,CAAC,CAAA;aACvE;SACF;QACD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAA2B,CAAA;QACxD,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAAoB,CAAA;QAC3C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAAoB,CAAA;QAC3C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAyB,CAAA;QACrD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAuB,CAAA;QACjD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAsB,CAAA;IACjD,CAAC;IAED,IAAI,KAAK;QACP,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAE5B,uCACK,IAAI,CAAC,IAAI,KACZ,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,MAAM,IAClE;IACH,CAAC;IAED,IAAI,IAAI;QACN,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE;YACjC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC9D,OAAO,EAAC,KAAK,EAAE,IAAI,EAAC,CAAA;SACrB;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;YAC3B,OAAO;gBACL,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK;gBAC1C,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI;aACnC,CAAA;SACF;QAED,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAA;IACH,CAAC;CACF;AA9DD,0BA8DC"}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
import { graphql as GraphQL } from '@octokit/graphql/dist-types/types';
|
|
||||||
import { Octokit } from '@octokit/rest';
|
|
||||||
import * as Context from './context';
|
|
||||||
export declare const context: Context.Context;
|
|
||||||
export declare class GitHub extends Octokit {
|
|
||||||
graphql: GraphQL;
|
|
||||||
/**
|
|
||||||
* Sets up the REST client and GraphQL client with auth and proxy support.
|
|
||||||
* The parameter `token` or `opts.auth` must be supplied. The GraphQL client
|
|
||||||
* authorization is not setup when `opts.auth` is a function or object.
|
|
||||||
*
|
|
||||||
* @param token Auth token
|
|
||||||
* @param opts Octokit options
|
|
||||||
*/
|
|
||||||
constructor(token: string, opts?: Omit<Octokit.Options, 'auth'>);
|
|
||||||
constructor(opts: Octokit.Options);
|
|
||||||
/**
|
|
||||||
* Disambiguates the constructor overload parameters
|
|
||||||
*/
|
|
||||||
private static disambiguate;
|
|
||||||
private static getOctokitOptions;
|
|
||||||
private static getGraphQL;
|
|
||||||
private static getAuthString;
|
|
||||||
private static getProxyAgent;
|
|
||||||
private static getApiBaseUrl;
|
|
||||||
private static getGraphQLBaseUrl;
|
|
||||||
}
|
|
||||||
-108
@@ -1,108 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
// Originally pulled from https://github.com/JasonEtco/actions-toolkit/blob/master/src/github.ts
|
|
||||||
const graphql_1 = require("@octokit/graphql");
|
|
||||||
const rest_1 = require("@octokit/rest");
|
|
||||||
const Context = __importStar(require("./context"));
|
|
||||||
const httpClient = __importStar(require("@actions/http-client"));
|
|
||||||
// We need this in order to extend Octokit
|
|
||||||
rest_1.Octokit.prototype = new rest_1.Octokit();
|
|
||||||
exports.context = new Context.Context();
|
|
||||||
class GitHub extends rest_1.Octokit {
|
|
||||||
constructor(token, opts) {
|
|
||||||
super(GitHub.getOctokitOptions(GitHub.disambiguate(token, opts)));
|
|
||||||
this.graphql = GitHub.getGraphQL(GitHub.disambiguate(token, opts));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Disambiguates the constructor overload parameters
|
|
||||||
*/
|
|
||||||
static disambiguate(token, opts) {
|
|
||||||
return [
|
|
||||||
typeof token === 'string' ? token : '',
|
|
||||||
typeof token === 'object' ? token : opts || {}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
static getOctokitOptions(args) {
|
|
||||||
const token = args[0];
|
|
||||||
const options = Object.assign({}, args[1]); // Shallow clone - don't mutate the object provided by the caller
|
|
||||||
// Base URL - GHES or Dotcom
|
|
||||||
options.baseUrl = options.baseUrl || this.getApiBaseUrl();
|
|
||||||
// Auth
|
|
||||||
const auth = GitHub.getAuthString(token, options);
|
|
||||||
if (auth) {
|
|
||||||
options.auth = auth;
|
|
||||||
}
|
|
||||||
// Proxy
|
|
||||||
const agent = GitHub.getProxyAgent(options.baseUrl, options);
|
|
||||||
if (agent) {
|
|
||||||
// Shallow clone - don't mutate the object provided by the caller
|
|
||||||
options.request = options.request ? Object.assign({}, options.request) : {};
|
|
||||||
// Set the agent
|
|
||||||
options.request.agent = agent;
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
static getGraphQL(args) {
|
|
||||||
const defaults = {};
|
|
||||||
defaults.baseUrl = this.getGraphQLBaseUrl();
|
|
||||||
const token = args[0];
|
|
||||||
const options = args[1];
|
|
||||||
// Authorization
|
|
||||||
const auth = this.getAuthString(token, options);
|
|
||||||
if (auth) {
|
|
||||||
defaults.headers = {
|
|
||||||
authorization: auth
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Proxy
|
|
||||||
const agent = GitHub.getProxyAgent(defaults.baseUrl, options);
|
|
||||||
if (agent) {
|
|
||||||
defaults.request = { agent };
|
|
||||||
}
|
|
||||||
return graphql_1.graphql.defaults(defaults);
|
|
||||||
}
|
|
||||||
static getAuthString(token, options) {
|
|
||||||
// Validate args
|
|
||||||
if (!token && !options.auth) {
|
|
||||||
throw new Error('Parameter token or opts.auth is required');
|
|
||||||
}
|
|
||||||
else if (token && options.auth) {
|
|
||||||
throw new Error('Parameters token and opts.auth may not both be specified');
|
|
||||||
}
|
|
||||||
return typeof options.auth === 'string' ? options.auth : `token ${token}`;
|
|
||||||
}
|
|
||||||
static getProxyAgent(destinationUrl, options) {
|
|
||||||
var _a;
|
|
||||||
if (!((_a = options.request) === null || _a === void 0 ? void 0 : _a.agent)) {
|
|
||||||
if (httpClient.getProxyUrl(destinationUrl)) {
|
|
||||||
const hc = new httpClient.HttpClient();
|
|
||||||
return hc.getAgent(destinationUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
static getApiBaseUrl() {
|
|
||||||
return process.env['GITHUB_API_URL'] || 'https://api.github.com';
|
|
||||||
}
|
|
||||||
static getGraphQLBaseUrl() {
|
|
||||||
let url = process.env['GITHUB_GRAPHQL_URL'] || 'https://api.github.com/graphql';
|
|
||||||
// Shouldn't be a trailing slash, but remove if so
|
|
||||||
if (url.endsWith('/')) {
|
|
||||||
url = url.substr(0, url.length - 1);
|
|
||||||
}
|
|
||||||
// Remove trailing "/graphql"
|
|
||||||
if (url.toUpperCase().endsWith('/GRAPHQL')) {
|
|
||||||
url = url.substr(0, url.length - '/graphql'.length);
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.GitHub = GitHub;
|
|
||||||
//# sourceMappingURL=github.js.map
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":";;;;;;;;;AAAA,gGAAgG;AAChG,8CAAwC;AAUxC,wCAAqC;AACrC,mDAAoC;AAEpC,iEAAkD;AAElD,0CAA0C;AAC1C,cAAO,CAAC,SAAS,GAAG,IAAI,cAAO,EAAE,CAAA;AAEpB,QAAA,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,CAAA;AAE5C,MAAa,MAAO,SAAQ,cAAO;IAiBjC,YAAY,KAA+B,EAAE,IAAsB;QACjE,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QAEjE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IACpE,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,YAAY,CACzB,KAA+B,EAC/B,IAAsB;QAEtB,OAAO;YACL,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YACtC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE;SAC/C,CAAA;IACH,CAAC;IAEO,MAAM,CAAC,iBAAiB,CAC9B,IAA+B;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,OAAO,qBAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA,CAAC,iEAAiE;QAE9F,4BAA4B;QAC5B,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAA;QAEzD,OAAO;QACP,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACjD,IAAI,IAAI,EAAE;YACR,OAAO,CAAC,IAAI,GAAG,IAAI,CAAA;SACpB;QAED,QAAQ;QACR,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC5D,IAAI,KAAK,EAAE;YACT,iEAAiE;YACjE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,mBAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAA;YAE7D,gBAAgB;YAChB,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;SAC9B;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;IAEO,MAAM,CAAC,UAAU,CAAC,IAA+B;QACvD,MAAM,QAAQ,GAA6B,EAAE,CAAA;QAC7C,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QAEvB,gBAAgB;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAC/C,IAAI,IAAI,EAAE;YACR,QAAQ,CAAC,OAAO,GAAG;gBACjB,aAAa,EAAE,IAAI;aACpB,CAAA;SACF;QAED,QAAQ;QACR,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC7D,IAAI,KAAK,EAAE;YACT,QAAQ,CAAC,OAAO,GAAG,EAAC,KAAK,EAAC,CAAA;SAC3B;QAED,OAAO,iBAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACnC,CAAC;IAEO,MAAM,CAAC,aAAa,CAC1B,KAAa,EACb,OAAwB;QAExB,gBAAgB;QAChB,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;SAC5D;aAAM,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE;YAChC,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAA;SACF;QAED,OAAO,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAA;IAC3E,CAAC;IAEO,MAAM,CAAC,aAAa,CAC1B,cAAsB,EACtB,OAAwB;;QAExB,IAAI,QAAC,OAAO,CAAC,OAAO,0CAAE,KAAK,CAAA,EAAE;YAC3B,IAAI,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE;gBAC1C,MAAM,EAAE,GAAG,IAAI,UAAU,CAAC,UAAU,EAAE,CAAA;gBACtC,OAAO,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;aACnC;SACF;QAED,OAAO,SAAS,CAAA;IAClB,CAAC;IAEO,MAAM,CAAC,aAAa;QAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,wBAAwB,CAAA;IAClE,CAAC;IAEO,MAAM,CAAC,iBAAiB;QAC9B,IAAI,GAAG,GACL,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,gCAAgC,CAAA;QAEvE,kDAAkD;QAClD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACrB,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;SACpC;QAED,6BAA6B;QAC7B,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;YAC1C,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;SACpD;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAxID,wBAwIC"}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
export interface PayloadRepository {
|
|
||||||
[key: string]: any;
|
|
||||||
full_name?: string;
|
|
||||||
name: string;
|
|
||||||
owner: {
|
|
||||||
[key: string]: any;
|
|
||||||
login: string;
|
|
||||||
name?: string;
|
|
||||||
};
|
|
||||||
html_url?: string;
|
|
||||||
}
|
|
||||||
export interface WebhookPayload {
|
|
||||||
[key: string]: any;
|
|
||||||
repository?: PayloadRepository;
|
|
||||||
issue?: {
|
|
||||||
[key: string]: any;
|
|
||||||
number: number;
|
|
||||||
html_url?: string;
|
|
||||||
body?: string;
|
|
||||||
};
|
|
||||||
pull_request?: {
|
|
||||||
[key: string]: any;
|
|
||||||
number: number;
|
|
||||||
html_url?: string;
|
|
||||||
body?: string;
|
|
||||||
};
|
|
||||||
sender?: {
|
|
||||||
[key: string]: any;
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
action?: string;
|
|
||||||
installation?: {
|
|
||||||
id: number;
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
//# sourceMappingURL=interfaces.js.map
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA,uDAAuD"}
|
|
||||||
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export const VERSION = "1.1.2";
|
|
||||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export declare const VERSION = "1.1.2";
|
|
||||||
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-2717
File diff suppressed because it is too large
Load Diff
Generated
Vendored
-13196
File diff suppressed because it is too large
Load Diff
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-6624
File diff suppressed because it is too large
Load Diff
Generated
Vendored
-38
@@ -1,38 +0,0 @@
|
|||||||
import { Deprecation } from "deprecation";
|
|
||||||
import endpointsByScope from "./generated/endpoints";
|
|
||||||
import { VERSION } from "./version";
|
|
||||||
import { registerEndpoints } from "./register-endpoints";
|
|
||||||
/**
|
|
||||||
* This plugin is a 1:1 copy of internal @octokit/rest plugins. The primary
|
|
||||||
* goal is to rebuild @octokit/rest on top of @octokit/core. Once that is
|
|
||||||
* done, we will remove the registerEndpoints methods and return the methods
|
|
||||||
* directly as with the other plugins. At that point we will also remove the
|
|
||||||
* legacy workarounds and deprecations.
|
|
||||||
*
|
|
||||||
* See the plan at
|
|
||||||
* https://github.com/octokit/plugin-rest-endpoint-methods.js/pull/1
|
|
||||||
*/
|
|
||||||
export function restEndpointMethods(octokit) {
|
|
||||||
// @ts-ignore
|
|
||||||
octokit.registerEndpoints = registerEndpoints.bind(null, octokit);
|
|
||||||
registerEndpoints(octokit, endpointsByScope);
|
|
||||||
// Aliasing scopes for backward compatibility
|
|
||||||
// See https://github.com/octokit/rest.js/pull/1134
|
|
||||||
[
|
|
||||||
["gitdata", "git"],
|
|
||||||
["authorization", "oauthAuthorizations"],
|
|
||||||
["pullRequests", "pulls"]
|
|
||||||
].forEach(([deprecatedScope, scope]) => {
|
|
||||||
Object.defineProperty(octokit, deprecatedScope, {
|
|
||||||
get() {
|
|
||||||
octokit.log.warn(
|
|
||||||
// @ts-ignore
|
|
||||||
new Deprecation(`[@octokit/plugin-rest-endpoint-methods] "octokit.${deprecatedScope}.*" methods are deprecated, use "octokit.${scope}.*" instead`));
|
|
||||||
// @ts-ignore
|
|
||||||
return octokit[scope];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
restEndpointMethods.VERSION = VERSION;
|
|
||||||
Generated
Vendored
-60
@@ -1,60 +0,0 @@
|
|||||||
import { Deprecation } from "deprecation";
|
|
||||||
export function registerEndpoints(octokit, routes) {
|
|
||||||
Object.keys(routes).forEach(namespaceName => {
|
|
||||||
if (!octokit[namespaceName]) {
|
|
||||||
octokit[namespaceName] = {};
|
|
||||||
}
|
|
||||||
Object.keys(routes[namespaceName]).forEach(apiName => {
|
|
||||||
const apiOptions = routes[namespaceName][apiName];
|
|
||||||
const endpointDefaults = ["method", "url", "headers"].reduce((map, key) => {
|
|
||||||
if (typeof apiOptions[key] !== "undefined") {
|
|
||||||
map[key] = apiOptions[key];
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}, {});
|
|
||||||
endpointDefaults.request = {
|
|
||||||
validate: apiOptions.params
|
|
||||||
};
|
|
||||||
let request = octokit.request.defaults(endpointDefaults);
|
|
||||||
// patch request & endpoint methods to support deprecated parameters.
|
|
||||||
// Not the most elegant solution, but we don’t want to move deprecation
|
|
||||||
// logic into octokit/endpoint.js as it’s out of scope
|
|
||||||
const hasDeprecatedParam = Object.keys(apiOptions.params || {}).find(key => apiOptions.params[key].deprecated);
|
|
||||||
if (hasDeprecatedParam) {
|
|
||||||
const patch = patchForDeprecation.bind(null, octokit, apiOptions);
|
|
||||||
request = patch(octokit.request.defaults(endpointDefaults), `.${namespaceName}.${apiName}()`);
|
|
||||||
request.endpoint = patch(request.endpoint, `.${namespaceName}.${apiName}.endpoint()`);
|
|
||||||
request.endpoint.merge = patch(request.endpoint.merge, `.${namespaceName}.${apiName}.endpoint.merge()`);
|
|
||||||
}
|
|
||||||
if (apiOptions.deprecated) {
|
|
||||||
octokit[namespaceName][apiName] = Object.assign(function deprecatedEndpointMethod() {
|
|
||||||
octokit.log.warn(new Deprecation(`[@octokit/rest] ${apiOptions.deprecated}`));
|
|
||||||
octokit[namespaceName][apiName] = request;
|
|
||||||
return request.apply(null, arguments);
|
|
||||||
}, request);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
octokit[namespaceName][apiName] = request;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function patchForDeprecation(octokit, apiOptions, method, methodName) {
|
|
||||||
const patchedMethod = (options) => {
|
|
||||||
options = Object.assign({}, options);
|
|
||||||
Object.keys(options).forEach(key => {
|
|
||||||
if (apiOptions.params[key] && apiOptions.params[key].deprecated) {
|
|
||||||
const aliasKey = apiOptions.params[key].alias;
|
|
||||||
octokit.log.warn(new Deprecation(`[@octokit/rest] "${key}" parameter is deprecated for "${methodName}". Use "${aliasKey}" instead`));
|
|
||||||
if (!(aliasKey in options)) {
|
|
||||||
options[aliasKey] = options[key];
|
|
||||||
}
|
|
||||||
delete options[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return method(options);
|
|
||||||
};
|
|
||||||
Object.keys(method).forEach(key => {
|
|
||||||
patchedMethod[key] = method[key];
|
|
||||||
});
|
|
||||||
return patchedMethod;
|
|
||||||
}
|
|
||||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export const VERSION = "2.4.0";
|
|
||||||
Generated
Vendored
-13085
File diff suppressed because it is too large
Load Diff
Generated
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export declare function registerEndpoints(octokit: any, routes: any): void;
|
|
||||||
Generated
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
import { RestEndpointMethods } from "./generated/rest-endpoint-methods-types";
|
|
||||||
export declare type Api = {
|
|
||||||
registerEndpoints: (endpoints: any) => void;
|
|
||||||
} & RestEndpointMethods;
|
|
||||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export declare const VERSION = "2.4.0";
|
|
||||||
Generated
Vendored
-6726
File diff suppressed because it is too large
Load Diff
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
-42072
File diff suppressed because it is too large
Load Diff
-43
@@ -1,43 +0,0 @@
|
|||||||
const { requestLog } = require("@octokit/plugin-request-log");
|
|
||||||
const {
|
|
||||||
restEndpointMethods
|
|
||||||
} = require("@octokit/plugin-rest-endpoint-methods");
|
|
||||||
|
|
||||||
const Core = require("./lib/core");
|
|
||||||
|
|
||||||
const CORE_PLUGINS = [
|
|
||||||
require("./plugins/authentication"),
|
|
||||||
require("./plugins/authentication-deprecated"), // deprecated: remove in v17
|
|
||||||
requestLog,
|
|
||||||
require("./plugins/pagination"),
|
|
||||||
restEndpointMethods,
|
|
||||||
require("./plugins/validate"),
|
|
||||||
|
|
||||||
require("octokit-pagination-methods") // deprecated: remove in v17
|
|
||||||
];
|
|
||||||
|
|
||||||
const OctokitRest = Core.plugin(CORE_PLUGINS);
|
|
||||||
|
|
||||||
function DeprecatedOctokit(options) {
|
|
||||||
const warn =
|
|
||||||
options && options.log && options.log.warn
|
|
||||||
? options.log.warn
|
|
||||||
: console.warn;
|
|
||||||
warn(
|
|
||||||
'[@octokit/rest] `const Octokit = require("@octokit/rest")` is deprecated. Use `const { Octokit } = require("@octokit/rest")` instead'
|
|
||||||
);
|
|
||||||
return new OctokitRest(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Octokit = Object.assign(DeprecatedOctokit, {
|
|
||||||
Octokit: OctokitRest
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(OctokitRest).forEach(key => {
|
|
||||||
/* istanbul ignore else */
|
|
||||||
if (OctokitRest.hasOwnProperty(key)) {
|
|
||||||
Octokit[key] = OctokitRest[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = Octokit;
|
|
||||||
-29
@@ -1,29 +0,0 @@
|
|||||||
module.exports = Octokit;
|
|
||||||
|
|
||||||
const { request } = require("@octokit/request");
|
|
||||||
const Hook = require("before-after-hook");
|
|
||||||
|
|
||||||
const parseClientOptions = require("./parse-client-options");
|
|
||||||
|
|
||||||
function Octokit(plugins, options) {
|
|
||||||
options = options || {};
|
|
||||||
const hook = new Hook.Collection();
|
|
||||||
const log = Object.assign(
|
|
||||||
{
|
|
||||||
debug: () => {},
|
|
||||||
info: () => {},
|
|
||||||
warn: console.warn,
|
|
||||||
error: console.error
|
|
||||||
},
|
|
||||||
options && options.log
|
|
||||||
);
|
|
||||||
const api = {
|
|
||||||
hook,
|
|
||||||
log,
|
|
||||||
request: request.defaults(parseClientOptions(options, log, hook))
|
|
||||||
};
|
|
||||||
|
|
||||||
plugins.forEach(pluginFunction => pluginFunction(api, options));
|
|
||||||
|
|
||||||
return api;
|
|
||||||
}
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
const factory = require("./factory");
|
|
||||||
|
|
||||||
module.exports = factory();
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
module.exports = factory;
|
|
||||||
|
|
||||||
const Octokit = require("./constructor");
|
|
||||||
const registerPlugin = require("./register-plugin");
|
|
||||||
|
|
||||||
function factory(plugins) {
|
|
||||||
const Api = Octokit.bind(null, plugins || []);
|
|
||||||
Api.plugin = registerPlugin.bind(null, plugins || []);
|
|
||||||
return Api;
|
|
||||||
}
|
|
||||||
Generated
Vendored
-89
@@ -1,89 +0,0 @@
|
|||||||
module.exports = parseOptions;
|
|
||||||
|
|
||||||
const { Deprecation } = require("deprecation");
|
|
||||||
const { getUserAgent } = require("universal-user-agent");
|
|
||||||
const once = require("once");
|
|
||||||
|
|
||||||
const pkg = require("../package.json");
|
|
||||||
|
|
||||||
const deprecateOptionsTimeout = once((log, deprecation) =>
|
|
||||||
log.warn(deprecation)
|
|
||||||
);
|
|
||||||
const deprecateOptionsAgent = once((log, deprecation) => log.warn(deprecation));
|
|
||||||
const deprecateOptionsHeaders = once((log, deprecation) =>
|
|
||||||
log.warn(deprecation)
|
|
||||||
);
|
|
||||||
|
|
||||||
function parseOptions(options, log, hook) {
|
|
||||||
if (options.headers) {
|
|
||||||
options.headers = Object.keys(options.headers).reduce((newObj, key) => {
|
|
||||||
newObj[key.toLowerCase()] = options.headers[key];
|
|
||||||
return newObj;
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
const clientDefaults = {
|
|
||||||
headers: options.headers || {},
|
|
||||||
request: options.request || {},
|
|
||||||
mediaType: {
|
|
||||||
previews: [],
|
|
||||||
format: ""
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.baseUrl) {
|
|
||||||
clientDefaults.baseUrl = options.baseUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.userAgent) {
|
|
||||||
clientDefaults.headers["user-agent"] = options.userAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.previews) {
|
|
||||||
clientDefaults.mediaType.previews = options.previews;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.timeZone) {
|
|
||||||
clientDefaults.headers["time-zone"] = options.timeZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.timeout) {
|
|
||||||
deprecateOptionsTimeout(
|
|
||||||
log,
|
|
||||||
new Deprecation(
|
|
||||||
"[@octokit/rest] new Octokit({timeout}) is deprecated. Use {request: {timeout}} instead. See https://github.com/octokit/request.js#request"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
clientDefaults.request.timeout = options.timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.agent) {
|
|
||||||
deprecateOptionsAgent(
|
|
||||||
log,
|
|
||||||
new Deprecation(
|
|
||||||
"[@octokit/rest] new Octokit({agent}) is deprecated. Use {request: {agent}} instead. See https://github.com/octokit/request.js#request"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
clientDefaults.request.agent = options.agent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.headers) {
|
|
||||||
deprecateOptionsHeaders(
|
|
||||||
log,
|
|
||||||
new Deprecation(
|
|
||||||
"[@octokit/rest] new Octokit({headers}) is deprecated. Use {userAgent, previews} instead. See https://github.com/octokit/request.js#request"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const userAgentOption = clientDefaults.headers["user-agent"];
|
|
||||||
const defaultUserAgent = `octokit.js/${pkg.version} ${getUserAgent()}`;
|
|
||||||
|
|
||||||
clientDefaults.headers["user-agent"] = [userAgentOption, defaultUserAgent]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(" ");
|
|
||||||
|
|
||||||
clientDefaults.request.hook = hook.bind(null, "request");
|
|
||||||
|
|
||||||
return clientDefaults;
|
|
||||||
}
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
module.exports = registerPlugin;
|
|
||||||
|
|
||||||
const factory = require("./factory");
|
|
||||||
|
|
||||||
function registerPlugin(plugins, pluginFunction) {
|
|
||||||
return factory(
|
|
||||||
plugins.includes(pluginFunction) ? plugins : plugins.concat(pluginFunction)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
-140
@@ -1,140 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@octokit/rest",
|
|
||||||
"version": "16.43.2",
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"description": "GitHub REST API client for Node.js",
|
|
||||||
"keywords": [
|
|
||||||
"octokit",
|
|
||||||
"github",
|
|
||||||
"rest",
|
|
||||||
"api-client"
|
|
||||||
],
|
|
||||||
"author": "Gregor Martynus (https://github.com/gr2m)",
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Mike de Boer",
|
|
||||||
"email": "info@mikedeboer.nl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Fabian Jakobs",
|
|
||||||
"email": "fabian@c9.io"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Joe Gallo",
|
|
||||||
"email": "joe@brassafrax.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Gregor Martynus",
|
|
||||||
"url": "https://github.com/gr2m"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": "https://github.com/octokit/rest.js",
|
|
||||||
"dependencies": {
|
|
||||||
"@octokit/auth-token": "^2.4.0",
|
|
||||||
"@octokit/plugin-paginate-rest": "^1.1.1",
|
|
||||||
"@octokit/plugin-request-log": "^1.0.0",
|
|
||||||
"@octokit/plugin-rest-endpoint-methods": "2.4.0",
|
|
||||||
"@octokit/request": "^5.2.0",
|
|
||||||
"@octokit/request-error": "^1.0.2",
|
|
||||||
"atob-lite": "^2.0.0",
|
|
||||||
"before-after-hook": "^2.0.0",
|
|
||||||
"btoa-lite": "^1.0.0",
|
|
||||||
"deprecation": "^2.0.0",
|
|
||||||
"lodash.get": "^4.4.2",
|
|
||||||
"lodash.set": "^4.3.2",
|
|
||||||
"lodash.uniq": "^4.5.0",
|
|
||||||
"octokit-pagination-methods": "^1.1.0",
|
|
||||||
"once": "^1.4.0",
|
|
||||||
"universal-user-agent": "^4.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@gimenete/type-writer": "^0.1.3",
|
|
||||||
"@octokit/auth": "^1.1.1",
|
|
||||||
"@octokit/fixtures-server": "^5.0.6",
|
|
||||||
"@octokit/graphql": "^4.2.0",
|
|
||||||
"@types/node": "^13.1.0",
|
|
||||||
"bundlesize": "^0.18.0",
|
|
||||||
"chai": "^4.1.2",
|
|
||||||
"compression-webpack-plugin": "^3.1.0",
|
|
||||||
"cypress": "^4.0.0",
|
|
||||||
"glob": "^7.1.2",
|
|
||||||
"http-proxy-agent": "^4.0.0",
|
|
||||||
"lodash.camelcase": "^4.3.0",
|
|
||||||
"lodash.merge": "^4.6.1",
|
|
||||||
"lodash.upperfirst": "^4.3.1",
|
|
||||||
"lolex": "^6.0.0",
|
|
||||||
"mkdirp": "^1.0.0",
|
|
||||||
"mocha": "^7.0.1",
|
|
||||||
"mustache": "^4.0.0",
|
|
||||||
"nock": "^11.3.3",
|
|
||||||
"npm-run-all": "^4.1.2",
|
|
||||||
"nyc": "^15.0.0",
|
|
||||||
"prettier": "^1.14.2",
|
|
||||||
"proxy": "^1.0.0",
|
|
||||||
"semantic-release": "^17.0.0",
|
|
||||||
"sinon": "^8.0.0",
|
|
||||||
"sinon-chai": "^3.0.0",
|
|
||||||
"sort-keys": "^4.0.0",
|
|
||||||
"string-to-arraybuffer": "^1.0.0",
|
|
||||||
"string-to-jsdoc-comment": "^1.0.0",
|
|
||||||
"typescript": "^3.3.1",
|
|
||||||
"webpack": "^4.0.0",
|
|
||||||
"webpack-bundle-analyzer": "^3.0.0",
|
|
||||||
"webpack-cli": "^3.0.0"
|
|
||||||
},
|
|
||||||
"types": "index.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"coverage": "nyc report --reporter=html && open coverage/index.html",
|
|
||||||
"lint": "prettier --check '{lib,plugins,scripts,test}/**/*.{js,json,ts}' 'docs/*.{js,json}' 'docs/src/**/*' index.js README.md package.json",
|
|
||||||
"lint:fix": "prettier --write '{lib,plugins,scripts,test}/**/*.{js,json,ts}' 'docs/*.{js,json}' 'docs/src/**/*' index.js README.md package.json",
|
|
||||||
"pretest": "npm run -s lint",
|
|
||||||
"test": "nyc mocha test/mocha-node-setup.js \"test/*/**/*-test.js\"",
|
|
||||||
"test:browser": "cypress run --browser chrome",
|
|
||||||
"build": "npm-run-all build:*",
|
|
||||||
"build:ts": "npm run -s update-endpoints:typescript",
|
|
||||||
"prebuild:browser": "mkdirp dist/",
|
|
||||||
"build:browser": "npm-run-all build:browser:*",
|
|
||||||
"build:browser:development": "webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json",
|
|
||||||
"build:browser:production": "webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map",
|
|
||||||
"generate-bundle-report": "webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html",
|
|
||||||
"update-endpoints": "npm-run-all update-endpoints:*",
|
|
||||||
"update-endpoints:fetch-json": "node scripts/update-endpoints/fetch-json",
|
|
||||||
"update-endpoints:typescript": "node scripts/update-endpoints/typescript",
|
|
||||||
"prevalidate:ts": "npm run -s build:ts",
|
|
||||||
"validate:ts": "tsc --target es6 --noImplicitAny index.d.ts",
|
|
||||||
"postvalidate:ts": "tsc --noEmit --target es6 test/typescript-validate.ts",
|
|
||||||
"start-fixtures-server": "octokit-fixtures-server"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"files": [
|
|
||||||
"index.js",
|
|
||||||
"index.d.ts",
|
|
||||||
"lib",
|
|
||||||
"plugins"
|
|
||||||
],
|
|
||||||
"nyc": {
|
|
||||||
"ignore": [
|
|
||||||
"test"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"release": {
|
|
||||||
"publish": [
|
|
||||||
"@semantic-release/npm",
|
|
||||||
{
|
|
||||||
"path": "@semantic-release/github",
|
|
||||||
"assets": [
|
|
||||||
"dist/*",
|
|
||||||
"!dist/*.map.gz"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"bundlesize": [
|
|
||||||
{
|
|
||||||
"path": "./dist/octokit-rest.min.js.gz",
|
|
||||||
"maxSize": "33 kB"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Generated
Vendored
-52
@@ -1,52 +0,0 @@
|
|||||||
module.exports = authenticate;
|
|
||||||
|
|
||||||
const { Deprecation } = require("deprecation");
|
|
||||||
const once = require("once");
|
|
||||||
|
|
||||||
const deprecateAuthenticate = once((log, deprecation) => log.warn(deprecation));
|
|
||||||
|
|
||||||
function authenticate(state, options) {
|
|
||||||
deprecateAuthenticate(
|
|
||||||
state.octokit.log,
|
|
||||||
new Deprecation(
|
|
||||||
'[@octokit/rest] octokit.authenticate() is deprecated. Use "auth" constructor option instead.'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
state.auth = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (options.type) {
|
|
||||||
case "basic":
|
|
||||||
if (!options.username || !options.password) {
|
|
||||||
throw new Error(
|
|
||||||
"Basic authentication requires both a username and password to be set"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "oauth":
|
|
||||||
if (!options.token && !(options.key && options.secret)) {
|
|
||||||
throw new Error(
|
|
||||||
"OAuth2 authentication requires a token or key & secret to be set"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "token":
|
|
||||||
case "app":
|
|
||||||
if (!options.token) {
|
|
||||||
throw new Error("Token authentication requires a token to be set");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error(
|
|
||||||
"Invalid authentication type, must be 'basic', 'oauth', 'token' or 'app'"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.auth = options;
|
|
||||||
}
|
|
||||||
Generated
Vendored
-43
@@ -1,43 +0,0 @@
|
|||||||
module.exports = authenticationBeforeRequest;
|
|
||||||
|
|
||||||
const btoa = require("btoa-lite");
|
|
||||||
const uniq = require("lodash.uniq");
|
|
||||||
|
|
||||||
function authenticationBeforeRequest(state, options) {
|
|
||||||
if (!state.auth.type) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.auth.type === "basic") {
|
|
||||||
const hash = btoa(`${state.auth.username}:${state.auth.password}`);
|
|
||||||
options.headers.authorization = `Basic ${hash}`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.auth.type === "token") {
|
|
||||||
options.headers.authorization = `token ${state.auth.token}`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.auth.type === "app") {
|
|
||||||
options.headers.authorization = `Bearer ${state.auth.token}`;
|
|
||||||
const acceptHeaders = options.headers.accept
|
|
||||||
.split(",")
|
|
||||||
.concat("application/vnd.github.machine-man-preview+json");
|
|
||||||
options.headers.accept = uniq(acceptHeaders)
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(",");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.url += options.url.indexOf("?") === -1 ? "?" : "&";
|
|
||||||
|
|
||||||
if (state.auth.token) {
|
|
||||||
options.url += `access_token=${encodeURIComponent(state.auth.token)}`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = encodeURIComponent(state.auth.key);
|
|
||||||
const secret = encodeURIComponent(state.auth.secret);
|
|
||||||
options.url += `client_id=${key}&client_secret=${secret}`;
|
|
||||||
}
|
|
||||||
Generated
Vendored
-31
@@ -1,31 +0,0 @@
|
|||||||
module.exports = authenticationPlugin;
|
|
||||||
|
|
||||||
const { Deprecation } = require("deprecation");
|
|
||||||
const once = require("once");
|
|
||||||
|
|
||||||
const deprecateAuthenticate = once((log, deprecation) => log.warn(deprecation));
|
|
||||||
|
|
||||||
const authenticate = require("./authenticate");
|
|
||||||
const beforeRequest = require("./before-request");
|
|
||||||
const requestError = require("./request-error");
|
|
||||||
|
|
||||||
function authenticationPlugin(octokit, options) {
|
|
||||||
if (options.auth) {
|
|
||||||
octokit.authenticate = () => {
|
|
||||||
deprecateAuthenticate(
|
|
||||||
octokit.log,
|
|
||||||
new Deprecation(
|
|
||||||
'[@octokit/rest] octokit.authenticate() is deprecated and has no effect when "auth" option is set on Octokit constructor'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const state = {
|
|
||||||
octokit,
|
|
||||||
auth: false
|
|
||||||
};
|
|
||||||
octokit.authenticate = authenticate.bind(null, state);
|
|
||||||
octokit.hook.before("request", beforeRequest.bind(null, state));
|
|
||||||
octokit.hook.error("request", requestError.bind(null, state));
|
|
||||||
}
|
|
||||||
Generated
Vendored
-55
@@ -1,55 +0,0 @@
|
|||||||
module.exports = authenticationRequestError;
|
|
||||||
|
|
||||||
const { RequestError } = require("@octokit/request-error");
|
|
||||||
|
|
||||||
function authenticationRequestError(state, error, options) {
|
|
||||||
/* istanbul ignore next */
|
|
||||||
if (!error.headers) throw error;
|
|
||||||
|
|
||||||
const otpRequired = /required/.test(error.headers["x-github-otp"] || "");
|
|
||||||
// handle "2FA required" error only
|
|
||||||
if (error.status !== 401 || !otpRequired) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
error.status === 401 &&
|
|
||||||
otpRequired &&
|
|
||||||
error.request &&
|
|
||||||
error.request.headers["x-github-otp"]
|
|
||||||
) {
|
|
||||||
throw new RequestError(
|
|
||||||
"Invalid one-time password for two-factor authentication",
|
|
||||||
401,
|
|
||||||
{
|
|
||||||
headers: error.headers,
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof state.auth.on2fa !== "function") {
|
|
||||||
throw new RequestError(
|
|
||||||
"2FA required, but options.on2fa is not a function. See https://github.com/octokit/rest.js#authentication",
|
|
||||||
401,
|
|
||||||
{
|
|
||||||
headers: error.headers,
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve()
|
|
||||||
.then(() => {
|
|
||||||
return state.auth.on2fa();
|
|
||||||
})
|
|
||||||
.then(oneTimePassword => {
|
|
||||||
const newOptions = Object.assign(options, {
|
|
||||||
headers: Object.assign(
|
|
||||||
{ "x-github-otp": oneTimePassword },
|
|
||||||
options.headers
|
|
||||||
)
|
|
||||||
});
|
|
||||||
return state.octokit.request(newOptions);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Generated
Vendored
-53
@@ -1,53 +0,0 @@
|
|||||||
module.exports = authenticationBeforeRequest;
|
|
||||||
|
|
||||||
const btoa = require("btoa-lite");
|
|
||||||
|
|
||||||
const withAuthorizationPrefix = require("./with-authorization-prefix");
|
|
||||||
|
|
||||||
function authenticationBeforeRequest(state, options) {
|
|
||||||
if (typeof state.auth === "string") {
|
|
||||||
options.headers.authorization = withAuthorizationPrefix(state.auth);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.auth.username) {
|
|
||||||
const hash = btoa(`${state.auth.username}:${state.auth.password}`);
|
|
||||||
options.headers.authorization = `Basic ${hash}`;
|
|
||||||
if (state.otp) {
|
|
||||||
options.headers["x-github-otp"] = state.otp;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.auth.clientId) {
|
|
||||||
// There is a special case for OAuth applications, when `clientId` and `clientSecret` is passed as
|
|
||||||
// Basic Authorization instead of query parameters. The only routes where that applies share the same
|
|
||||||
// URL though: `/applications/:client_id/tokens/:access_token`.
|
|
||||||
//
|
|
||||||
// 1. [Check an authorization](https://developer.github.com/v3/oauth_authorizations/#check-an-authorization)
|
|
||||||
// 2. [Reset an authorization](https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization)
|
|
||||||
// 3. [Revoke an authorization for an application](https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application)
|
|
||||||
//
|
|
||||||
// We identify by checking the URL. It must merge both "/applications/:client_id/tokens/:access_token"
|
|
||||||
// as well as "/applications/123/tokens/token456"
|
|
||||||
if (/\/applications\/:?[\w_]+\/tokens\/:?[\w_]+($|\?)/.test(options.url)) {
|
|
||||||
const hash = btoa(`${state.auth.clientId}:${state.auth.clientSecret}`);
|
|
||||||
options.headers.authorization = `Basic ${hash}`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.url += options.url.indexOf("?") === -1 ? "?" : "&";
|
|
||||||
options.url += `client_id=${state.auth.clientId}&client_secret=${state.auth.clientSecret}`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve()
|
|
||||||
|
|
||||||
.then(() => {
|
|
||||||
return state.auth();
|
|
||||||
})
|
|
||||||
|
|
||||||
.then(authorization => {
|
|
||||||
options.headers.authorization = withAuthorizationPrefix(authorization);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Generated
Vendored
-76
@@ -1,76 +0,0 @@
|
|||||||
module.exports = authenticationPlugin;
|
|
||||||
|
|
||||||
const { createTokenAuth } = require("@octokit/auth-token");
|
|
||||||
const { Deprecation } = require("deprecation");
|
|
||||||
const once = require("once");
|
|
||||||
|
|
||||||
const beforeRequest = require("./before-request");
|
|
||||||
const requestError = require("./request-error");
|
|
||||||
const validate = require("./validate");
|
|
||||||
const withAuthorizationPrefix = require("./with-authorization-prefix");
|
|
||||||
|
|
||||||
const deprecateAuthBasic = once((log, deprecation) => log.warn(deprecation));
|
|
||||||
const deprecateAuthObject = once((log, deprecation) => log.warn(deprecation));
|
|
||||||
|
|
||||||
function authenticationPlugin(octokit, options) {
|
|
||||||
// If `options.authStrategy` is set then use it and pass in `options.auth`
|
|
||||||
if (options.authStrategy) {
|
|
||||||
const auth = options.authStrategy(options.auth);
|
|
||||||
octokit.hook.wrap("request", auth.hook);
|
|
||||||
octokit.auth = auth;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If neither `options.authStrategy` nor `options.auth` are set, the `octokit` instance
|
|
||||||
// is unauthenticated. The `octokit.auth()` method is a no-op and no request hook is registred.
|
|
||||||
if (!options.auth) {
|
|
||||||
octokit.auth = () =>
|
|
||||||
Promise.resolve({
|
|
||||||
type: "unauthenticated"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBasicAuthString =
|
|
||||||
typeof options.auth === "string" &&
|
|
||||||
/^basic/.test(withAuthorizationPrefix(options.auth));
|
|
||||||
|
|
||||||
// If only `options.auth` is set to a string, use the default token authentication strategy.
|
|
||||||
if (typeof options.auth === "string" && !isBasicAuthString) {
|
|
||||||
const auth = createTokenAuth(options.auth);
|
|
||||||
octokit.hook.wrap("request", auth.hook);
|
|
||||||
octokit.auth = auth;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise log a deprecation message
|
|
||||||
const [deprecationMethod, deprecationMessapge] = isBasicAuthString
|
|
||||||
? [
|
|
||||||
deprecateAuthBasic,
|
|
||||||
'Setting the "new Octokit({ auth })" option to a Basic Auth string is deprecated. Use https://github.com/octokit/auth-basic.js instead. See (https://octokit.github.io/rest.js/#authentication)'
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
deprecateAuthObject,
|
|
||||||
'Setting the "new Octokit({ auth })" option to an object without also setting the "authStrategy" option is deprecated and will be removed in v17. See (https://octokit.github.io/rest.js/#authentication)'
|
|
||||||
];
|
|
||||||
deprecationMethod(
|
|
||||||
octokit.log,
|
|
||||||
new Deprecation("[@octokit/rest] " + deprecationMessapge)
|
|
||||||
);
|
|
||||||
|
|
||||||
octokit.auth = () =>
|
|
||||||
Promise.resolve({
|
|
||||||
type: "deprecated",
|
|
||||||
message: deprecationMessapge
|
|
||||||
});
|
|
||||||
|
|
||||||
validate(options.auth);
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
octokit,
|
|
||||||
auth: options.auth
|
|
||||||
};
|
|
||||||
|
|
||||||
octokit.hook.before("request", beforeRequest.bind(null, state));
|
|
||||||
octokit.hook.error("request", requestError.bind(null, state));
|
|
||||||
}
|
|
||||||
Generated
Vendored
-61
@@ -1,61 +0,0 @@
|
|||||||
module.exports = authenticationRequestError;
|
|
||||||
|
|
||||||
const { RequestError } = require("@octokit/request-error");
|
|
||||||
|
|
||||||
function authenticationRequestError(state, error, options) {
|
|
||||||
if (!error.headers) throw error;
|
|
||||||
|
|
||||||
const otpRequired = /required/.test(error.headers["x-github-otp"] || "");
|
|
||||||
// handle "2FA required" error only
|
|
||||||
if (error.status !== 401 || !otpRequired) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
error.status === 401 &&
|
|
||||||
otpRequired &&
|
|
||||||
error.request &&
|
|
||||||
error.request.headers["x-github-otp"]
|
|
||||||
) {
|
|
||||||
if (state.otp) {
|
|
||||||
delete state.otp; // no longer valid, request again
|
|
||||||
} else {
|
|
||||||
throw new RequestError(
|
|
||||||
"Invalid one-time password for two-factor authentication",
|
|
||||||
401,
|
|
||||||
{
|
|
||||||
headers: error.headers,
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof state.auth.on2fa !== "function") {
|
|
||||||
throw new RequestError(
|
|
||||||
"2FA required, but options.on2fa is not a function. See https://github.com/octokit/rest.js#authentication",
|
|
||||||
401,
|
|
||||||
{
|
|
||||||
headers: error.headers,
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve()
|
|
||||||
.then(() => {
|
|
||||||
return state.auth.on2fa();
|
|
||||||
})
|
|
||||||
.then(oneTimePassword => {
|
|
||||||
const newOptions = Object.assign(options, {
|
|
||||||
headers: Object.assign(options.headers, {
|
|
||||||
"x-github-otp": oneTimePassword
|
|
||||||
})
|
|
||||||
});
|
|
||||||
return state.octokit.request(newOptions).then(response => {
|
|
||||||
// If OTP still valid, then persist it for following requests
|
|
||||||
state.otp = oneTimePassword;
|
|
||||||
return response;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Generated
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
module.exports = validateAuth;
|
|
||||||
|
|
||||||
function validateAuth(auth) {
|
|
||||||
if (typeof auth === "string") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof auth === "function") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auth.username && auth.password) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auth.clientId && auth.clientSecret) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`Invalid "auth" option: ${JSON.stringify(auth)}`);
|
|
||||||
}
|
|
||||||
Generated
Vendored
-23
@@ -1,23 +0,0 @@
|
|||||||
module.exports = withAuthorizationPrefix;
|
|
||||||
|
|
||||||
const atob = require("atob-lite");
|
|
||||||
|
|
||||||
const REGEX_IS_BASIC_AUTH = /^[\w-]+:/;
|
|
||||||
|
|
||||||
function withAuthorizationPrefix(authorization) {
|
|
||||||
if (/^(basic|bearer|token) /i.test(authorization)) {
|
|
||||||
return authorization;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (REGEX_IS_BASIC_AUTH.test(atob(authorization))) {
|
|
||||||
return `basic ${authorization}`;
|
|
||||||
}
|
|
||||||
} catch (error) {}
|
|
||||||
|
|
||||||
if (authorization.split(/\./).length === 3) {
|
|
||||||
return `bearer ${authorization}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `token ${authorization}`;
|
|
||||||
}
|
|
||||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
module.exports = paginatePlugin;
|
|
||||||
|
|
||||||
const { paginateRest } = require("@octokit/plugin-paginate-rest");
|
|
||||||
|
|
||||||
function paginatePlugin(octokit) {
|
|
||||||
Object.assign(octokit, paginateRest(octokit));
|
|
||||||
}
|
|
||||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
module.exports = octokitValidate;
|
|
||||||
|
|
||||||
const validate = require("./validate");
|
|
||||||
|
|
||||||
function octokitValidate(octokit) {
|
|
||||||
octokit.hook.before("request", validate.bind(null, octokit));
|
|
||||||
}
|
|
||||||
Generated
Vendored
-151
@@ -1,151 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
module.exports = validate;
|
|
||||||
|
|
||||||
const { RequestError } = require("@octokit/request-error");
|
|
||||||
const get = require("lodash.get");
|
|
||||||
const set = require("lodash.set");
|
|
||||||
|
|
||||||
function validate(octokit, options) {
|
|
||||||
if (!options.request.validate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { validate: params } = options.request;
|
|
||||||
|
|
||||||
Object.keys(params).forEach(parameterName => {
|
|
||||||
const parameter = get(params, parameterName);
|
|
||||||
|
|
||||||
const expectedType = parameter.type;
|
|
||||||
let parentParameterName;
|
|
||||||
let parentValue;
|
|
||||||
let parentParamIsPresent = true;
|
|
||||||
let parentParameterIsArray = false;
|
|
||||||
|
|
||||||
if (/\./.test(parameterName)) {
|
|
||||||
parentParameterName = parameterName.replace(/\.[^.]+$/, "");
|
|
||||||
parentParameterIsArray = parentParameterName.slice(-2) === "[]";
|
|
||||||
if (parentParameterIsArray) {
|
|
||||||
parentParameterName = parentParameterName.slice(0, -2);
|
|
||||||
}
|
|
||||||
parentValue = get(options, parentParameterName);
|
|
||||||
parentParamIsPresent =
|
|
||||||
parentParameterName === "headers" ||
|
|
||||||
(typeof parentValue === "object" && parentValue !== null);
|
|
||||||
}
|
|
||||||
|
|
||||||
const values = parentParameterIsArray
|
|
||||||
? (get(options, parentParameterName) || []).map(
|
|
||||||
value => value[parameterName.split(/\./).pop()]
|
|
||||||
)
|
|
||||||
: [get(options, parameterName)];
|
|
||||||
|
|
||||||
values.forEach((value, i) => {
|
|
||||||
const valueIsPresent = typeof value !== "undefined";
|
|
||||||
const valueIsNull = value === null;
|
|
||||||
const currentParameterName = parentParameterIsArray
|
|
||||||
? parameterName.replace(/\[\]/, `[${i}]`)
|
|
||||||
: parameterName;
|
|
||||||
|
|
||||||
if (!parameter.required && !valueIsPresent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the parent parameter is of type object but allows null
|
|
||||||
// then the child parameters can be ignored
|
|
||||||
if (!parentParamIsPresent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameter.allowNull && valueIsNull) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parameter.allowNull && valueIsNull) {
|
|
||||||
throw new RequestError(
|
|
||||||
`'${currentParameterName}' cannot be null`,
|
|
||||||
400,
|
|
||||||
{
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameter.required && !valueIsPresent) {
|
|
||||||
throw new RequestError(
|
|
||||||
`Empty value for parameter '${currentParameterName}': ${JSON.stringify(
|
|
||||||
value
|
|
||||||
)}`,
|
|
||||||
400,
|
|
||||||
{
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse to integer before checking for enum
|
|
||||||
// so that string "1" will match enum with number 1
|
|
||||||
if (expectedType === "integer") {
|
|
||||||
const unparsedValue = value;
|
|
||||||
value = parseInt(value, 10);
|
|
||||||
if (isNaN(value)) {
|
|
||||||
throw new RequestError(
|
|
||||||
`Invalid value for parameter '${currentParameterName}': ${JSON.stringify(
|
|
||||||
unparsedValue
|
|
||||||
)} is NaN`,
|
|
||||||
400,
|
|
||||||
{
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameter.enum && parameter.enum.indexOf(String(value)) === -1) {
|
|
||||||
throw new RequestError(
|
|
||||||
`Invalid value for parameter '${currentParameterName}': ${JSON.stringify(
|
|
||||||
value
|
|
||||||
)}`,
|
|
||||||
400,
|
|
||||||
{
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameter.validation) {
|
|
||||||
const regex = new RegExp(parameter.validation);
|
|
||||||
if (!regex.test(value)) {
|
|
||||||
throw new RequestError(
|
|
||||||
`Invalid value for parameter '${currentParameterName}': ${JSON.stringify(
|
|
||||||
value
|
|
||||||
)}`,
|
|
||||||
400,
|
|
||||||
{
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expectedType === "object" && typeof value === "string") {
|
|
||||||
try {
|
|
||||||
value = JSON.parse(value);
|
|
||||||
} catch (exception) {
|
|
||||||
throw new RequestError(
|
|
||||||
`JSON parse error of value for parameter '${currentParameterName}': ${JSON.stringify(
|
|
||||||
value
|
|
||||||
)}`,
|
|
||||||
400,
|
|
||||||
{
|
|
||||||
request: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set(options, parameter.mapTo || currentParameterName, value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
-7
@@ -1,7 +0,0 @@
|
|||||||
# [ISC License](https://spdx.org/licenses/ISC)
|
|
||||||
|
|
||||||
Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
|
|
||||||
|
|
||||||
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.
|
|
||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
# universal-user-agent
|
|
||||||
|
|
||||||
> Get a user agent string in both browser and node
|
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/universal-user-agent)
|
|
||||||
[](https://travis-ci.com/gr2m/universal-user-agent)
|
|
||||||
[](https://greenkeeper.io/)
|
|
||||||
|
|
||||||
```js
|
|
||||||
const { getUserAgent } = require("universal-user-agent");
|
|
||||||
// or import { getUserAgent } from "universal-user-agent";
|
|
||||||
|
|
||||||
const userAgent = getUserAgent();
|
|
||||||
// userAgent will look like this
|
|
||||||
// in browser: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0"
|
|
||||||
// in node: Node.js/v8.9.4 (macOS High Sierra; x64)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
The Node implementation was originally inspired by [default-user-agent](https://www.npmjs.com/package/default-user-agent).
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[ISC](LICENSE.md)
|
|
||||||
Generated
Vendored
-22
@@ -1,22 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
Object.defineProperty(exports, '__esModule', { value: true });
|
|
||||||
|
|
||||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
||||||
|
|
||||||
var osName = _interopDefault(require('os-name'));
|
|
||||||
|
|
||||||
function getUserAgent() {
|
|
||||||
try {
|
|
||||||
return `Node.js/${process.version.substr(1)} (${osName()}; ${process.arch})`;
|
|
||||||
} catch (error) {
|
|
||||||
if (/wmic os get Caption/.test(error.message)) {
|
|
||||||
return "Windows <version undetectable>";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getUserAgent = getUserAgent;
|
|
||||||
//# sourceMappingURL=index.js.map
|
|
||||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"index.js","sources":["../dist-src/node.js"],"sourcesContent":["import osName from \"os-name\";\nexport function getUserAgent() {\n try {\n return `Node.js/${process.version.substr(1)} (${osName()}; ${process.arch})`;\n }\n catch (error) {\n if (/wmic os get Caption/.test(error.message)) {\n return \"Windows <version undetectable>\";\n }\n throw error;\n }\n}\n"],"names":["getUserAgent","process","version","substr","osName","arch","error","test","message"],"mappings":";;;;;;;;AACO,SAASA,YAAT,GAAwB;MACvB;WACQ,WAAUC,OAAO,CAACC,OAAR,CAAgBC,MAAhB,CAAuB,CAAvB,CAA0B,KAAIC,MAAM,EAAG,KAAIH,OAAO,CAACI,IAAK,GAA1E;GADJ,CAGA,OAAOC,KAAP,EAAc;QACN,sBAAsBC,IAAtB,CAA2BD,KAAK,CAACE,OAAjC,CAAJ,EAA+C;aACpC,gCAAP;;;UAEEF,KAAN;;;;;;"}
|
|
||||||
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
export function getUserAgent() {
|
|
||||||
try {
|
|
||||||
return navigator.userAgent;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return "<environment unknown>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user