mirror of
https://github.com/github/codeql-action.git
synced 2026-10-20 01:31:28 +00:00
Compare commits
33 Commits
v4
...
mbg/deprec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bb7f8f14a | ||
|
|
6cf1931c04 | ||
|
|
ae098fa9fe | ||
|
|
0a458f10ac | ||
|
|
4ebc48bf25 | ||
|
|
1ec6b03cf4 | ||
|
|
2b128fe612 | ||
|
|
7a6e2f798f | ||
|
|
46d3daa879 | ||
|
|
2edace40f1 | ||
|
|
e5b217aeb5 | ||
|
|
3ec43abae3 | ||
|
|
3afe9c01db | ||
|
|
8844fb33e0 | ||
|
|
c1641847bb | ||
|
|
047c751d92 | ||
|
|
f6e8dce502 | ||
|
|
a08b587b61 | ||
|
|
bfe264b559 | ||
|
|
f9b4185b99 | ||
|
|
66c96fdc35 | ||
|
|
1d30a842cd | ||
|
|
1b0a617641 | ||
|
|
96501a33ac | ||
|
|
a2438139ce | ||
|
|
e0625309c3 | ||
|
|
61bfcffab9 | ||
|
|
102e46e9d1 | ||
|
|
0735d7910f | ||
|
|
7d7a550898 | ||
|
|
23d418cf2e | ||
|
|
924990a9c7 | ||
|
|
4a2ca5c068 |
4
.github/workflows/__analysis-kinds.yml
generated
vendored
4
.github/workflows/__analysis-kinds.yml
generated
vendored
@@ -87,7 +87,7 @@ jobs:
|
||||
post-processed-sarif-path: '${{ runner.temp }}/post-processed'
|
||||
|
||||
- name: Upload SARIF files
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: |
|
||||
analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload post-processed SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: |
|
||||
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||
|
||||
2
.github/workflows/__config-export.yml
generated
vendored
2
.github/workflows/__config-export.yml
generated
vendored
@@ -65,7 +65,7 @@ jobs:
|
||||
output: '${{ runner.temp }}/results'
|
||||
upload-database: false
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||
|
||||
2
.github/workflows/__config-input.yml
generated
vendored
2
.github/workflows/__config-input.yml
generated
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
|
||||
2
.github/workflows/__diagnostics-export.yml
generated
vendored
2
.github/workflows/__diagnostics-export.yml
generated
vendored
@@ -76,7 +76,7 @@ jobs:
|
||||
output: '${{ runner.temp }}/results'
|
||||
upload-database: false
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||
|
||||
2
.github/workflows/__export-file-baseline-information.yml
generated
vendored
2
.github/workflows/__export-file-baseline-information.yml
generated
vendored
@@ -97,7 +97,7 @@ jobs:
|
||||
with:
|
||||
output: '${{ runner.temp }}/results'
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||
|
||||
2
.github/workflows/__job-run-uuid-sarif.yml
generated
vendored
2
.github/workflows/__job-run-uuid-sarif.yml
generated
vendored
@@ -62,7 +62,7 @@ jobs:
|
||||
with:
|
||||
output: '${{ runner.temp }}/results'
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||
|
||||
1
.github/workflows/__multi-language-autodetect.yml
generated
vendored
1
.github/workflows/__multi-language-autodetect.yml
generated
vendored
@@ -192,6 +192,5 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES: true
|
||||
CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI: true
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
|
||||
2
.github/workflows/__packaging-codescanning-config-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-codescanning-config-inputs-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||
cache: false
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
|
||||
2
.github/workflows/__packaging-config-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-config-inputs-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||
cache: false
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
|
||||
2
.github/workflows/__packaging-config-js.yml
generated
vendored
2
.github/workflows/__packaging-config-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||
cache: false
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
|
||||
2
.github/workflows/__packaging-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-inputs-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||
cache: false
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
- name: Check expected artifacts exist
|
||||
run: |
|
||||
LANGUAGES="cpp csharp go java javascript python"
|
||||
|
||||
2
.github/workflows/debug-artifacts-safe.yml
vendored
2
.github/workflows/debug-artifacts-safe.yml
vendored
@@ -82,7 +82,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
- name: Check expected artifacts exist
|
||||
run: |
|
||||
VERSIONS="stable-v2.20.7 default linked nightly-latest"
|
||||
|
||||
2
.github/workflows/post-release-mergeback.yml
vendored
2
.github/workflows/post-release-mergeback.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0 # ensure we have all tags and can push commits
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
|
||||
8
.github/workflows/pr-checks.yml
vendored
8
.github/workflows/pr-checks.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: "npm"
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: "npm"
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
|
||||
- name: Upload repo size comment
|
||||
if: steps.fetch-base.outcome == 'success'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: repo-size-comment
|
||||
path: ${{ runner.temp }}/repo-size/
|
||||
@@ -223,7 +223,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download repo size comment
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
with:
|
||||
name: repo-size-comment
|
||||
path: repo-size-comment
|
||||
|
||||
2
.github/workflows/query-filters.yml
vendored
2
.github/workflows/query-filters.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
|
||||
2
.github/workflows/rebuild.yml
vendored
2
.github/workflows/rebuild.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
ref: ${{ env.HEAD_REF }}
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
|
||||
2
.github/workflows/update-bundle.yml
vendored
2
.github/workflows/update-bundle.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
git config --global user.name "github-actions[bot]"
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
|
||||
|
||||
## [UNRELEASED]
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.39.0 - 15 Oct 2026
|
||||
|
||||
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205)
|
||||
|
||||
166
lib/entry-points.js
generated
166
lib/entry-points.js
generated
@@ -26401,7 +26401,7 @@ var require_utils4 = __commonJS({
|
||||
})();
|
||||
Object.defineProperty(exports2, "__esModule", { value: true });
|
||||
exports2.GitHub = exports2.defaults = exports2.context = void 0;
|
||||
exports2.getOctokitOptions = getOctokitOptions2;
|
||||
exports2.getOctokitOptions = getOctokitOptions;
|
||||
var Context = __importStar2(require_context());
|
||||
var Utils = __importStar2(require_utils3());
|
||||
var core_1 = (init_dist_src2(), __toCommonJS(dist_src_exports));
|
||||
@@ -26417,7 +26417,7 @@ var require_utils4 = __commonJS({
|
||||
}
|
||||
};
|
||||
exports2.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports2.defaults);
|
||||
function getOctokitOptions2(token, options) {
|
||||
function getOctokitOptions(token, options) {
|
||||
const opts = Object.assign({}, options || {});
|
||||
const auth2 = Utils.getAuthString(token, opts);
|
||||
if (auth2) {
|
||||
@@ -140010,7 +140010,7 @@ var require_utils10 = __commonJS({
|
||||
}
|
||||
};
|
||||
exports2.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports2.defaults);
|
||||
function getOctokitOptions2(token, options) {
|
||||
function getOctokitOptions(token, options) {
|
||||
const opts = Object.assign({}, options || {});
|
||||
const auth2 = Utils.getAuthString(token, opts);
|
||||
if (auth2) {
|
||||
@@ -140018,7 +140018,7 @@ var require_utils10 = __commonJS({
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
exports2.getOctokitOptions = getOctokitOptions2;
|
||||
exports2.getOctokitOptions = getOctokitOptions;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -169558,7 +169558,6 @@ function checkSchema(schema, obj, options = {}, path30 = "") {
|
||||
// src/util.ts
|
||||
var BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json";
|
||||
var BROKEN_VERSIONS = ["0.0.0-20211207"];
|
||||
var GITHUB_DOTCOM_URL = "https://github.com";
|
||||
var DEFAULT_DEBUG_ARTIFACT_NAME = "debug-artifacts";
|
||||
var DEFAULT_DEBUG_DATABASE_NAME = "db";
|
||||
var DEFAULT_RESERVED_RAM_SCALING_FACTOR = 0.05;
|
||||
@@ -169774,34 +169773,6 @@ function getGeneratedSuitePath(config, language) {
|
||||
"config-queries.qls"
|
||||
);
|
||||
}
|
||||
function parseGitHubUrl(inputUrl) {
|
||||
const originalUrl = inputUrl;
|
||||
if (inputUrl.indexOf("://") === -1) {
|
||||
inputUrl = `https://${inputUrl}`;
|
||||
}
|
||||
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
||||
}
|
||||
let url2;
|
||||
try {
|
||||
url2 = new URL(inputUrl);
|
||||
} catch {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
||||
}
|
||||
if (url2.hostname === "github.com" || url2.hostname === "api.github.com") {
|
||||
return GITHUB_DOTCOM_URL;
|
||||
}
|
||||
if (url2.pathname.indexOf("/api/v3") !== -1) {
|
||||
url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3"));
|
||||
}
|
||||
if (url2.hostname.startsWith("api.")) {
|
||||
url2.hostname = url2.hostname.substring(4);
|
||||
}
|
||||
if (!url2.pathname.endsWith("/")) {
|
||||
url2.pathname = `${url2.pathname}/`;
|
||||
}
|
||||
return url2.toString();
|
||||
}
|
||||
var CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR = "CODEQL_ACTION_WARNED_ABOUT_VERSION";
|
||||
var hasBeenWarnedAboutVersion = false;
|
||||
function checkGitHubVersionInRange(version, logger2) {
|
||||
@@ -170183,7 +170154,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) {
|
||||
return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME);
|
||||
}
|
||||
function getActionVersion() {
|
||||
return "4.39.0";
|
||||
return "4.39.1";
|
||||
}
|
||||
function getWorkflowEventName(env = getEnv()) {
|
||||
return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);
|
||||
@@ -170481,12 +170452,24 @@ function fixCodeQualityCategory(logger2, category, env = getEnv()) {
|
||||
|
||||
// src/logging.ts
|
||||
var core5 = __toESM(require_core());
|
||||
var joinMessageStrings = (message) => {
|
||||
if (Array.isArray(message)) {
|
||||
return message.join(" ");
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
};
|
||||
var autoJoinMessageStrings = (fn) => {
|
||||
return (message) => {
|
||||
return fn(joinMessageStrings(message));
|
||||
};
|
||||
};
|
||||
function getActionsLogger() {
|
||||
return {
|
||||
debug: core5.debug,
|
||||
info: core5.info,
|
||||
warning: core5.warning,
|
||||
error: core5.error,
|
||||
debug: autoJoinMessageStrings(core5.debug),
|
||||
info: autoJoinMessageStrings(core5.info),
|
||||
warning: autoJoinMessageStrings(core5.warning),
|
||||
error: autoJoinMessageStrings(core5.error),
|
||||
isDebug: core5.isDebug,
|
||||
startGroup: core5.startGroup,
|
||||
endGroup: core5.endGroup
|
||||
@@ -170659,6 +170642,43 @@ retry.VERSION = VERSION7;
|
||||
// src/api-client.ts
|
||||
var import_undici = __toESM(require_undici());
|
||||
|
||||
// src/github.ts
|
||||
var GITHUB_DOTCOM_URL = "https://github.com";
|
||||
function parseGitHubUrl(inputUrl) {
|
||||
const originalUrl = inputUrl;
|
||||
if (inputUrl.indexOf("://") === -1) {
|
||||
inputUrl = `https://${inputUrl}`;
|
||||
}
|
||||
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
||||
}
|
||||
let url2;
|
||||
try {
|
||||
url2 = new URL(inputUrl);
|
||||
} catch {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
||||
}
|
||||
if (url2.hostname === "github.com" || url2.hostname === "api.github.com") {
|
||||
return GITHUB_DOTCOM_URL;
|
||||
}
|
||||
if (url2.pathname.indexOf("/api/v3") !== -1) {
|
||||
url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3"));
|
||||
}
|
||||
if (url2.hostname.startsWith("api.")) {
|
||||
url2.hostname = url2.hostname.substring(4);
|
||||
}
|
||||
if (!url2.pathname.endsWith("/")) {
|
||||
url2.pathname = `${url2.pathname}/`;
|
||||
}
|
||||
return url2.toString();
|
||||
}
|
||||
function getCurrentInstance(env) {
|
||||
return {
|
||||
url: env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
||||
apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
||||
};
|
||||
}
|
||||
|
||||
// src/repository.ts
|
||||
function isRepositoryNwoStr(val) {
|
||||
return val.includes("/");
|
||||
@@ -170724,43 +170744,46 @@ function makeProxyRequestOptions(dispatcher) {
|
||||
};
|
||||
}
|
||||
function createApiClientWithDetails(apiDetails, { allowExternal = false, proxy = void 0 } = {}) {
|
||||
const auth2 = allowExternal && apiDetails.externalRepoAuth || apiDetails.auth;
|
||||
const auth2 = allowExternal && apiDetails.externalRepoAuth !== void 0 ? apiDetails.externalRepoAuth : apiDetails.auth;
|
||||
const retryingOctokit = githubUtils.GitHub.plugin(retry);
|
||||
const requestOptions = makeProxyRequestOptions(proxy);
|
||||
return new retryingOctokit(
|
||||
githubUtils.getOctokitOptions(auth2, {
|
||||
baseUrl: apiDetails.apiURL,
|
||||
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
||||
log: {
|
||||
debug: core6.debug,
|
||||
info: core6.info,
|
||||
warn: core6.warning,
|
||||
error: core6.error
|
||||
},
|
||||
request: requestOptions,
|
||||
retry: {
|
||||
doNotRetry: DO_NOT_RETRY_STATUSES
|
||||
}
|
||||
})
|
||||
);
|
||||
const opts = {
|
||||
auth: auth2 !== void 0 && auth2.trim() !== "" ? `token ${auth2}` : void 0,
|
||||
baseUrl: apiDetails.apiURL,
|
||||
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
||||
log: {
|
||||
debug: core6.debug,
|
||||
info: core6.info,
|
||||
warn: core6.warning,
|
||||
error: core6.error
|
||||
},
|
||||
request: requestOptions,
|
||||
retry: {
|
||||
doNotRetry: DO_NOT_RETRY_STATUSES
|
||||
}
|
||||
};
|
||||
return new retryingOctokit(opts);
|
||||
}
|
||||
function getApiDetails(env = getEnv()) {
|
||||
return {
|
||||
auth: getRequiredInput("token"),
|
||||
url: env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
||||
apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
||||
...getCurrentInstance(env)
|
||||
};
|
||||
}
|
||||
function getApiClient(env = getEnv()) {
|
||||
return createApiClientWithDetails(getApiDetails(env));
|
||||
function getApiClient(env = getEnv(), apiDetails) {
|
||||
return createApiClientWithDetails(apiDetails ?? getApiDetails(env));
|
||||
}
|
||||
function getApiClientWithExternalAuth(apiDetails, proxy) {
|
||||
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
||||
}
|
||||
function getAuthorizationHeaderFor(logger2, apiDetails, url2) {
|
||||
const token = apiDetails.auth?.trim();
|
||||
if (token === void 0 || token === "") {
|
||||
return void 0;
|
||||
}
|
||||
if (url2.startsWith(`${apiDetails.url}/`) || apiDetails.apiURL && url2.startsWith(`${apiDetails.apiURL}/`)) {
|
||||
logger2.debug(`Providing an authorization token.`);
|
||||
return `token ${apiDetails.auth}`;
|
||||
return `token ${token}`;
|
||||
}
|
||||
logger2.debug(`Not using an authorization token.`);
|
||||
return void 0;
|
||||
@@ -171921,11 +171944,6 @@ var featureConfig = {
|
||||
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
|
||||
minimumVersion: void 0
|
||||
},
|
||||
["cleanup_toolcache_bundles" /* CleanupToolcacheBundles */]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES",
|
||||
minimumVersion: void 0
|
||||
},
|
||||
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
|
||||
@@ -176718,7 +176736,6 @@ function getToolcacheDestination({ logger: logger2 }, source) {
|
||||
}
|
||||
async function tryDeleteToolcacheBundles({
|
||||
env,
|
||||
features,
|
||||
logger: logger2
|
||||
}) {
|
||||
if (env.getOptional("CODEQL_ACTION_HAS_SET_UP_CODEQL" /* HAS_SET_UP_CODEQL */) !== void 0) {
|
||||
@@ -176727,7 +176744,7 @@ async function tryDeleteToolcacheBundles({
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!isGitHubHostedRunner() || !isToolcacheOnWorkspaceFilesystem(logger2) || !await features.getValue("cleanup_toolcache_bundles" /* CleanupToolcacheBundles */)) {
|
||||
if (!isGitHubHostedRunner(env) || !isToolcacheOnWorkspaceFilesystem(logger2)) {
|
||||
return;
|
||||
}
|
||||
const result = await deleteToolcacheBundles({ env, logger: logger2 });
|
||||
@@ -176787,7 +176804,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
||||
break;
|
||||
case "download": {
|
||||
const result = await downloadCodeQLBundle(
|
||||
{ env: getEnv(), features, logger: logger2 },
|
||||
{ env: getEnv(), logger: logger2 },
|
||||
source,
|
||||
apiDetails,
|
||||
zstdAvailability.version,
|
||||
@@ -178491,7 +178508,7 @@ async function recordClearCleanupSizes(codeql, config, reports, logger2) {
|
||||
}
|
||||
}
|
||||
async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails) {
|
||||
const client = getApiClient();
|
||||
const client = getApiClient(getEnv(), apiDetails);
|
||||
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
||||
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
||||
let uploadsBaseUrl = uploadsUrl.toString();
|
||||
@@ -178512,7 +178529,6 @@ async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundled
|
||||
commit_oid: commitOid,
|
||||
data: bundledDbReadStream,
|
||||
headers: {
|
||||
authorization: `token ${apiDetails.auth}`,
|
||||
"Content-Type": "application/zip",
|
||||
"Content-Length": bundledDbSize
|
||||
},
|
||||
@@ -180011,6 +180027,7 @@ async function shouldDisableCombineSarifFiles(sarifObjects, githubVersion) {
|
||||
return true;
|
||||
}
|
||||
async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger2) {
|
||||
const env = getEnv();
|
||||
logger2.info("Combining SARIF files using the CodeQL CLI");
|
||||
const sarifObjects = sarifFiles.map(readSarifFile);
|
||||
const deprecationWarningMessage = gitHubVersion.type === "GitHub Enterprise Server" /* GHES */ ? "and will be removed in GitHub Enterprise Server 3.18" : "and will be removed in July 2025";
|
||||
@@ -180043,8 +180060,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
|
||||
externalRepoAuth: getOptionalInput(
|
||||
"external-repository-token"
|
||||
),
|
||||
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
|
||||
apiURL: getRequiredEnvParam("GITHUB_API_URL")
|
||||
...getCurrentInstance(env)
|
||||
};
|
||||
const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type);
|
||||
const initCodeQLResult = await initCodeQL(
|
||||
@@ -186450,8 +186466,7 @@ async function run3(actionState) {
|
||||
apiDetails = {
|
||||
auth: getRequiredInput("token"),
|
||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||
url: actionState.env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
||||
apiURL: actionState.env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
||||
...getCurrentInstance(actionState.env)
|
||||
};
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
checkGitHubVersionInRange(gitHubVersion, logger2);
|
||||
@@ -187493,8 +187508,7 @@ async function run6(actionState) {
|
||||
const apiDetails = {
|
||||
auth: getRequiredInput("token"),
|
||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||
url: actionState.env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
||||
apiURL: actionState.env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
||||
...getCurrentInstance(actionState.env)
|
||||
};
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
checkGitHubVersionInRange(gitHubVersion, logger2);
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.39.0",
|
||||
"version": "4.39.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "codeql",
|
||||
"version": "4.39.0",
|
||||
"version": "4.39.1",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"pr-checks"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.39.0",
|
||||
"version": "4.39.1",
|
||||
"private": true,
|
||||
"description": "CodeQL action",
|
||||
"scripts": {
|
||||
|
||||
@@ -46,7 +46,7 @@ steps:
|
||||
post-processed-sarif-path: "${{ runner.temp }}/post-processed"
|
||||
|
||||
- name: Upload SARIF files
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: |
|
||||
analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||
@@ -54,7 +54,7 @@ steps:
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload post-processed SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: |
|
||||
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||
|
||||
@@ -14,7 +14,7 @@ steps:
|
||||
output: "${{ runner.temp }}/results"
|
||||
upload-database: false
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||
|
||||
@@ -27,7 +27,7 @@ steps:
|
||||
output: "${{ runner.temp }}/results"
|
||||
upload-database: false
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||
|
||||
@@ -27,7 +27,7 @@ steps:
|
||||
with:
|
||||
output: "${{ runner.temp }}/results"
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||
|
||||
@@ -12,7 +12,7 @@ steps:
|
||||
with:
|
||||
output: "${{ runner.temp }}/results"
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||
|
||||
@@ -14,7 +14,6 @@ operatingSystems:
|
||||
- stable-v2.21.4
|
||||
- stable-v2.22.4
|
||||
env:
|
||||
CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES: true
|
||||
CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI: true
|
||||
installGo: true
|
||||
installDotNet: true
|
||||
|
||||
@@ -215,8 +215,8 @@ const languageSetups: LanguageSetups = {
|
||||
name: "Install Node.js",
|
||||
uses: pinnedUses(
|
||||
"actions/setup-node",
|
||||
"820762786026740c76f36085b0efc47a31fe5020",
|
||||
"v7.0.0",
|
||||
"949feb2413d6458794dcd2491c4babbbce0c15c1",
|
||||
"v7.1.0",
|
||||
),
|
||||
with: {
|
||||
"node-version": defaultLanguageVersions.javascript,
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from "./actions-util";
|
||||
import { computeAutomationID } from "./api-client";
|
||||
import { EnvVar } from "./environment";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { RecordingLogger, setupTests } from "./testing-utils";
|
||||
import { initializeEnvironment, withTmpDir } from "./util";
|
||||
|
||||
@@ -238,7 +237,7 @@ test.serial("fixCodeQualityCategory", (t) => {
|
||||
GITHUB_EVENT_NAME: "dynamic",
|
||||
},
|
||||
() => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
// Categories that should get adjusted.
|
||||
t.is(fixCodeQualityCategory(logger, "/language:c#"), "/language:csharp");
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
supportedAnalysisKinds,
|
||||
} from "./analyses";
|
||||
import { EnvVar } from "./environment";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import {
|
||||
createFeatures,
|
||||
RecordingLogger,
|
||||
@@ -65,7 +64,7 @@ test.serial(
|
||||
.withArgs("analysis-kinds")
|
||||
.returns("code-scanning,code-quality");
|
||||
const result = await getAnalysisKinds(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
features,
|
||||
true,
|
||||
);
|
||||
@@ -139,7 +138,7 @@ test.serial(
|
||||
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
||||
optionalInputStub.withArgs("quality-queries").returns("code-quality");
|
||||
const result = await getAnalysisKinds(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
features,
|
||||
true,
|
||||
);
|
||||
@@ -155,7 +154,7 @@ test.serial(
|
||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||
requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing");
|
||||
await t.throwsAsync(
|
||||
getAnalysisKinds(getRunnerLogger(true), features, true),
|
||||
getAnalysisKinds(new RecordingLogger(), features, true),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -181,7 +180,7 @@ for (let i = 0; i < analysisKinds.length; i++) {
|
||||
.withArgs("analysis-kinds")
|
||||
.returns([analysisKind, otherAnalysis].join(","));
|
||||
const result = await getAnalysisKinds(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
features,
|
||||
true,
|
||||
);
|
||||
@@ -199,7 +198,7 @@ for (let i = 0; i < analysisKinds.length; i++) {
|
||||
.withArgs("analysis-kinds")
|
||||
.returns([analysisKind, otherAnalysis].join(","));
|
||||
await t.throwsAsync(
|
||||
getAnalysisKinds(getRunnerLogger(true), features, true),
|
||||
getAnalysisKinds(new RecordingLogger(), features, true),
|
||||
{
|
||||
instanceOf: ConfigurationError,
|
||||
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`,
|
||||
|
||||
@@ -17,12 +17,12 @@ import { defaultSuites } from "./config/db-config";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import {
|
||||
setupTests,
|
||||
setupActionsVars,
|
||||
createFeatures,
|
||||
createTestConfig,
|
||||
RecordingLogger,
|
||||
callee,
|
||||
} from "./testing-utils";
|
||||
import * as uploadLib from "./upload-lib";
|
||||
@@ -195,7 +195,7 @@ test.serial("status report fields", async (t) => {
|
||||
undefined,
|
||||
codeql,
|
||||
config,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
createFeatures([Feature.QaTelemetryEnabled]),
|
||||
);
|
||||
t.deepEqual(Object.keys(statusReport).sort(), [
|
||||
|
||||
@@ -8,7 +8,14 @@ import * as actionsUtil from "./actions-util";
|
||||
import * as api from "./api-client";
|
||||
import { DO_NOT_RETRY_STATUSES } from "./api-client";
|
||||
import { ActionsEnvVars, RegistryProxyVars } from "./environment";
|
||||
import { callee, getTestEnv, setupTests } from "./testing-utils";
|
||||
import { GITHUB_DOTCOM_API_URL, GITHUB_DOTCOM_URL } from "./github";
|
||||
import {
|
||||
callee,
|
||||
getTestEnv,
|
||||
RecordingLogger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
setupTests,
|
||||
} from "./testing-utils";
|
||||
import * as util from "./util";
|
||||
|
||||
setupTests(test);
|
||||
@@ -284,3 +291,87 @@ test("makeProxyRequestOptions - returns fetch with custom proxy", async (t) => {
|
||||
githubUtils.defaults.request,
|
||||
);
|
||||
});
|
||||
|
||||
test.serial(
|
||||
"getApiClientWithExternalAuth constructs clients with or without tokens",
|
||||
(t) => {
|
||||
t.notThrows(() => {
|
||||
api.getApiClientWithExternalAuth(SAMPLE_DOTCOM_API_DETAILS);
|
||||
api.getApiClientWithExternalAuth({
|
||||
...SAMPLE_DOTCOM_API_DETAILS,
|
||||
auth: undefined,
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("getAuthorizationHeaderFor - returns undefined if there's no token", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
{ ...SAMPLE_DOTCOM_API_DETAILS, auth: undefined },
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
{ ...SAMPLE_DOTCOM_API_DETAILS, auth: "" },
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
{ ...SAMPLE_DOTCOM_API_DETAILS, auth: " " },
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
test("getAuthorizationHeaderFor - returns header value with token if url is allowed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
`token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`${GITHUB_DOTCOM_API_URL}/github`,
|
||||
),
|
||||
`token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||
);
|
||||
});
|
||||
|
||||
test("getAuthorizationHeaderFor - returns undefined if url is not allowed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`https://localhost/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`https://api.localhost/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as core from "@actions/core";
|
||||
import * as githubUtils from "@actions/github/lib/utils";
|
||||
import type { OctokitOptions } from "@octokit/core";
|
||||
import * as retry from "@octokit/plugin-retry";
|
||||
import { RequestRequestOptions } from "@octokit/types";
|
||||
import {
|
||||
@@ -12,26 +13,32 @@ import {
|
||||
import type { ActionState } from "./action-common";
|
||||
import { getActionVersion, getRequiredInput } from "./actions-util";
|
||||
import {
|
||||
ActionsEnvVars,
|
||||
EnvVar,
|
||||
ReadOnlyEnv,
|
||||
RegistryProxyVars,
|
||||
getEnv,
|
||||
exportEnvVar,
|
||||
} from "./environment";
|
||||
import {
|
||||
getCurrentInstance,
|
||||
GITHUB_DOTCOM_URL,
|
||||
parseGitHubUrl,
|
||||
type GitHubApiCombinedDetails,
|
||||
type GitHubApiDetails,
|
||||
} from "./github";
|
||||
import { Logger } from "./logging";
|
||||
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
||||
import {
|
||||
asHTTPError,
|
||||
ConfigurationError,
|
||||
getRequiredEnvParam,
|
||||
GITHUB_DOTCOM_URL,
|
||||
GitHubVariant,
|
||||
GitHubVersion,
|
||||
parseGitHubUrl,
|
||||
parseMatrixInput,
|
||||
} from "./util";
|
||||
|
||||
export type { GitHubApiDetails, GitHubApiCombinedDetails } from "./github";
|
||||
|
||||
const GITHUB_ENTERPRISE_VERSION_HEADER = "x-github-enterprise-version";
|
||||
|
||||
/**
|
||||
@@ -43,21 +50,6 @@ const GITHUB_ENTERPRISE_VERSION_HEADER = "x-github-enterprise-version";
|
||||
*/
|
||||
export const DO_NOT_RETRY_STATUSES = [400, 410, 422, 451];
|
||||
|
||||
export type GitHubApiCombinedDetails = GitHubApiDetails &
|
||||
GitHubApiExternalRepoDetails;
|
||||
|
||||
export interface GitHubApiDetails {
|
||||
auth: string;
|
||||
url: string;
|
||||
apiURL: string | undefined;
|
||||
}
|
||||
|
||||
export interface GitHubApiExternalRepoDetails {
|
||||
externalRepoAuth?: string;
|
||||
url: string;
|
||||
apiURL: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration for the private registry authentication proxy,
|
||||
* if it is available in the environment.
|
||||
@@ -139,37 +131,60 @@ function createApiClientWithDetails(
|
||||
{ allowExternal = false, proxy = undefined }: CreateApiClientOptions = {},
|
||||
): ApiClient {
|
||||
const auth =
|
||||
(allowExternal && apiDetails.externalRepoAuth) || apiDetails.auth;
|
||||
allowExternal && apiDetails.externalRepoAuth !== undefined
|
||||
? apiDetails.externalRepoAuth
|
||||
: apiDetails.auth;
|
||||
const retryingOctokit = githubUtils.GitHub.plugin(retry.retry);
|
||||
const requestOptions = makeProxyRequestOptions(proxy);
|
||||
return new retryingOctokit(
|
||||
githubUtils.getOctokitOptions(auth, {
|
||||
baseUrl: apiDetails.apiURL,
|
||||
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
||||
log: {
|
||||
debug: core.debug,
|
||||
info: core.info,
|
||||
warn: core.warning,
|
||||
error: core.error,
|
||||
},
|
||||
request: requestOptions,
|
||||
retry: {
|
||||
doNotRetry: DO_NOT_RETRY_STATUSES,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const opts: OctokitOptions = {
|
||||
auth:
|
||||
auth !== undefined && auth.trim() !== "" ? `token ${auth}` : undefined,
|
||||
baseUrl: apiDetails.apiURL,
|
||||
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
||||
log: {
|
||||
debug: core.debug,
|
||||
info: core.info,
|
||||
warn: core.warning,
|
||||
error: core.error,
|
||||
},
|
||||
request: requestOptions,
|
||||
retry: {
|
||||
doNotRetry: DO_NOT_RETRY_STATUSES,
|
||||
},
|
||||
};
|
||||
|
||||
return new retryingOctokit(opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `GitHubApiDetails` object describing the GitHub instance we are currently running on.
|
||||
*
|
||||
* @param env The environment variables to read.
|
||||
*/
|
||||
export function getApiDetails(env: ReadOnlyEnv = getEnv()): GitHubApiDetails {
|
||||
return {
|
||||
auth: getRequiredInput("token"),
|
||||
url: env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
||||
apiURL: env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
||||
...getCurrentInstance(env),
|
||||
};
|
||||
}
|
||||
|
||||
export function getApiClient(env: ReadOnlyEnv = getEnv()) {
|
||||
return createApiClientWithDetails(getApiDetails(env));
|
||||
/**
|
||||
* Constructs an {@link ApiClient} using {@link apiDetails}.
|
||||
*
|
||||
* If {@link apiDetails} is not specified, then the GitHub instance URLs and auth token
|
||||
* are taken from {@link env}.
|
||||
*
|
||||
* If {@link env} is not specified, then the process environment is used.
|
||||
*
|
||||
* @param env The environment to obtain the GitHub instance URLs from.
|
||||
* @param apiDetails The {@link GitHubApiDetails} to construct the {@link ApiClient} for.
|
||||
*/
|
||||
export function getApiClient(
|
||||
env: ReadOnlyEnv = getEnv(),
|
||||
apiDetails?: GitHubApiDetails,
|
||||
) {
|
||||
return createApiClientWithDetails(apiDetails ?? getApiDetails(env));
|
||||
}
|
||||
|
||||
export function getApiClientWithExternalAuth(
|
||||
@@ -194,6 +209,12 @@ export function getAuthorizationHeaderFor(
|
||||
apiDetails: GitHubApiDetails,
|
||||
url: string,
|
||||
): string | undefined {
|
||||
// We don't have to check the `url` if we don't have a token to begin with.
|
||||
const token = apiDetails.auth?.trim();
|
||||
if (token === undefined || token === "") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We only want to provide an authorization header if we are downloading
|
||||
// from the same GitHub instance the Action is running on.
|
||||
// This avoids leaking Enterprise tokens to dotcom.
|
||||
@@ -202,7 +223,7 @@ export function getAuthorizationHeaderFor(
|
||||
(apiDetails.apiURL && url.startsWith(`${apiDetails.apiURL}/`))
|
||||
) {
|
||||
logger.debug(`Providing an authorization token.`);
|
||||
return `token ${apiDetails.auth}`;
|
||||
return `token ${token}`;
|
||||
}
|
||||
|
||||
logger.debug(`Not using an authorization token.`);
|
||||
|
||||
@@ -10,12 +10,12 @@ import {
|
||||
scanArtifactsForTokens,
|
||||
TokenType,
|
||||
} from "./artifact-scanner";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
getRecordingLogger,
|
||||
LoggedMessage,
|
||||
makeTestToken,
|
||||
RecordingLogger,
|
||||
} from "./testing-utils";
|
||||
|
||||
test("makeTestToken", (t) => {
|
||||
@@ -121,7 +121,7 @@ for (const { type, value, checkPattern } of testTokens) {
|
||||
}
|
||||
|
||||
test("scanArtifactsForTokens handles files without tokens", async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-"));
|
||||
|
||||
try {
|
||||
|
||||
@@ -3,15 +3,14 @@ import path from "path";
|
||||
|
||||
import test from "ava";
|
||||
|
||||
import { getRunnerLogger } from "../logging";
|
||||
import { setupTests } from "../testing-utils";
|
||||
import { RecordingLogger, setupTests } from "../testing-utils";
|
||||
import * as util from "../util";
|
||||
|
||||
import { getCachedCodeQlVersion } from "./output-cache";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
test.serial(
|
||||
"getCachedCodeQlVersion reuses a version persisted by an earlier step",
|
||||
|
||||
@@ -22,7 +22,6 @@ import type { Config } from "./config-utils";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { DocUrl } from "./doc-url";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { ToolsSource } from "./setup-codeql";
|
||||
import {
|
||||
setupTests,
|
||||
@@ -34,6 +33,8 @@ import {
|
||||
makeVersionInfo,
|
||||
createTestConfig,
|
||||
makeMacro,
|
||||
getCodeQLForTesting,
|
||||
RecordingLogger,
|
||||
} from "./testing-utils";
|
||||
import { ToolsDownloadStatusReport } from "./tools-download";
|
||||
import * as util from "./util";
|
||||
@@ -102,7 +103,7 @@ async function installIntoToolcache({
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
}
|
||||
@@ -126,7 +127,7 @@ function mockReleaseApi({
|
||||
});
|
||||
}
|
||||
|
||||
function mockApiDetails(apiDetails: GitHubApiDetails) {
|
||||
function mockApiDetails(apiDetails: Required<GitHubApiDetails>) {
|
||||
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
||||
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
||||
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
||||
@@ -140,7 +141,7 @@ function mockApiDetails(apiDetails: GitHubApiDetails) {
|
||||
}
|
||||
|
||||
async function stubCodeql(): Promise<codeql.CodeQL> {
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
const codeqlObject = await getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
||||
sinon
|
||||
.stub(codeqlObject, "isTracedLanguage")
|
||||
@@ -176,7 +177,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
|
||||
@@ -212,7 +213,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
|
||||
@@ -252,7 +253,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
|
||||
@@ -362,7 +363,7 @@ for (const {
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
|
||||
@@ -405,7 +406,7 @@ for (const toolcacheVersion of [
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
t.is(
|
||||
@@ -450,7 +451,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
t.deepEqual(result.toolsVersion, "0.0.0-20200601");
|
||||
@@ -497,7 +498,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||
@@ -537,7 +538,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||
@@ -579,7 +580,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
false,
|
||||
);
|
||||
|
||||
@@ -664,7 +665,7 @@ const injectedConfigMacro = makeMacro({
|
||||
tempDir,
|
||||
};
|
||||
thisStubConfig.computedConfig = generateCodeScanningConfig(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
thisStubConfig.originalUserInput,
|
||||
augmentationProperties,
|
||||
);
|
||||
@@ -1039,7 +1040,7 @@ test.serial("runTool summarizes autobuilder errors", async (t) => {
|
||||
[2019-09-18 12:00:01] [autobuild] A non-error message
|
||||
`;
|
||||
stubToolRunnerConstructor(1, stderr);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
const codeqlObject = await getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
||||
sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor");
|
||||
// io throws because of the test CodeQL object.
|
||||
@@ -1095,7 +1096,7 @@ test.serial("runTool recognizes fatal internal errors", async (t) => {
|
||||
com.semmle.util.exception.CatastrophicError: An error occurred while evaluating ControlFlowGraph::ControlFlow::Root.isRootOf/1#dispred#f610e6ed/2@86282cc8
|
||||
Severe disk cache trouble (corruption or out of space) at /home/runner/work/_temp/codeql_databases/go/db-go/default/cache/pages/28/33.pack: Failed to write item to disk`;
|
||||
stubToolRunnerConstructor(1, stderr);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
const codeqlObject = await getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
||||
sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor");
|
||||
// io throws because of the test CodeQL object.
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
} from "./feature-flags";
|
||||
import { isAnalyzingDefaultBranch } from "./git-utils";
|
||||
import { Language } from "./languages";
|
||||
import { getRunnerLogger, Logger } from "./logging";
|
||||
import type { Logger } from "./logging";
|
||||
import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "./overlay";
|
||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||
import * as setupCodeql from "./setup-codeql";
|
||||
@@ -486,18 +486,6 @@ export function createStubCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a real, newly created CodeQL instance for testing. The instance refers to
|
||||
* a non-existent placeholder codeql command, so tests that use this function
|
||||
* should also stub the toolrunner.ToolRunner constructor.
|
||||
*/
|
||||
export async function getCodeQLForTesting(
|
||||
cmd = "codeql-for-testing",
|
||||
logger: Logger = getRunnerLogger(true),
|
||||
): Promise<CodeQL> {
|
||||
return getCodeQLForCmd(logger, cmd, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a CodeQL object for CodeQL CLI access.
|
||||
*
|
||||
@@ -506,7 +494,7 @@ export async function getCodeQLForTesting(
|
||||
* version requirement. Must be set to true outside tests.
|
||||
* @returns A new CodeQL object
|
||||
*/
|
||||
async function getCodeQLForCmd(
|
||||
export async function getCodeQLForCmd(
|
||||
logger: Logger,
|
||||
cmd: string,
|
||||
checkVersion: boolean,
|
||||
|
||||
@@ -21,7 +21,6 @@ import { RepositoryProperties } from "./feature-flags/properties";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import { GitVersionInfo } from "./git-utils";
|
||||
import { BuiltInLanguage, Language } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
|
||||
import * as overlayDiagnostics from "./overlay/diagnostics";
|
||||
import { OverlayDisabledReason } from "./overlay/diagnostics";
|
||||
@@ -42,6 +41,7 @@ import {
|
||||
callee,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
AssertableTarget,
|
||||
RecordingLogger,
|
||||
} from "./testing-utils";
|
||||
import {
|
||||
GitHubVariant,
|
||||
@@ -102,7 +102,7 @@ function createTestInitConfigInputs(
|
||||
features: createFeatures([]),
|
||||
repositoryProperties: {},
|
||||
enableFileCoverageInformation: true,
|
||||
logger: getRunnerLogger(true),
|
||||
logger: new RecordingLogger(),
|
||||
} satisfies configUtils.InitConfigInputs,
|
||||
overrides,
|
||||
);
|
||||
@@ -150,7 +150,7 @@ function mockListLanguages(languages: string[]) {
|
||||
|
||||
test.serial("load empty config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const languages = "javascript,python";
|
||||
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
@@ -196,7 +196,7 @@ test.serial("load empty config", async (t) => {
|
||||
|
||||
test.serial("load code quality config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const languages = "actions";
|
||||
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
@@ -252,7 +252,7 @@ test.serial(
|
||||
"initActionState doesn't throw if there are queries configured in the repository properties",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const languages = "javascript";
|
||||
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
@@ -315,7 +315,7 @@ test.serial(
|
||||
|
||||
test.serial("loading a saved config produces the same config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -363,7 +363,7 @@ test.serial("loading a saved config produces the same config", async (t) => {
|
||||
|
||||
test.serial("loading config with version mismatch throws", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -788,12 +788,12 @@ test.serial("Unknown languages", async (t) => {
|
||||
});
|
||||
});
|
||||
|
||||
const mockLogger = getRunnerLogger(true);
|
||||
const mockLogger = new RecordingLogger();
|
||||
|
||||
test.serial("no generateRegistries when registries is undefined", async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const registriesInput = undefined;
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const { registriesAuthTokens, qlconfigFile } =
|
||||
await configUtils.generateRegistries(registriesInput, tmpDir, logger);
|
||||
|
||||
@@ -814,7 +814,7 @@ test.serial(
|
||||
token: "not-a-token",
|
||||
},
|
||||
]);
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const { registriesAuthTokens, qlconfigFile } =
|
||||
await configUtils.generateRegistries(registriesInput, tmpDir, logger);
|
||||
|
||||
@@ -2247,7 +2247,7 @@ test("applyIncrementalAnalysisSettings: no-op when mode is not Overlay and diff
|
||||
const config = createTestConfig({});
|
||||
config.overlayDatabaseMode = OverlayDatabaseMode.None;
|
||||
const codeql = createStubCodeQL({});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
await configUtils.applyIncrementalAnalysisSettings(
|
||||
config,
|
||||
@@ -2265,7 +2265,7 @@ test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions w
|
||||
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
|
||||
});
|
||||
const codeql = createStubCodeQL({});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
await configUtils.applyIncrementalAnalysisSettings(
|
||||
config,
|
||||
@@ -2288,7 +2288,7 @@ test.serial(
|
||||
});
|
||||
config.useOverlayDatabaseCaching = true;
|
||||
const codeql = createStubCodeQL({});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const addDiagnosticsStub = sinon
|
||||
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
|
||||
.resolves();
|
||||
@@ -2320,7 +2320,7 @@ test.serial(
|
||||
config.useOverlayDatabaseCaching = false;
|
||||
config.overlayModeSetExplicitly = true;
|
||||
const codeql = createStubCodeQL({});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const addDiagnosticsStub = sinon
|
||||
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
|
||||
.resolves();
|
||||
@@ -2343,7 +2343,7 @@ test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only r
|
||||
const config = createTestConfig({});
|
||||
config.overlayDatabaseMode = OverlayDatabaseMode.None;
|
||||
const codeql = createStubCodeQL({});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
await configUtils.applyIncrementalAnalysisSettings(
|
||||
config,
|
||||
@@ -2557,7 +2557,7 @@ test("determineUserConfig - merges configs if FF is enabled in Default Setup", a
|
||||
// also check whether loading the configuration from disk that was written
|
||||
// by `determineUserConfig` matches our expectations.
|
||||
const loadedFromDisk = configUtils.getLocalConfig(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
expectedConfigPath,
|
||||
false,
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import test, { ExecutionContext } from "ava";
|
||||
|
||||
import { RepositoryProperties } from "../feature-flags/properties";
|
||||
import { BuiltInLanguage, Language } from "../languages";
|
||||
import { getRunnerLogger } from "../logging";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
getRecordingLogger,
|
||||
@@ -384,7 +383,7 @@ calculateAugmentationErrorMacro(
|
||||
|
||||
test("parseUserConfig - successfully parses valid YAML", (t) => {
|
||||
const result = dbConfig.parseUserConfig(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
"test",
|
||||
`
|
||||
paths-ignore:
|
||||
@@ -410,7 +409,7 @@ test("parseUserConfig - throws a ConfigurationError if the file is not valid YAM
|
||||
t.throws(
|
||||
() =>
|
||||
dbConfig.parseUserConfig(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
"test",
|
||||
`
|
||||
paths-ignore:
|
||||
@@ -629,7 +628,7 @@ test("mergeDefaultSetupAndUserConfigs - warns about invalid keys from Default Se
|
||||
/** Parses `contents` as a configuration without validating it. */
|
||||
function parseUnvalidatedConfig(contents: string): dbConfig.UserConfig {
|
||||
return dbConfig.parseUserConfig(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
"test",
|
||||
contents,
|
||||
false,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as fs from "fs";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import * as github from "@actions/github";
|
||||
import test from "ava";
|
||||
@@ -10,7 +11,10 @@ import { GitHubApiDetails } from "./api-client";
|
||||
import * as apiClient from "./api-client";
|
||||
import { createStubCodeQL } from "./codeql";
|
||||
import { Config } from "./config-utils";
|
||||
import { cleanupAndUploadDatabases } from "./database-upload";
|
||||
import {
|
||||
cleanupAndUploadDatabases,
|
||||
uploadBundledDatabase,
|
||||
} from "./database-upload";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
@@ -23,6 +27,7 @@ import {
|
||||
getTestEnv,
|
||||
initAllState,
|
||||
RecordingLogger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
setupActionsVars,
|
||||
setupTests,
|
||||
} from "./testing-utils";
|
||||
@@ -550,3 +555,86 @@ test.serial(
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"uploadBundledDatabase provides expected request arguments",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
// Write some file that `uploadBundledDatabase` can use for its `fs.createReadStream(bundledDb)` call
|
||||
// so we don't have to stub that or create a fake `ReadStream`.
|
||||
const dbPath = path.join(tmpDir, "db");
|
||||
const content = JSON.stringify({});
|
||||
fs.writeFileSync(dbPath, content);
|
||||
|
||||
// A simple stub for `fetch` that satisfies Octokit when it inspects the response.
|
||||
const fetchStub = sinon.stub().resolves({
|
||||
status: 200,
|
||||
headers: new Headers(),
|
||||
text: async () => "",
|
||||
});
|
||||
|
||||
// Construct a real `ApiClient`.
|
||||
const client = apiClient.getApiClient(
|
||||
getTestEnv(),
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
);
|
||||
|
||||
// Then wrap the real `request` method in a stub that calls it with our stubbed `fetch`.
|
||||
// This ensures that we have a real `ApiClient` with a mostly real `request`, but which
|
||||
// does not perform any actual requests.
|
||||
const request = client.request;
|
||||
sinon.stub(client, "request").callsFake(async (route, options) =>
|
||||
request(route, {
|
||||
...options,
|
||||
request: { ...options?.request, fetch: fetchStub },
|
||||
}),
|
||||
);
|
||||
|
||||
// Stub `getApiClient` to return our modified `ApiClient`.
|
||||
const getApiClient = sinon
|
||||
.stub(apiClient, "getApiClient")
|
||||
.returns(client);
|
||||
|
||||
// Calling `uploadBundledDatabase` shouldn't throw.
|
||||
const nwo: RepositoryNwo = { owner: "test", repo: "foo" };
|
||||
const language: BuiltInLanguage = BuiltInLanguage.java;
|
||||
|
||||
await t.notThrowsAsync(async () => {
|
||||
await uploadBundledDatabase(
|
||||
nwo,
|
||||
language,
|
||||
"123",
|
||||
dbPath,
|
||||
content.length,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
);
|
||||
});
|
||||
|
||||
// Check that our stubs were called and that they received the expected arguments.
|
||||
t.is(getApiClient.callCount, 1);
|
||||
t.is(fetchStub.callCount, 1);
|
||||
|
||||
const args = fetchStub.args[0];
|
||||
t.is(args.length, 2);
|
||||
|
||||
const url = args[0];
|
||||
t.is(
|
||||
url,
|
||||
`https://uploads.github.com/repos/${nwo.owner}/${nwo.repo}/code-scanning/codeql/databases/${language}?name=${language}-database&commit_oid=123`,
|
||||
);
|
||||
|
||||
const options = args[1];
|
||||
t.like(options, {
|
||||
// Going via `new Headers` and `Object.fromEntries` ensures we get the same cases
|
||||
// for the header keys as we are given.
|
||||
headers: Object.fromEntries(
|
||||
new Headers({
|
||||
authorization: `token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||
"Content-Type": "application/zip",
|
||||
"Content-Length": content.length.toString(),
|
||||
}).entries(),
|
||||
),
|
||||
method: "POST",
|
||||
} satisfies RequestInit);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,11 +12,12 @@ import { type CodeQL } from "./codeql";
|
||||
import { Config } from "./config-utils";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import { parseGitHubUrl } from "./github";
|
||||
import { Logger, withGroupAsync } from "./logging";
|
||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||
import { RepositoryNwo } from "./repository";
|
||||
import * as util from "./util";
|
||||
import { asHTTPError, bundleDb, CleanupLevel, parseGitHubUrl } from "./util";
|
||||
import { asHTTPError, bundleDb, CleanupLevel } from "./util";
|
||||
|
||||
/** Information about a database upload. */
|
||||
export interface DatabaseUploadResult {
|
||||
@@ -258,7 +259,7 @@ async function recordClearCleanupSizes(
|
||||
*
|
||||
* @returns the duration of the upload in milliseconds
|
||||
*/
|
||||
async function uploadBundledDatabase(
|
||||
export async function uploadBundledDatabase(
|
||||
repositoryNwo: RepositoryNwo,
|
||||
language: string,
|
||||
commitOid: string,
|
||||
@@ -266,7 +267,10 @@ async function uploadBundledDatabase(
|
||||
bundledDbSize: number,
|
||||
apiDetails: GitHubApiDetails,
|
||||
): Promise<number> {
|
||||
const client = getApiClient();
|
||||
// Ensure that the `apiDetails` that `getApiClient` uses match the ones we were given here,
|
||||
// because we use `apiDetails.auth` below which must be used with the same instance that
|
||||
// `apiDetails` refers to.
|
||||
const client = getApiClient(util.getEnv(), apiDetails);
|
||||
|
||||
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
||||
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
||||
@@ -292,7 +296,6 @@ async function uploadBundledDatabase(
|
||||
commit_oid: commitOid,
|
||||
data: bundledDbReadStream,
|
||||
headers: {
|
||||
authorization: `token ${apiDetails.auth}`,
|
||||
"Content-Type": "application/zip",
|
||||
"Content-Length": bundledDbSize,
|
||||
},
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
exportedForTesting,
|
||||
} from "./diff-informed-analysis-utils";
|
||||
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { parseRepositoryNwo } from "./repository";
|
||||
import {
|
||||
setupTests,
|
||||
@@ -19,6 +18,7 @@ import {
|
||||
mockFeatureFlagApiEndpoint,
|
||||
setupActionsVars,
|
||||
makeMacro,
|
||||
RecordingLogger,
|
||||
} from "./testing-utils";
|
||||
import { GitHubVariant, withTmpDir } from "./util";
|
||||
import type { GitHubVersion } from "./util";
|
||||
@@ -55,7 +55,7 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
|
||||
const testCase = { ...defaultTestCase, ...partialTestCase };
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const codeql = mockCodeQLVersion(testCase.codeQLVersion);
|
||||
|
||||
if (testCase.diffInformedQueriesEnvVar !== undefined) {
|
||||
@@ -182,7 +182,7 @@ test.serial(
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const codeql = mockCodeQLVersion("2.21.0");
|
||||
const features = createFeatures([Feature.DiffInformedQueries]);
|
||||
|
||||
@@ -207,7 +207,7 @@ test.serial(
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const codeql = mockCodeQLVersion("2.21.0");
|
||||
// A features implementation whose getValue rejects, simulating an
|
||||
// unexpected failure when determining whether diff-informed analysis
|
||||
@@ -237,7 +237,7 @@ test.serial(
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const codeql = mockCodeQLVersion("2.21.0");
|
||||
const features = createFeatures([Feature.DiffInformedQueries]);
|
||||
|
||||
@@ -274,7 +274,7 @@ test.serial(
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const codeql = mockCodeQLVersion("2.21.0");
|
||||
const features = createFeatures([Feature.DiffInformedQueries]);
|
||||
|
||||
@@ -313,7 +313,7 @@ function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
|
||||
changes,
|
||||
patch: patch?.join("\n"),
|
||||
},
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,11 +74,6 @@ export enum Feature {
|
||||
AllowMergeConfigFiles = "allow_merge_config_files",
|
||||
/** Controls whether we allow multiple values for the `analysis-kinds` input. */
|
||||
AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds",
|
||||
/**
|
||||
* Controls whether we delete CodeQL bundles that we are not going to use from the toolcache
|
||||
* before downloading a different bundle, in order to reclaim disk space.
|
||||
*/
|
||||
CleanupToolcacheBundles = "cleanup_toolcache_bundles",
|
||||
CleanupTrapCaches = "cleanup_trap_caches",
|
||||
/** Whether to allow the `config-file` input to be specified via a repository property. */
|
||||
ConfigFileRepositoryProperty = "config_file_repository_property",
|
||||
@@ -221,11 +216,6 @@ export const featureConfig = {
|
||||
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.CleanupToolcacheBundles]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.CleanupTrapCaches]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
|
||||
|
||||
@@ -2,7 +2,6 @@ import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import * as api from "../api-client";
|
||||
import { getRunnerLogger } from "../logging";
|
||||
import { parseRepositoryNwo } from "../repository";
|
||||
import { RecordingLogger, setupTests } from "../testing-utils";
|
||||
|
||||
@@ -19,7 +18,7 @@ test.serial(
|
||||
url: "",
|
||||
data: {},
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
await t.throwsAsync(
|
||||
properties.loadPropertiesFromApi(logger, mockRepositoryNwo),
|
||||
@@ -39,7 +38,7 @@ test.serial(
|
||||
url: "",
|
||||
data: [{}],
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
await t.throwsAsync(
|
||||
properties.loadPropertiesFromApi(logger, mockRepositoryNwo),
|
||||
@@ -63,7 +62,7 @@ test.serial(
|
||||
{ property_name: "also-not-used-by-us", value: ["A", "B", "C"] },
|
||||
],
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
await t.notThrowsAsync(
|
||||
properties.loadPropertiesFromApi(logger, mockRepositoryNwo),
|
||||
@@ -86,7 +85,7 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => {
|
||||
{ property_name: "unknown-property", value: "something" },
|
||||
] satisfies properties.GitHubPropertiesResponse,
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
const response = await properties.loadPropertiesFromApi(
|
||||
logger,
|
||||
@@ -113,7 +112,7 @@ test.serial("loadPropertiesFromApi parses true boolean property", async (t) => {
|
||||
{ property_name: "github-codeql-extra-queries", value: "+queries" },
|
||||
] satisfies properties.GitHubPropertiesResponse,
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const warningSpy = sinon.spy(logger, "warning");
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
const response = await properties.loadPropertiesFromApi(
|
||||
@@ -141,7 +140,7 @@ test.serial(
|
||||
},
|
||||
] satisfies properties.GitHubPropertiesResponse,
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const warningSpy = sinon.spy(logger, "warning");
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
const response = await properties.loadPropertiesFromApi(
|
||||
@@ -164,7 +163,7 @@ test.serial(
|
||||
url: "",
|
||||
data: [{ property_name: "github-codeql-extra-queries", value: 123 }],
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
await t.throwsAsync(
|
||||
properties.loadPropertiesFromApi(logger, mockRepositoryNwo),
|
||||
@@ -190,7 +189,7 @@ test.serial(
|
||||
},
|
||||
] satisfies properties.GitHubPropertiesResponse,
|
||||
});
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const warningSpy = sinon.spy(logger, "warning");
|
||||
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
const response = await properties.loadPropertiesFromApi(
|
||||
|
||||
@@ -8,11 +8,12 @@ import {
|
||||
FeatureWithoutCLI,
|
||||
initFeatures,
|
||||
} from "../feature-flags";
|
||||
import { getRunnerLogger } from "../logging";
|
||||
import type { Logger } from "../logging";
|
||||
import { parseRepositoryNwo } from "../repository";
|
||||
import {
|
||||
LoggedMessage,
|
||||
mockCodeQLVersion,
|
||||
RecordingLogger,
|
||||
setupActionsVars,
|
||||
} from "../testing-utils";
|
||||
import { ToolsFeature } from "../tools-features";
|
||||
@@ -51,7 +52,7 @@ export function assertAllFeaturesUndefinedInApi(
|
||||
|
||||
export function setUpFeatureFlagTests(
|
||||
tmpDir: string,
|
||||
logger = getRunnerLogger(true),
|
||||
logger: Logger = new RecordingLogger(),
|
||||
gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion,
|
||||
): FeatureEnablement {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
|
||||
@@ -5,9 +5,8 @@ import * as ava from "ava";
|
||||
import test from "ava";
|
||||
|
||||
import * as fingerprints from "./fingerprints";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import * as sarif from "./sarif";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import { RecordingLogger, setupTests } from "./testing-utils";
|
||||
import * as util from "./util";
|
||||
|
||||
setupTests(test);
|
||||
@@ -131,7 +130,7 @@ function testResolveUriToFile(uri: any, index: any, artifactsURIs: any[]) {
|
||||
location,
|
||||
artifacts,
|
||||
process.cwd(),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -218,7 +217,7 @@ test("addFingerprints", async (t) => {
|
||||
await fingerprints.addFingerprints(
|
||||
input,
|
||||
sourceRoot,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
expected,
|
||||
);
|
||||
@@ -246,7 +245,7 @@ test("missingRegions", async (t) => {
|
||||
await fingerprints.addFingerprints(
|
||||
input,
|
||||
sourceRoot,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
expected,
|
||||
);
|
||||
|
||||
111
src/github.test.ts
Normal file
111
src/github.test.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import test from "ava";
|
||||
|
||||
import { ActionsEnvVars } from "./environment";
|
||||
import * as github from "./github";
|
||||
import { getTestEnv, setupTests } from "./testing-utils";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
test("parseGitHubUrl", (t) => {
|
||||
t.deepEqual(github.parseGitHubUrl("github.com"), "https://github.com");
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.com"),
|
||||
"https://github.com",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://api.github.com"),
|
||||
"https://github.com",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.com/foo/bar"),
|
||||
"https://github.com",
|
||||
);
|
||||
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("github.example.com"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.example.com"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://api.github.example.com"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.example.com/api/v3"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.example.com:1234"),
|
||||
"https://github.example.com:1234/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://api.github.example.com:1234"),
|
||||
"https://github.example.com:1234/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.example.com:1234/api/v3"),
|
||||
"https://github.example.com:1234/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.example.com/base/path"),
|
||||
"https://github.example.com/base/path/",
|
||||
);
|
||||
t.deepEqual(
|
||||
github.parseGitHubUrl("https://github.example.com/base/path/api/v3"),
|
||||
"https://github.example.com/base/path/",
|
||||
);
|
||||
|
||||
t.throws(() => github.parseGitHubUrl(""), {
|
||||
message: '"" is not a valid URL',
|
||||
});
|
||||
t.throws(() => github.parseGitHubUrl("ssh://github.com"), {
|
||||
message: '"ssh://github.com" is not a http or https URL',
|
||||
});
|
||||
t.throws(() => github.parseGitHubUrl("http:///::::433"), {
|
||||
message: '"http:///::::433" is not a valid URL',
|
||||
});
|
||||
});
|
||||
|
||||
test("getCurrentInstance throws if required env vars aren't set", (t) => {
|
||||
t.throws(() => github.getCurrentInstance(getTestEnv()));
|
||||
t.throws(() => {
|
||||
const env = getTestEnv({
|
||||
[ActionsEnvVars.GITHUB_SERVER_URL]: "https://localhost",
|
||||
});
|
||||
github.getCurrentInstance(env);
|
||||
});
|
||||
t.throws(() => {
|
||||
const env = getTestEnv({
|
||||
[ActionsEnvVars.GITHUB_API_URL]: "https://api.localhost",
|
||||
});
|
||||
github.getCurrentInstance(env);
|
||||
});
|
||||
});
|
||||
|
||||
test("getCurrentInstance constructs instance from environment", (t) => {
|
||||
const url = "https://localhost";
|
||||
const apiUrl = "https://api.localhost";
|
||||
|
||||
const env = getTestEnv({
|
||||
[ActionsEnvVars.GITHUB_SERVER_URL]: url,
|
||||
[ActionsEnvVars.GITHUB_API_URL]: apiUrl,
|
||||
});
|
||||
const instance = github.getCurrentInstance(env);
|
||||
|
||||
t.is(instance.url, url);
|
||||
t.is(instance.apiURL, apiUrl);
|
||||
});
|
||||
|
||||
test("getCurrentInstance constructs dotcom instance with dotcom env vars", (t) => {
|
||||
const env = getTestEnv({
|
||||
[ActionsEnvVars.GITHUB_SERVER_URL]: github.GITHUB_DOTCOM_URL,
|
||||
[ActionsEnvVars.GITHUB_API_URL]: github.GITHUB_DOTCOM_API_URL,
|
||||
});
|
||||
const instance = github.getCurrentInstance(env);
|
||||
const dotcomInstance = github.getDotcomInstance();
|
||||
|
||||
t.deepEqual(dotcomInstance, instance);
|
||||
});
|
||||
110
src/github.ts
Normal file
110
src/github.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { ActionsEnvVars, type ReadOnlyEnv } from "./environment";
|
||||
import { ConfigurationError } from "./util";
|
||||
|
||||
/** A string representing a GitHub instance address. */
|
||||
export type InstanceURL = string;
|
||||
|
||||
/**
|
||||
* The URL for github.com.
|
||||
*/
|
||||
export const GITHUB_DOTCOM_URL: InstanceURL = "https://github.com";
|
||||
|
||||
/** A string representing a GitHub API instance address. */
|
||||
export type InstanceApiURL = string;
|
||||
|
||||
/**
|
||||
* The URL for api.github.com.
|
||||
*/
|
||||
export const GITHUB_DOTCOM_API_URL: InstanceApiURL = "https://api.github.com";
|
||||
|
||||
/**
|
||||
* Represents information about a GitHub instance, how to authenticate to it,
|
||||
* and how to authenticate to other repos on it.
|
||||
*/
|
||||
export type GitHubApiCombinedDetails = GitHubApiDetails &
|
||||
GitHubApiExternalRepoDetails;
|
||||
|
||||
/** Represents information about a GitHub instance. */
|
||||
export type GitHubInstance = {
|
||||
/** The base URL of the GitHub instance, such as `https://github.com`. */
|
||||
url: string;
|
||||
/**
|
||||
* The API base URL of the GitHub instance, such as `https://api.github.com`.
|
||||
* Typically this is the `api.` subdomain of the `url` domain.
|
||||
*/
|
||||
apiURL: string | undefined;
|
||||
};
|
||||
|
||||
/** Represents a {@link GitHubInstance} with a token for accessing the API. */
|
||||
export type GitHubApiDetails = GitHubInstance & {
|
||||
/** The token to use for accessing the API of the GitHub instance. */
|
||||
auth?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents information for accessing a repository on the same GitHub instance as the Action
|
||||
* is currently running on.
|
||||
*/
|
||||
export type GitHubApiExternalRepoDetails = {
|
||||
/** An optional token for accessing repo(s) on the same GitHub instance. */
|
||||
externalRepoAuth?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses user input of a github.com or GHES URL to a canonical form.
|
||||
* Removes any API prefix or suffix if one is present.
|
||||
*/
|
||||
export function parseGitHubUrl(inputUrl: string): string {
|
||||
const originalUrl = inputUrl;
|
||||
if (inputUrl.indexOf("://") === -1) {
|
||||
inputUrl = `https://${inputUrl}`;
|
||||
}
|
||||
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
||||
}
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(inputUrl);
|
||||
} catch {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
||||
}
|
||||
|
||||
// If we detect this is trying to be to github.com
|
||||
// then return with a fixed canonical URL.
|
||||
if (url.hostname === "github.com" || url.hostname === "api.github.com") {
|
||||
return GITHUB_DOTCOM_URL;
|
||||
}
|
||||
|
||||
// Remove the API prefix if it's present
|
||||
if (url.pathname.indexOf("/api/v3") !== -1) {
|
||||
url.pathname = url.pathname.substring(0, url.pathname.indexOf("/api/v3"));
|
||||
}
|
||||
// Also consider subdomain isolation on GHES
|
||||
if (url.hostname.startsWith("api.")) {
|
||||
url.hostname = url.hostname.substring(4);
|
||||
}
|
||||
|
||||
// Normalise path to having a trailing slash for consistency
|
||||
if (!url.pathname.endsWith("/")) {
|
||||
url.pathname = `${url.pathname}/`;
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
/** Retrieves a {@link GitHubInstance} describing the instance we are running on. */
|
||||
export function getCurrentInstance(env: ReadOnlyEnv): GitHubInstance {
|
||||
return {
|
||||
url: env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
||||
apiURL: env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
||||
};
|
||||
}
|
||||
|
||||
/** Retrieves a {@link GitHubInstance} describing the GitHub.com instance. */
|
||||
export function getDotcomInstance(): GitHubInstance {
|
||||
return {
|
||||
url: GITHUB_DOTCOM_URL,
|
||||
apiURL: GITHUB_DOTCOM_API_URL,
|
||||
};
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import * as debugArtifacts from "./debug-artifacts";
|
||||
import { EnvVar } from "./environment";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as initActionPostHelper from "./init-action-post-helper";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||
import * as overlayStatus from "./overlay/status";
|
||||
import { parseRepositoryNwo } from "./repository";
|
||||
@@ -20,6 +19,7 @@ import {
|
||||
createFeatures,
|
||||
createTestConfig,
|
||||
DEFAULT_ACTIONS_VARS,
|
||||
getCodeQLForTesting,
|
||||
getTestEnv,
|
||||
makeMacro,
|
||||
makeVersionInfo,
|
||||
@@ -62,7 +62,7 @@ test.serial("init-post action with debug mode off", async (t) => {
|
||||
createFeatures([]),
|
||||
"success",
|
||||
getTestEnv(),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(uploadAllAvailableDebugArtifactsSpy.notCalled);
|
||||
@@ -86,7 +86,7 @@ test.serial("init-post action with debug mode on", async (t) => {
|
||||
createFeatures([]),
|
||||
"success",
|
||||
getTestEnv(),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(uploadAllAvailableDebugArtifactsSpy.called);
|
||||
@@ -383,7 +383,7 @@ test.serial(
|
||||
createFeatures([Feature.OverlayAnalysisStatusSave]),
|
||||
"success",
|
||||
getTestEnv(),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.true(
|
||||
@@ -453,7 +453,7 @@ test.serial(
|
||||
createFeatures([]),
|
||||
"success",
|
||||
getTestEnv(),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.true(
|
||||
@@ -497,7 +497,7 @@ test.serial("does not save overlay status when build successful", async (t) => {
|
||||
createFeatures([Feature.OverlayAnalysisStatusSave]),
|
||||
"success",
|
||||
env,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.true(
|
||||
@@ -536,7 +536,7 @@ test.serial(
|
||||
createFeatures([]),
|
||||
"success",
|
||||
getTestEnv(),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.true(
|
||||
@@ -589,7 +589,7 @@ async function runOverlayPostStep({
|
||||
createFeatures([Feature.OverlayAnalysisStatusSave]),
|
||||
jobStatus,
|
||||
env,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
return { saveOverlayStatusStub };
|
||||
@@ -737,7 +737,7 @@ async function testFailedSarifUpload(
|
||||
.withArgs("matrix")
|
||||
.returns(JSON.stringify(matrix));
|
||||
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
const codeqlObject = await getCodeQLForTesting();
|
||||
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
||||
const databaseExportDiagnosticsStub = sinon.stub(
|
||||
@@ -764,7 +764,7 @@ async function testFailedSarifUpload(
|
||||
config,
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures(features),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
if (expectUpload) {
|
||||
t.deepEqual(result, {
|
||||
@@ -832,7 +832,7 @@ async function mockRiskAssessmentEnv(matrix: string) {
|
||||
.stub(apiClient, "getGitHubVersion")
|
||||
.resolves({ type: util.GitHubVariant.GHES, version: "3.0.0" });
|
||||
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
const codeqlObject = await getCodeQLForTesting();
|
||||
const databaseExportDiagnostics = sinon
|
||||
.stub(codeqlObject, "databaseExportDiagnostics")
|
||||
.resolves();
|
||||
|
||||
@@ -50,6 +50,7 @@ import {
|
||||
loadRepositoryProperties,
|
||||
RepositoryPropertyName,
|
||||
} from "./feature-flags/properties";
|
||||
import * as github from "./github";
|
||||
import {
|
||||
checkInstallPython311,
|
||||
checkPacksForOverlayCompatibility,
|
||||
@@ -233,8 +234,7 @@ async function run(
|
||||
apiDetails = {
|
||||
auth: getRequiredInput("token"),
|
||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||
url: actionState.env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
||||
apiURL: actionState.env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
||||
...github.getCurrentInstance(actionState.env),
|
||||
};
|
||||
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
|
||||
17
src/logging.test.ts
Normal file
17
src/logging.test.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import test from "ava";
|
||||
|
||||
import { joinMessageStrings } from "./logging";
|
||||
import { setupTests } from "./testing-utils";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
test("joinMessageStrings", async (t) => {
|
||||
// For strings and errors, it is the identity function.
|
||||
t.deepEqual(joinMessageStrings("Hello"), "Hello");
|
||||
|
||||
const error = new Error("Some error");
|
||||
t.deepEqual(joinMessageStrings(error), error);
|
||||
|
||||
// For arrays of strings, we get a join-ed string.
|
||||
t.deepEqual(joinMessageStrings(["foo", "bar"]), "foo bar");
|
||||
});
|
||||
@@ -1,45 +1,92 @@
|
||||
import * as core from "@actions/core";
|
||||
|
||||
export interface Logger {
|
||||
debug: (message: string) => void;
|
||||
info: (message: string) => void;
|
||||
warning: (message: string | Error) => void;
|
||||
error: (message: string | Error) => void;
|
||||
/** Types that all of our logging functions accept. */
|
||||
export type Loggable = string | string[];
|
||||
|
||||
/** Some logging functions also accept errors directly. */
|
||||
export type LoggableError = Loggable | Error;
|
||||
|
||||
export interface Logger {
|
||||
/**
|
||||
* Logs {@link message} at debug-level.
|
||||
* In Actions, this will only be output if workflow debugging is enabled.
|
||||
*
|
||||
* @param message
|
||||
* A string or an array of strings. If an array of strings is provided, they are joined using
|
||||
* space as the delimiter and printed as a single line.
|
||||
*/
|
||||
debug: (message: Loggable) => void;
|
||||
/**
|
||||
* Logs {@link message} at info-level.
|
||||
* In Actions, this will always be output.
|
||||
*
|
||||
* @param message
|
||||
* A string or an array of strings. If an array of strings is provided, they are joined using
|
||||
* space as the delimiter and printed as a single line.
|
||||
*/
|
||||
info: (message: Loggable) => void;
|
||||
/**
|
||||
* Logs {@link message} at warning-level.
|
||||
* In Actions, this will always be output and highlighted as a warning. It will additionally
|
||||
* result in a warning-level workflow annotation.
|
||||
*
|
||||
* @param message
|
||||
* A string or an array of strings. If an array of strings is provided, they are joined using
|
||||
* space as the delimiter and printed as a single line.
|
||||
*/
|
||||
warning: (message: LoggableError) => void;
|
||||
/**
|
||||
* Logs {@link message} at error-level.
|
||||
* In Actions, this will always be output and highlighted as an error. It will additionally
|
||||
* result in an error-level workflow annotation.
|
||||
*
|
||||
* @param message
|
||||
* A string or an array of strings. If an array of strings is provided, they are joined using
|
||||
* space as the delimiter and printed as a single line.
|
||||
*/
|
||||
error: (message: LoggableError) => void;
|
||||
/**
|
||||
* Gets a value indicating whether debugging is enabled.
|
||||
*/
|
||||
isDebug: () => boolean;
|
||||
|
||||
startGroup: (name: string) => void;
|
||||
endGroup: () => void;
|
||||
}
|
||||
|
||||
/** If `message` is an array of strings, the array is `join`-ed into one string separated by spaces. */
|
||||
export const joinMessageStrings = <T>(
|
||||
message: string[] | string | T,
|
||||
): string | T => {
|
||||
if (Array.isArray(message)) {
|
||||
return message.join(" ");
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps a logging function so that `joinMessageStrings` is applied to the input before
|
||||
* calling the wrapped logging function.
|
||||
*/
|
||||
const autoJoinMessageStrings = <T>(fn: (msg: string | T) => void) => {
|
||||
return (message: string[] | string | T) => {
|
||||
return fn(joinMessageStrings(message));
|
||||
};
|
||||
};
|
||||
|
||||
export function getActionsLogger(): Logger {
|
||||
return {
|
||||
debug: core.debug,
|
||||
info: core.info,
|
||||
warning: core.warning,
|
||||
error: core.error,
|
||||
debug: autoJoinMessageStrings(core.debug),
|
||||
info: autoJoinMessageStrings(core.info),
|
||||
warning: autoJoinMessageStrings(core.warning),
|
||||
error: autoJoinMessageStrings(core.error),
|
||||
isDebug: core.isDebug,
|
||||
startGroup: core.startGroup,
|
||||
endGroup: core.endGroup,
|
||||
};
|
||||
}
|
||||
|
||||
export function getRunnerLogger(debugMode: boolean): Logger {
|
||||
return {
|
||||
// eslint-disable-next-line no-console
|
||||
debug: debugMode ? console.debug : () => undefined,
|
||||
// eslint-disable-next-line no-console
|
||||
info: console.info,
|
||||
// eslint-disable-next-line no-console
|
||||
warning: console.warn,
|
||||
// eslint-disable-next-line no-console
|
||||
error: console.error,
|
||||
isDebug: () => debugMode,
|
||||
startGroup: () => undefined,
|
||||
endGroup: () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function withGroup<T>(groupName: string, f: () => T): T {
|
||||
core.startGroup(groupName);
|
||||
try {
|
||||
|
||||
@@ -11,11 +11,11 @@ import type { ResolveDatabaseOutput } from "../codeql";
|
||||
import * as environment from "../environment";
|
||||
import * as gitUtils from "../git-utils";
|
||||
import { BuiltInLanguage } from "../languages";
|
||||
import { getRunnerLogger } from "../logging";
|
||||
import {
|
||||
createTestConfig,
|
||||
makeMacro,
|
||||
mockCodeQLVersion,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "../testing-utils";
|
||||
import * as utils from "../util";
|
||||
@@ -63,7 +63,7 @@ const testDownloadOverlayBaseDatabaseFromCache = makeMacro({
|
||||
const dbLocation = path.join(tmpDir, "db");
|
||||
await fs.promises.mkdir(dbLocation, { recursive: true });
|
||||
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const testCase = { ...defaultDownloadTestCase, ...partialTestCase };
|
||||
const config = createTestConfig({
|
||||
dbLocation,
|
||||
@@ -214,7 +214,7 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
|
||||
);
|
||||
|
||||
test.serial("overlay-base database cache keys remain stable", async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const config = createTestConfig({ languages: ["python", "javascript"] });
|
||||
const codeQlVersion = "2.23.0";
|
||||
const commitOid = "abc123def456";
|
||||
@@ -261,7 +261,7 @@ test.serial("overlay-base database cache keys remain stable", async (t) => {
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases returns unique versions sorted latest first",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
sinon.stub(apiClient, "listActionsCaches").resolves([
|
||||
@@ -287,7 +287,7 @@ test.serial(
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases returns empty list when no caches exist",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
sinon.stub(apiClient, "listActionsCaches").resolves([]);
|
||||
@@ -303,7 +303,7 @@ test.serial(
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases returns empty list when cache keys are unparseable",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
sinon.stub(apiClient, "listActionsCaches").resolves([
|
||||
@@ -324,7 +324,7 @@ test.serial(
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases returns the single version when only one cache exists",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
sinon.stub(apiClient, "listActionsCaches").resolves([
|
||||
@@ -344,7 +344,7 @@ test.serial(
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases resolves language aliases",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
// The alias `c++` should be resolved to "cpp" and match cache entries keyed with "cpp"
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
@@ -365,7 +365,7 @@ test.serial(
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases de-duplicates resolved language aliases",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
const listActionsCachesStub = sinon
|
||||
@@ -391,7 +391,7 @@ test.serial(
|
||||
test.serial(
|
||||
"getCodeQlVersionsForOverlayBaseDatabases ignores nightly versions with build metadata",
|
||||
async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
|
||||
sinon.stub(apiClient, "listActionsCaches").resolves([
|
||||
|
||||
@@ -6,8 +6,11 @@ import * as sinon from "sinon";
|
||||
|
||||
import * as actionsUtil from "../actions-util";
|
||||
import * as gitUtils from "../git-utils";
|
||||
import { getRunnerLogger } from "../logging";
|
||||
import { createTestConfig, setupTests } from "../testing-utils";
|
||||
import {
|
||||
createTestConfig,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "../testing-utils";
|
||||
import { withTmpDir } from "../util";
|
||||
|
||||
import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from ".";
|
||||
@@ -27,7 +30,7 @@ test.serial(
|
||||
),
|
||||
);
|
||||
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const config = createTestConfig({ dbLocation });
|
||||
|
||||
// Mock the getFileOidsUnderPath function to return base OIDs
|
||||
@@ -91,7 +94,7 @@ test.serial(
|
||||
),
|
||||
);
|
||||
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const config = createTestConfig({ dbLocation });
|
||||
|
||||
// Mock the getFileOidsUnderPath function to return base OIDs
|
||||
@@ -169,7 +172,7 @@ test.serial(
|
||||
),
|
||||
);
|
||||
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const config = createTestConfig({ dbLocation });
|
||||
|
||||
// Mock the getFileOidsUnderPath function to return base OIDs
|
||||
@@ -232,7 +235,7 @@ test.serial(
|
||||
),
|
||||
);
|
||||
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const config = createTestConfig({ dbLocation });
|
||||
|
||||
// Base OIDs (sourceRoot-relative paths)
|
||||
|
||||
@@ -17,9 +17,10 @@ import { getGitHubVersion } from "./api-client";
|
||||
import { CodeQL } from "./codeql";
|
||||
import { ComputedInput, getToolsInput } from "./config/inputs";
|
||||
import { getRawLanguagesNoAutodetect } from "./config-utils";
|
||||
import { ActionsEnvVars, EnvVar } from "./environment";
|
||||
import { EnvVar } from "./environment";
|
||||
import { initFeatures } from "./feature-flags";
|
||||
import { loadRepositoryProperties } from "./feature-flags/properties";
|
||||
import * as github from "./github";
|
||||
import { initCodeQL } from "./init";
|
||||
import { Logger } from "./logging";
|
||||
import { getRepositoryNwo } from "./repository";
|
||||
@@ -112,8 +113,7 @@ async function run(
|
||||
const apiDetails = {
|
||||
auth: getRequiredInput("token"),
|
||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||
url: actionState.env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
||||
apiURL: actionState.env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
||||
...github.getCurrentInstance(actionState.env),
|
||||
};
|
||||
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
|
||||
@@ -14,7 +14,6 @@ import * as diagnostics from "./diagnostics";
|
||||
import { ActionsEnvVars, Env, EnvVar, ReadOnlyEnv } from "./environment";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
|
||||
import { MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION } from "./per-language-bundles";
|
||||
import * as setupCodeql from "./setup-codeql";
|
||||
@@ -22,6 +21,7 @@ import * as tar from "./tar";
|
||||
import {
|
||||
LINKED_CLI_VERSION,
|
||||
LoggedMessage,
|
||||
RecordingLogger,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
checkExpectedLogMessages,
|
||||
@@ -117,7 +117,7 @@ test.serial("convert to semver", (t) => {
|
||||
try {
|
||||
const parsedVersion = setupCodeql.convertToSemVer(
|
||||
version,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(parsedVersion, expectedVersion);
|
||||
} catch (e) {
|
||||
@@ -145,7 +145,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
false,
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.deepEqual(source, {
|
||||
@@ -231,7 +231,7 @@ for (const {
|
||||
GitHubVariant.DOTCOM,
|
||||
tarSupportsZstd,
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(source.toolsVersion, LINKED_CLI_VERSION.cliVersion);
|
||||
@@ -596,8 +596,8 @@ test.serial(
|
||||
undefined, // rawLanguages
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.CleanupToolcacheBundles]),
|
||||
getRunnerLogger(true),
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(result.toolsVersion, "local");
|
||||
@@ -634,7 +634,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.deepEqual(source, {
|
||||
@@ -694,7 +694,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
@@ -733,7 +733,7 @@ for (const perLanguageBundles of [false, true]) {
|
||||
? [Feature.ForceNightly, Feature.PerLanguageBundles]
|
||||
: [Feature.ForceNightly],
|
||||
),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
@@ -848,7 +848,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
true,
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
{
|
||||
message:
|
||||
@@ -1020,7 +1020,7 @@ test.serial(
|
||||
t.is(
|
||||
setupCodeql.tryGetTagNameFromUrl(
|
||||
"https://github.com/org/codeql-bundle-testing/releases/download/codeql-bundle-v2.19.0/codeql-bundle-linux64.tar.zst",
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
"codeql-bundle-v2.19.0",
|
||||
);
|
||||
@@ -1032,7 +1032,7 @@ test.serial(
|
||||
(t) => {
|
||||
sinon.stub(toolcache, "findAllVersions").returns([]);
|
||||
t.is(
|
||||
setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)),
|
||||
setupCodeql.getLatestToolcacheVersion(new RecordingLogger()),
|
||||
undefined,
|
||||
);
|
||||
},
|
||||
@@ -1044,7 +1044,7 @@ test.serial(
|
||||
const testVersions = ["2.3.1", "3.2.1", "1.2.3"];
|
||||
sinon.stub(toolcache, "findAllVersions").returns(testVersions);
|
||||
|
||||
t.is(setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), "3.2.1");
|
||||
t.is(setupCodeql.getLatestToolcacheVersion(new RecordingLogger()), "3.2.1");
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1098,7 +1098,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
false,
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(listStub.calledOnce);
|
||||
@@ -1137,7 +1137,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
false,
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(listStub.notCalled);
|
||||
@@ -1175,7 +1175,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
@@ -1226,7 +1226,7 @@ test.serial(
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
@@ -1296,7 +1296,7 @@ for (const fallback of [false, true]) {
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.true(fetchRelease.calledTwice);
|
||||
@@ -1375,10 +1375,7 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) {
|
||||
};
|
||||
});
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
||||
const features = createFeatures([
|
||||
Feature.PerLanguageBundles,
|
||||
Feature.CleanupToolcacheBundles,
|
||||
]);
|
||||
const features = createFeatures([Feature.PerLanguageBundles]);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
@@ -1564,7 +1561,7 @@ for (const error of [
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
{ is: error },
|
||||
);
|
||||
@@ -1600,7 +1597,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
{ is: error },
|
||||
);
|
||||
@@ -1633,7 +1630,7 @@ test.serial(
|
||||
overlayMatchEnabledVersions,
|
||||
["javascript"],
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, [
|
||||
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
|
||||
@@ -1656,7 +1653,7 @@ test.serial(
|
||||
overlayMatchEnabledVersions,
|
||||
["javascript"],
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, []);
|
||||
},
|
||||
@@ -1673,7 +1670,7 @@ const noLanguagesMacro = makeMacro({
|
||||
overlayMatchEnabledVersions,
|
||||
rawLanguages,
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, []);
|
||||
t.assert(
|
||||
@@ -1698,7 +1695,7 @@ test.serial(
|
||||
overlayMatchEnabledVersions,
|
||||
["javascript"],
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, []);
|
||||
},
|
||||
@@ -1718,7 +1715,7 @@ test.serial(
|
||||
overlayMatchEnabledVersions,
|
||||
["javascript"],
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, [
|
||||
{ cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" },
|
||||
@@ -1735,7 +1732,7 @@ test.serial(
|
||||
overlayMatchEnabledVersions,
|
||||
["javascript"],
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, []);
|
||||
t.assert(
|
||||
@@ -1759,7 +1756,7 @@ test.serial(
|
||||
overlayMatchEnabledVersions,
|
||||
["javascript"],
|
||||
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(
|
||||
result,
|
||||
@@ -1790,7 +1787,7 @@ test.serial(
|
||||
Feature.OverlayAnalysisMatchCodeqlVersion,
|
||||
Feature.OverlayAnalysisMatchCodeqlVersionDryRun,
|
||||
]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
t.deepEqual(result, [
|
||||
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
|
||||
@@ -1826,11 +1823,15 @@ function createToolcacheEntry(
|
||||
*/
|
||||
async function runDownloadCodeQL(
|
||||
toolcacheRoot: string,
|
||||
features: Feature[],
|
||||
bundleVersion: string | undefined,
|
||||
env = getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: toolcacheRoot,
|
||||
}),
|
||||
{
|
||||
env = getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted",
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: toolcacheRoot,
|
||||
}),
|
||||
}: {
|
||||
env?: Env;
|
||||
} = {},
|
||||
): Promise<{
|
||||
codeqlFolder: string;
|
||||
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
||||
@@ -1841,7 +1842,6 @@ async function runDownloadCodeQL(
|
||||
const { codeqlFolder } = await setupCodeql.downloadCodeQLBundle(
|
||||
initAllState({
|
||||
env,
|
||||
features: createFeatures(features),
|
||||
}),
|
||||
{
|
||||
bundle: {
|
||||
@@ -1879,11 +1879,9 @@ async function runDownloadCodeQL(
|
||||
async function testToolcacheCleanup(
|
||||
t: ExecutionContext<unknown>,
|
||||
{
|
||||
features,
|
||||
runnerEnvironment,
|
||||
setUp,
|
||||
}: {
|
||||
features: Feature[];
|
||||
runnerEnvironment: string | undefined;
|
||||
setUp?: (env: Env) => void;
|
||||
},
|
||||
@@ -1895,12 +1893,8 @@ async function testToolcacheCleanup(
|
||||
) {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
if (runnerEnvironment === undefined) {
|
||||
delete process.env[ActionsEnvVars.RUNNER_ENVIRONMENT];
|
||||
} else {
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = runnerEnvironment;
|
||||
}
|
||||
const env = getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: runnerEnvironment,
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: tmpDir,
|
||||
});
|
||||
setUp?.(env);
|
||||
@@ -1920,9 +1914,8 @@ async function testToolcacheCleanup(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
features,
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
env,
|
||||
{ env },
|
||||
);
|
||||
|
||||
t.true(
|
||||
@@ -1934,28 +1927,12 @@ async function testToolcacheCleanup(
|
||||
});
|
||||
}
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle does not clean up the toolcache when the feature flag is disabled",
|
||||
async (t) => {
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{ features: [], runnerEnvironment: "github-hosted" },
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
t.true(fs.existsSync(staleDirectory));
|
||||
t.true(fs.existsSync(destinationDirectory));
|
||||
t.is(cleanupDiagnostic, undefined);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle does not clean up the toolcache when the runner is not GitHub-hosted",
|
||||
async (t) => {
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: "self-hosted",
|
||||
},
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
@@ -1975,7 +1952,6 @@ test.serial(
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: undefined,
|
||||
},
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
@@ -1988,12 +1964,11 @@ test.serial(
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle deletes other CodeQL bundles from the toolcache when enabled on a GitHub-hosted runner",
|
||||
"downloadCodeQLBundle deletes other CodeQL bundles from the toolcache on a GitHub-hosted runner",
|
||||
async (t) => {
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: "github-hosted",
|
||||
},
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
@@ -2027,7 +2002,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2057,7 +2031,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2120,7 +2093,7 @@ test.serial(
|
||||
env: new ReadOnlyEnv({
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: injectedRoot,
|
||||
}),
|
||||
logger: getRunnerLogger(true),
|
||||
logger: new RecordingLogger(),
|
||||
});
|
||||
|
||||
t.deepEqual(result, {
|
||||
@@ -2189,7 +2162,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
toolcacheRoot,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2212,7 +2184,6 @@ test.serial(
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: "github-hosted",
|
||||
setUp: (env) => {
|
||||
env.set(EnvVar.HAS_SET_UP_CODEQL, "true");
|
||||
@@ -2242,9 +2213,13 @@ test.serial(
|
||||
);
|
||||
const { codeqlFolder, cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
getTestEnv({ [EnvVar.HAS_SET_UP_CODEQL]: "true" }),
|
||||
{
|
||||
env: getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted",
|
||||
[EnvVar.HAS_SET_UP_CODEQL]: "true",
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
t.true(fs.existsSync(staleDirectory));
|
||||
@@ -2273,7 +2248,7 @@ test.serial(
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(
|
||||
@@ -2312,8 +2287,8 @@ test.serial(
|
||||
undefined, // rawLanguages
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.CleanupToolcacheBundles]),
|
||||
getRunnerLogger(true),
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
{ is: error },
|
||||
);
|
||||
@@ -2347,7 +2322,6 @@ test.serial(
|
||||
|
||||
const { codeqlFolder, cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
undefined, // bundleVersion
|
||||
);
|
||||
|
||||
@@ -2381,7 +2355,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2417,7 +2390,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2431,7 +2403,7 @@ test.serial(
|
||||
"isToolcacheOnWorkspaceFilesystem assumes a different filesystem when it cannot tell",
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
t.true(toolsDownload.isToolcacheOnWorkspaceFilesystem(logger));
|
||||
@@ -2467,7 +2439,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
toolcacheRoot,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
|
||||
@@ -839,7 +839,7 @@ function getToolcacheDestination(
|
||||
}
|
||||
|
||||
/**
|
||||
* Reclaims disk space by deleting the CodeQL tools from the toolcache, if enabled.
|
||||
* Reclaims disk space by deleting the CodeQL tools from the toolcache on GitHub-hosted runners.
|
||||
*
|
||||
* On GitHub-hosted runners the toolcache shares a filesystem with the workspace, so tools left in
|
||||
* the toolcache take up space that the analysis could use instead. This holds wherever we extract
|
||||
@@ -847,9 +847,8 @@ function getToolcacheDestination(
|
||||
*/
|
||||
async function tryDeleteToolcacheBundles({
|
||||
env,
|
||||
features,
|
||||
logger,
|
||||
}: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>): Promise<void> {
|
||||
}: ActionState<["Logger", "ReadOnlyEnv"]>): Promise<void> {
|
||||
// A step that has already set up CodeQL may hand out a path into the toolcache that a later step
|
||||
// runs, so only the first step to set it up can know that nothing else relies on the toolcache.
|
||||
if (env.getOptional(EnvVar.HAS_SET_UP_CODEQL) !== undefined) {
|
||||
@@ -860,11 +859,7 @@ async function tryDeleteToolcacheBundles({
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!isGitHubHostedRunner() ||
|
||||
!isToolcacheOnWorkspaceFilesystem(logger) ||
|
||||
!(await features.getValue(Feature.CleanupToolcacheBundles))
|
||||
) {
|
||||
if (!isGitHubHostedRunner(env) || !isToolcacheOnWorkspaceFilesystem(logger)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -983,7 +978,7 @@ export async function setupCodeQLBundle(
|
||||
break;
|
||||
case "download": {
|
||||
const result = await downloadCodeQLBundle(
|
||||
{ env: getEnv(), features, logger },
|
||||
{ env: getEnv(), logger },
|
||||
source,
|
||||
apiDetails,
|
||||
zstdAvailability.version,
|
||||
@@ -1019,7 +1014,7 @@ export async function setupCodeQLBundle(
|
||||
* @returns The extraction directory and download timings.
|
||||
*/
|
||||
export async function downloadCodeQLBundle(
|
||||
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
|
||||
action: ActionState<["Logger", "ReadOnlyEnv"]>,
|
||||
source: CodeQLDownloadSource,
|
||||
apiDetails: api.GitHubApiDetails,
|
||||
tarVersion: tar.TarVersion | undefined,
|
||||
|
||||
@@ -2,12 +2,13 @@ import { ActionState } from "../action-common";
|
||||
import { isRunningLocalAction } from "../actions-util";
|
||||
import * as api from "../api-client";
|
||||
import { ActionsEnvVars } from "../environment";
|
||||
import { GITHUB_DOTCOM_URL } from "../github";
|
||||
import {
|
||||
isRepositoryNwoStr,
|
||||
parseRepositoryNwo,
|
||||
type RepositoryNwoStr,
|
||||
} from "../repository";
|
||||
import { GITHUB_DOTCOM_URL, type InstanceURL } from "../util";
|
||||
import { type InstanceURL } from "../util";
|
||||
|
||||
/** The NWO of the standard CodeQL Action repository. */
|
||||
export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
||||
|
||||
@@ -13,7 +13,7 @@ import { setUpFeatureFlagTests } from "./feature-flags/testing-util";
|
||||
import { UnvalidatedObject, validateSchema } from "./json";
|
||||
import { makeFromSchema } from "./json/testing-util";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger, Logger } from "./logging";
|
||||
import { Logger } from "./logging";
|
||||
import { BundlePlatform, getBundlePlatform } from "./platform";
|
||||
import * as repository from "./setup/repository";
|
||||
import * as startProxyExports from "./start-proxy";
|
||||
@@ -67,7 +67,7 @@ test("getCredentials prefers registriesCredentials over registrySecrets", async
|
||||
]);
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
registrySecrets,
|
||||
registryCredentials,
|
||||
undefined,
|
||||
@@ -84,7 +84,7 @@ test("getCredentials throws an error when configurations are not an array", asyn
|
||||
t.throws(
|
||||
() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
registryCredentials,
|
||||
undefined,
|
||||
@@ -103,7 +103,7 @@ test("getCredentials throws error when credential is not an object", async (t) =
|
||||
t.throws(
|
||||
() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
testCredential,
|
||||
undefined,
|
||||
@@ -124,7 +124,7 @@ test("getCredentials throws error when credential is missing type", async (t) =>
|
||||
t.throws(
|
||||
() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
testCredential,
|
||||
undefined,
|
||||
@@ -147,7 +147,7 @@ test("getCredentials throws error when credential missing host and url", async (
|
||||
t.throws(
|
||||
() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
testCredential,
|
||||
undefined,
|
||||
@@ -161,7 +161,7 @@ test("getCredentials throws error when credential missing host and url", async (
|
||||
|
||||
test("getCredentials filters by language when specified", async (t) => {
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON(mixedCredentials),
|
||||
BuiltInLanguage.java,
|
||||
@@ -172,7 +172,7 @@ test("getCredentials filters by language when specified", async (t) => {
|
||||
|
||||
test("getCredentials returns all for a language when specified", async (t) => {
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON([...mixedCredentials, gitSourceCredential]),
|
||||
BuiltInLanguage.go,
|
||||
@@ -192,7 +192,7 @@ test("getCredentials returns all goproxy_servers for Go when specified", async (
|
||||
];
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON(multipleGoproxyServers),
|
||||
BuiltInLanguage.go,
|
||||
@@ -221,7 +221,7 @@ test("getCredentials returns all maven_repositories for Java when specified", as
|
||||
];
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON(multipleMavenRepositories),
|
||||
BuiltInLanguage.java,
|
||||
@@ -239,7 +239,7 @@ test("getCredentials returns all credentials when no language specified", async
|
||||
const credentialsInput = toEncodedJSON(mixedCredentials);
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
credentialsInput,
|
||||
undefined,
|
||||
@@ -269,7 +269,7 @@ test("getCredentials throws an error when non-printable characters are used", as
|
||||
t.throws(
|
||||
() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
credentialsInput,
|
||||
undefined,
|
||||
@@ -300,7 +300,7 @@ for (const oidcSchemaInfo of startProxyExports.oidcSchemas) {
|
||||
t.throws(
|
||||
() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
credentialsInput,
|
||||
undefined,
|
||||
@@ -324,7 +324,7 @@ test("getCredentials accepts OIDC configurations", (t) => {
|
||||
);
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON(oidcConfigurations),
|
||||
BuiltInLanguage.csharp,
|
||||
@@ -514,7 +514,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => {
|
||||
]);
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
credentialsInput,
|
||||
BuiltInLanguage.java,
|
||||
@@ -533,7 +533,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => {
|
||||
};
|
||||
t.throws(() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON([{ ...baseInvalid, "replaces-base": null }]),
|
||||
BuiltInLanguage.java,
|
||||
@@ -541,7 +541,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => {
|
||||
);
|
||||
t.throws(() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON([{ ...baseInvalid, "replaces-base": 123 }]),
|
||||
BuiltInLanguage.java,
|
||||
@@ -549,7 +549,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => {
|
||||
);
|
||||
t.throws(() =>
|
||||
startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
toEncodedJSON([{ ...baseInvalid, "replaces-base": "true" }]),
|
||||
BuiltInLanguage.java,
|
||||
@@ -565,7 +565,7 @@ test("getCredentials returns only ALWAYS_ENABLED_REGISTRY_TYPE credentials for A
|
||||
]);
|
||||
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
credentialsInput,
|
||||
BuiltInLanguage.actions,
|
||||
@@ -597,7 +597,7 @@ test("getCredentials always returns ALWAYS_ENABLED_REGISTRY_TYPE credentials for
|
||||
// Test all languages.
|
||||
for (const language of Object.values(BuiltInLanguage)) {
|
||||
const credentials = startProxyExports.getCredentials(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
undefined,
|
||||
credentialsInput,
|
||||
language,
|
||||
|
||||
@@ -6,7 +6,6 @@ import * as actionsUtil from "./actions-util";
|
||||
import { Config } from "./config-utils";
|
||||
import { EnvVar, RegistryProxyVars } from "./environment";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { ToolsSource } from "./setup-codeql";
|
||||
import type { Registry } from "./start-proxy";
|
||||
import {
|
||||
@@ -154,7 +153,7 @@ test.serial("createStatusReportBase", async (t) => {
|
||||
languages: [BuiltInLanguage.java, BuiltInLanguage.swift],
|
||||
}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
);
|
||||
@@ -203,7 +202,7 @@ test.serial("createStatusReportBase - empty configuration", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
{},
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
if (t.truthy(statusReport)) {
|
||||
@@ -225,7 +224,7 @@ test.serial("createStatusReportBase - partial configuration", async (t) => {
|
||||
languages: ["go"],
|
||||
},
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
if (t.truthy(statusReport)) {
|
||||
@@ -248,7 +247,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
createTestConfig({}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
)
|
||||
@@ -264,7 +263,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
createTestConfig({}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
)
|
||||
@@ -281,7 +280,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
createTestConfig({}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
)
|
||||
@@ -297,7 +296,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
createTestConfig({}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
)
|
||||
@@ -314,7 +313,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
createTestConfig({}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
)
|
||||
@@ -330,7 +329,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => {
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
createTestConfig({}),
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
)
|
||||
@@ -411,7 +410,7 @@ const testCreateInitWithConfigStatusReport = makeMacro({
|
||||
new Date("May 19, 2023 05:19:00"),
|
||||
config,
|
||||
{ numAvailableBytes: 100, numTotalBytes: 500 },
|
||||
getRunnerLogger(false),
|
||||
new RecordingLogger(),
|
||||
"failure cause",
|
||||
"exception stack trace",
|
||||
);
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
exportEnvVar,
|
||||
} from "./environment";
|
||||
import { getRef } from "./git-utils";
|
||||
import { GITHUB_DOTCOM_URL } from "./github";
|
||||
import * as json from "./json";
|
||||
import type { Logger } from "./logging";
|
||||
import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching";
|
||||
@@ -41,7 +42,6 @@ import {
|
||||
ConfigurationError,
|
||||
getRequiredEnvParam,
|
||||
isInTestMode,
|
||||
GITHUB_DOTCOM_URL,
|
||||
DiskUsage,
|
||||
assertNever,
|
||||
BuildMode,
|
||||
|
||||
@@ -3,9 +3,8 @@ import * as stream from "stream";
|
||||
|
||||
import test from "ava";
|
||||
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { extractTarZst } from "./tar";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import { RecordingLogger, setupTests } from "./testing-utils";
|
||||
import { withTmpDir } from "./util";
|
||||
|
||||
setupTests(test);
|
||||
@@ -17,7 +16,7 @@ test("extractTarZst rejects if the input stream errors", async (t) => {
|
||||
archive,
|
||||
path.join(tmpDir, "dest"),
|
||||
{ type: "gnu", version: "1.34" },
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
archive.destroy(
|
||||
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
featureConfig,
|
||||
FeatureEnablement,
|
||||
} from "./feature-flags";
|
||||
import { Logger } from "./logging";
|
||||
import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging";
|
||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||
import { getBundlePlatform } from "./platform";
|
||||
import { ActionName } from "./status-report";
|
||||
@@ -658,12 +658,13 @@ export class RecordingLogger implements Logger {
|
||||
|
||||
constructor(private readonly logToConsole: boolean = true) {}
|
||||
|
||||
private addMessage(level: LogLevel, message: string | Error): void {
|
||||
this.messages.push({ type: level, message });
|
||||
private addMessage(level: LogLevel, message: LoggableError): void {
|
||||
const joinedMessage = joinMessageStrings(message);
|
||||
this.messages.push({ type: level, message: joinedMessage });
|
||||
|
||||
if (this.logToConsole) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(message);
|
||||
console.debug(joinedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,19 +685,19 @@ export class RecordingLogger implements Logger {
|
||||
return true;
|
||||
}
|
||||
|
||||
debug(message: string) {
|
||||
debug(message: Loggable) {
|
||||
this.addMessage("debug", message);
|
||||
}
|
||||
|
||||
info(message: string) {
|
||||
info(message: Loggable) {
|
||||
this.addMessage("info", message);
|
||||
}
|
||||
|
||||
warning(message: string | Error) {
|
||||
warning(message: LoggableError) {
|
||||
this.addMessage("warning", message);
|
||||
}
|
||||
|
||||
error(message: string | Error) {
|
||||
error(message: LoggableError) {
|
||||
this.addMessage("error", message);
|
||||
}
|
||||
|
||||
@@ -1041,3 +1042,15 @@ export function makeTestToken(length: number = 36) {
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
return chars.repeat(Math.ceil(length / chars.length)).slice(0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a real, newly created CodeQL instance for testing. The instance refers to
|
||||
* a non-existent placeholder codeql command, so tests that use this function
|
||||
* should also stub the toolrunner.ToolRunner constructor.
|
||||
*/
|
||||
export async function getCodeQLForTesting(
|
||||
cmd = "codeql-for-testing",
|
||||
logger: Logger = new RecordingLogger(),
|
||||
): Promise<codeql.CodeQL> {
|
||||
return codeql.getCodeQLForCmd(logger, cmd, false);
|
||||
}
|
||||
|
||||
@@ -10,9 +10,8 @@ import { https } from "follow-redirects";
|
||||
import nock from "nock";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import * as tar from "./tar";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import { RecordingLogger, setupTests } from "./testing-utils";
|
||||
import { downloadAndExtract } from "./tools-download";
|
||||
import * as util from "./util";
|
||||
|
||||
@@ -34,7 +33,7 @@ test.serial(
|
||||
undefined,
|
||||
{},
|
||||
undefined,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(Number.isInteger(statusReport.downloadDurationMs));
|
||||
@@ -72,7 +71,7 @@ test.serial(
|
||||
undefined,
|
||||
{},
|
||||
{ type: "gnu", version: "1.34" },
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(Number.isInteger(statusReport.downloadDurationMs));
|
||||
@@ -105,7 +104,7 @@ test.serial(
|
||||
undefined,
|
||||
{},
|
||||
{ type: "gnu", version: "1.34" },
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
{
|
||||
instanceOf: util.HTTPError,
|
||||
@@ -149,7 +148,7 @@ test.serial(
|
||||
undefined,
|
||||
{},
|
||||
{ type: "gnu", version: "1.34" },
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(Number.isInteger(statusReport.downloadDurationMs));
|
||||
@@ -189,7 +188,7 @@ test.serial(
|
||||
undefined,
|
||||
{},
|
||||
{ type: "gnu", version: "1.34" },
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(
|
||||
@@ -237,7 +236,7 @@ test.serial(
|
||||
undefined,
|
||||
{},
|
||||
{ type: "gnu", version: "1.34" },
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.assert(Number.isInteger(statusReport.totalDurationMs));
|
||||
|
||||
@@ -4,11 +4,12 @@ import * as path from "path";
|
||||
import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import { CodeQL, getCodeQLForTesting } from "./codeql";
|
||||
import type { CodeQL } from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import {
|
||||
createTestConfig,
|
||||
getCodeQLForTesting,
|
||||
makeVersionInfo,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
|
||||
@@ -16,12 +16,12 @@ import * as configUtils from "./config-utils";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import {
|
||||
createFeatures,
|
||||
createTestConfig,
|
||||
getRecordingLogger,
|
||||
makeVersionInfo,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "./testing-utils";
|
||||
import {
|
||||
@@ -265,7 +265,7 @@ test.serial("cleanup removes only old CodeQL TRAP caches", async (t) => {
|
||||
const statusReport = await cleanupTrapCaches(
|
||||
config,
|
||||
createFeatures([Feature.CleanupTrapCaches]),
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(listStub.callCount, 1);
|
||||
|
||||
@@ -10,9 +10,9 @@ import * as analyses from "./analyses";
|
||||
import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses";
|
||||
import * as api from "./api-client";
|
||||
import * as diffUtils from "./diff-informed-analysis-utils";
|
||||
import { getRunnerLogger, Logger } from "./logging";
|
||||
import { Logger } from "./logging";
|
||||
import * as sarif from "./sarif";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import { RecordingLogger, setupTests } from "./testing-utils";
|
||||
import * as uploadLib from "./upload-lib";
|
||||
import { UploadPayload } from "./upload-lib/types";
|
||||
import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util";
|
||||
@@ -29,7 +29,7 @@ test.serial("validateSarifFileSchema - valid", (t) => {
|
||||
uploadLib.validateSarifFileSchema(
|
||||
uploadLib.readSarifFileOrThrow(inputFile),
|
||||
inputFile,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -40,7 +40,7 @@ test.serial("validateSarifFileSchema - invalid", (t) => {
|
||||
uploadLib.validateSarifFileSchema(
|
||||
uploadLib.readSarifFileOrThrow(inputFile),
|
||||
inputFile,
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -179,7 +179,7 @@ test.serial("finding SARIF files", async (t) => {
|
||||
}
|
||||
|
||||
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
tmpDir,
|
||||
);
|
||||
|
||||
@@ -200,7 +200,7 @@ test.serial("getGroupedSarifFilePaths - Risk Assessment files", async (t) => {
|
||||
fs.writeFileSync(sarifPath, "");
|
||||
|
||||
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
sarifPath,
|
||||
);
|
||||
|
||||
@@ -218,7 +218,7 @@ test.serial("getGroupedSarifFilePaths - Code Quality file", async (t) => {
|
||||
fs.writeFileSync(sarifPath, "");
|
||||
|
||||
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
sarifPath,
|
||||
);
|
||||
|
||||
@@ -236,7 +236,7 @@ test.serial("getGroupedSarifFilePaths - Code Scanning file", async (t) => {
|
||||
fs.writeFileSync(sarifPath, "");
|
||||
|
||||
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
sarifPath,
|
||||
);
|
||||
|
||||
@@ -254,7 +254,7 @@ test.serial("getGroupedSarifFilePaths - Other file", async (t) => {
|
||||
fs.writeFileSync(sarifPath, "");
|
||||
|
||||
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
sarifPath,
|
||||
);
|
||||
|
||||
@@ -932,7 +932,7 @@ function uploadPayloadFixtures(analysis: analyses.AnalysisConfig) {
|
||||
owner: mockData.owner,
|
||||
repo: mockData.repo,
|
||||
},
|
||||
getRunnerLogger(true),
|
||||
new RecordingLogger(),
|
||||
analysis,
|
||||
);
|
||||
|
||||
@@ -1019,7 +1019,7 @@ function runFilterAlertsByDiffRange(
|
||||
diffRanges: diffUtils.DiffThunkRange[],
|
||||
): Partial<sarif.Log> {
|
||||
sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges);
|
||||
return uploadLib.filterAlertsByDiffRange(getRunnerLogger(true), input);
|
||||
return uploadLib.filterAlertsByDiffRange(new RecordingLogger(), input);
|
||||
}
|
||||
|
||||
test.serial(
|
||||
|
||||
@@ -18,6 +18,7 @@ import { ActionsEnvVars, EnvVar, exportEnvVar } from "./environment";
|
||||
import { FeatureEnablement } from "./feature-flags";
|
||||
import * as fingerprints from "./fingerprints";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import * as github from "./github";
|
||||
import { initCodeQL } from "./init";
|
||||
import { Logger } from "./logging";
|
||||
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
||||
@@ -33,7 +34,6 @@ import * as util from "./util";
|
||||
import {
|
||||
ConfigurationError,
|
||||
getErrorMessage,
|
||||
getRequiredEnvParam,
|
||||
GitHubVariant,
|
||||
GitHubVersion,
|
||||
satisfiesGHESVersion,
|
||||
@@ -104,6 +104,8 @@ async function combineSarifFilesUsingCLI(
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
): Promise<Partial<sarif.Log>> {
|
||||
const env = util.getEnv();
|
||||
|
||||
logger.info("Combining SARIF files using the CodeQL CLI");
|
||||
|
||||
const sarifObjects = sarifFiles.map(sarif.readSarifFile);
|
||||
@@ -152,8 +154,7 @@ async function combineSarifFilesUsingCLI(
|
||||
externalRepoAuth: actionsUtil.getOptionalInput(
|
||||
"external-repository-token",
|
||||
),
|
||||
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
|
||||
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
|
||||
...github.getCurrentInstance(env),
|
||||
};
|
||||
|
||||
const codeQLDefaultVersionInfo =
|
||||
|
||||
@@ -5,8 +5,12 @@ import test, { ExecutionContext } from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import { AnalysisKind, getAnalysisConfig } from "./analyses";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { createFeatures, makeMacro, setupTests } from "./testing-utils";
|
||||
import {
|
||||
createFeatures,
|
||||
makeMacro,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "./testing-utils";
|
||||
import { UploadResult } from "./upload-lib";
|
||||
import * as uploadLib from "./upload-lib";
|
||||
import { postProcessAndUploadSarif } from "./upload-sarif";
|
||||
@@ -51,7 +55,7 @@ const postProcessAndUploadSarifMacro = makeMacro({
|
||||
expectedResult: Partial<Record<AnalysisKind, UploadSarifExpectedResult>>,
|
||||
) => {
|
||||
await util.withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const testPath = sarifPath(tempDir);
|
||||
const features = createFeatures([]);
|
||||
|
||||
@@ -206,7 +210,7 @@ test.serial(
|
||||
"postProcessAndUploadSarif doesn't upload if upload is disabled",
|
||||
async (t) => {
|
||||
await util.withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const features = createFeatures([]);
|
||||
|
||||
const toFullPath = (filename: string) => path.join(tempDir, filename);
|
||||
@@ -239,7 +243,7 @@ test.serial(
|
||||
"postProcessAndUploadSarif writes post-processed SARIF files if output directory is provided",
|
||||
async (t) => {
|
||||
await util.withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const logger = new RecordingLogger();
|
||||
const features = createFeatures([]);
|
||||
|
||||
const toFullPath = (filename: string) => path.join(tempDir, filename);
|
||||
|
||||
@@ -10,8 +10,7 @@ import * as sinon from "sinon";
|
||||
|
||||
import * as api from "./api-client";
|
||||
import { EnvVar } from "./environment";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import { RecordingLogger, setupTests } from "./testing-utils";
|
||||
import * as util from "./util";
|
||||
|
||||
setupTests(test);
|
||||
@@ -92,7 +91,7 @@ for (const {
|
||||
|
||||
test("getMemoryFlag() throws if the ram input is < 0 or NaN", async (t) => {
|
||||
for (const input of ["-1", "hello!"]) {
|
||||
t.throws(() => util.getMemoryFlag(input, getRunnerLogger(true)));
|
||||
t.throws(() => util.getMemoryFlag(input, new RecordingLogger()));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -109,13 +108,13 @@ test("getThreadsFlag() should return the correct --threads flag", (t) => {
|
||||
];
|
||||
|
||||
for (const [input, expectedFlag] of tests) {
|
||||
const flag = util.getThreadsFlag(input, getRunnerLogger(true));
|
||||
const flag = util.getThreadsFlag(input, new RecordingLogger());
|
||||
t.deepEqual(flag, expectedFlag);
|
||||
}
|
||||
});
|
||||
|
||||
test("getThreadsFlag() throws if the threads input is not an integer", (t) => {
|
||||
t.throws(() => util.getThreadsFlag("hello!", getRunnerLogger(true)));
|
||||
t.throws(() => util.getThreadsFlag("hello!", new RecordingLogger()));
|
||||
});
|
||||
|
||||
test.serial(
|
||||
@@ -164,66 +163,6 @@ test.serial("getExtraOptionsEnvParam() fails on invalid JSON", (t) => {
|
||||
process.env.CODEQL_ACTION_EXTRA_OPTIONS = origExtraOptions;
|
||||
});
|
||||
|
||||
test("parseGitHubUrl", (t) => {
|
||||
t.deepEqual(util.parseGitHubUrl("github.com"), "https://github.com");
|
||||
t.deepEqual(util.parseGitHubUrl("https://github.com"), "https://github.com");
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://api.github.com"),
|
||||
"https://github.com",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.com/foo/bar"),
|
||||
"https://github.com",
|
||||
);
|
||||
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("github.example.com"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.example.com"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://api.github.example.com"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.example.com/api/v3"),
|
||||
"https://github.example.com/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.example.com:1234"),
|
||||
"https://github.example.com:1234/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://api.github.example.com:1234"),
|
||||
"https://github.example.com:1234/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.example.com:1234/api/v3"),
|
||||
"https://github.example.com:1234/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.example.com/base/path"),
|
||||
"https://github.example.com/base/path/",
|
||||
);
|
||||
t.deepEqual(
|
||||
util.parseGitHubUrl("https://github.example.com/base/path/api/v3"),
|
||||
"https://github.example.com/base/path/",
|
||||
);
|
||||
|
||||
t.throws(() => util.parseGitHubUrl(""), {
|
||||
message: '"" is not a valid URL',
|
||||
});
|
||||
t.throws(() => util.parseGitHubUrl("ssh://github.com"), {
|
||||
message: '"ssh://github.com" is not a http or https URL',
|
||||
});
|
||||
t.throws(() => util.parseGitHubUrl("http:///::::433"), {
|
||||
message: '"http:///::::433" is not a valid URL',
|
||||
});
|
||||
});
|
||||
|
||||
test("allowed API versions", async (t) => {
|
||||
t.is(util.apiVersionInRange("1.33.0", "1.33", "2.0"), undefined);
|
||||
t.is(util.apiVersionInRange("1.33.1", "1.33", "2.0"), undefined);
|
||||
@@ -445,7 +384,7 @@ test("getCgroupCpuCountFromCpus calculates the number of CPUs correctly", async
|
||||
const testCpuFile = `${tmpDir}/cpus-file`;
|
||||
fs.writeFileSync(testCpuFile, "1, 9-10\n", "utf-8");
|
||||
t.deepEqual(
|
||||
util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)),
|
||||
util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()),
|
||||
3,
|
||||
);
|
||||
});
|
||||
@@ -456,7 +395,7 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file doesn't exist"
|
||||
const testCpuFile = `${tmpDir}/cpus-file`;
|
||||
t.false(fs.existsSync(testCpuFile));
|
||||
t.deepEqual(
|
||||
util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)),
|
||||
util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
@@ -467,7 +406,7 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file exists but is
|
||||
const testCpuFile = `${tmpDir}/cpus-file`;
|
||||
fs.writeFileSync(testCpuFile, "\n", "utf-8");
|
||||
t.deepEqual(
|
||||
util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)),
|
||||
util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
@@ -477,7 +416,7 @@ test.serial(
|
||||
"checkDiskUsage succeeds and produces positive numbers",
|
||||
async (t) => {
|
||||
process.env["GITHUB_WORKSPACE"] = os.tmpdir();
|
||||
const diskUsage = await util.checkDiskUsage(getRunnerLogger(true));
|
||||
const diskUsage = await util.checkDiskUsage(new RecordingLogger());
|
||||
if (t.truthy(diskUsage)) {
|
||||
t.true(diskUsage.numAvailableBytes > 0);
|
||||
t.true(diskUsage.numTotalBytes > 0);
|
||||
|
||||
48
src/util.ts
48
src/util.ts
@@ -50,11 +50,6 @@ const BROKEN_VERSIONS = ["0.0.0-20211207"];
|
||||
/** A string representing a GitHub instance. */
|
||||
export type InstanceURL = string;
|
||||
|
||||
/**
|
||||
* The URL for github.com.
|
||||
*/
|
||||
export const GITHUB_DOTCOM_URL: InstanceURL = "https://github.com";
|
||||
|
||||
/**
|
||||
* Default name of the debugging artifact.
|
||||
*/
|
||||
@@ -470,49 +465,6 @@ export function getGeneratedSuitePath(config: Config, language: Language) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses user input of a github.com or GHES URL to a canonical form.
|
||||
* Removes any API prefix or suffix if one is present.
|
||||
*/
|
||||
export function parseGitHubUrl(inputUrl: string): string {
|
||||
const originalUrl = inputUrl;
|
||||
if (inputUrl.indexOf("://") === -1) {
|
||||
inputUrl = `https://${inputUrl}`;
|
||||
}
|
||||
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
||||
}
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(inputUrl);
|
||||
} catch {
|
||||
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
||||
}
|
||||
|
||||
// If we detect this is trying to be to github.com
|
||||
// then return with a fixed canonical URL.
|
||||
if (url.hostname === "github.com" || url.hostname === "api.github.com") {
|
||||
return GITHUB_DOTCOM_URL;
|
||||
}
|
||||
|
||||
// Remove the API prefix if it's present
|
||||
if (url.pathname.indexOf("/api/v3") !== -1) {
|
||||
url.pathname = url.pathname.substring(0, url.pathname.indexOf("/api/v3"));
|
||||
}
|
||||
// Also consider subdomain isolation on GHES
|
||||
if (url.hostname.startsWith("api.")) {
|
||||
url.hostname = url.hostname.substring(4);
|
||||
}
|
||||
|
||||
// Normalise path to having a trailing slash for consistency
|
||||
if (!url.pathname.endsWith("/")) {
|
||||
url.pathname = `${url.pathname}/`;
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
const CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR =
|
||||
"CODEQL_ACTION_WARNED_ABOUT_VERSION";
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ import * as yaml from "js-yaml";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { createStubCodeQL, getCodeQLForTesting } from "./codeql";
|
||||
import { createStubCodeQL } from "./codeql";
|
||||
import { ActionsEnvVars, EnvVar } from "./environment";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
getCodeQLForTesting,
|
||||
createTestConfig,
|
||||
getRecordingLogger,
|
||||
getTestEnv,
|
||||
|
||||
Reference in New Issue
Block a user