Compare commits

..

23 Commits

Author SHA1 Message Date
Óscar San José 8c6a2b4d4b Rebuild 2026-06-02 15:13:54 +02:00
Óscar San José 57b3666b1d Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-06-01 20:23:20 +02:00
Óscar San José 1251f87758 Improve testing 2026-06-01 20:19:50 +02:00
Óscar San José 6963dfbbc5 Add logging and telemetry for mode 2026-06-01 18:44:55 +02:00
Óscar San José d426d33115 Implement an enforce/dynamic approach 2026-06-01 18:33:23 +02:00
Óscar San José f22e7a29ce Merge branch 'main' into copilot/add-tools-input-source-repository 2026-06-01 17:31:14 +02:00
Óscar San José d8e5e3dbab Rebuild 2026-06-01 17:26:52 +02:00
copilot-swe-agent[bot] 9b49e27edb Allow repository tools property fallback in resolveToolsInput 2026-05-29 11:39:28 +00:00
Óscar San José aeb3e20ace Rebuild 2026-05-29 13:26:31 +02:00
Óscar San José d622e410d6 Lint 2026-05-29 13:23:34 +02:00
Óscar San José fb605661cd Missing files 2026-05-29 13:18:17 +02:00
Óscar San José 063bb8b614 Move resolve-tools-input.ts and tests to src/config 2026-05-29 13:16:55 +02:00
Óscar San José 3d8236de69 More fixes from CR 2026-05-29 13:14:23 +02:00
Óscar San José b1eeb13c4c Lint 2026-05-29 13:08:58 +02:00
Óscar San José 964d328667 More fixes from CR 2026-05-29 13:08:26 +02:00
Óscar San José f9b6569832 More fixes from CR 2026-05-29 13:07:20 +02:00
Óscar San José 3782e65e9f Easy fixes from CR 2026-05-29 12:52:51 +02:00
Óscar San José dafa67e1d3 Rebuild 2026-05-29 10:07:34 +02:00
Óscar San José 0d5f0f55c2 Lint fixes 2026-05-29 10:03:21 +02:00
Óscar San José 7c7926f8df Fixed tests due to stale language.ts obscuring language/index.ts import when done at module level 2026-05-25 16:33:01 +02:00
Óscar San José 838486a3c3 Merge branch 'main' of https://github.com/github/codeql-action into copilot/add-tools-input-source-repository 2026-05-25 13:27:20 +02:00
copilot-swe-agent[bot] 09a0f62a7a Refactor resolveToolsInput: accept repository properties as parameter, simplify implementation and tests 2026-05-25 11:10:26 +00:00
Óscar San José 652e91defb Add repo property to override codeql-cli version 2026-04-16 17:09:34 +02:00
39 changed files with 971 additions and 429 deletions
+1 -5
View File
@@ -4,11 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
## [UNRELEASED] ## [UNRELEASED]
No user facing changes. - Organizations can create a custom repository property named `github-codeql-tools` to set a default CodeQL CLI tools value. You can optionally set `github-codeql-tools-mode` to control scope: use `enforce` (default) to apply to all workflows, or `dynamic` to apply only to dynamic workflows. If a workflow provides an explicit `tools:` input, that input takes precedence. For more information, see [Managing custom properties for repositories in your organization](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization), [Repository properties for Code Scanning](https://docs.github.com/en/code-security/concepts/code-scanning/repository-properties) and [Customizing your advanced setup for code scanning](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning).
## 4.36.1 - 02 Jun 2026
No user facing changes.
## 4.36.0 - 22 May 2026 ## 4.36.0 - 22 May 2026
+255 -183
View File
@@ -19179,12 +19179,12 @@ var require_lib = __commonJS({
throw new Error("Client has already been disposed."); throw new Error("Client has already been disposed.");
} }
const parsedUrl = new URL(requestUrl); const parsedUrl = new URL(requestUrl);
let info8 = this._prepareRequest(verb, parsedUrl, headers); let info7 = this._prepareRequest(verb, parsedUrl, headers);
const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
let numTries = 0; let numTries = 0;
let response; let response;
do { do {
response = yield this.requestRaw(info8, data); response = yield this.requestRaw(info7, data);
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
let authenticationHandler; let authenticationHandler;
for (const handler2 of this.handlers) { for (const handler2 of this.handlers) {
@@ -19194,7 +19194,7 @@ var require_lib = __commonJS({
} }
} }
if (authenticationHandler) { if (authenticationHandler) {
return authenticationHandler.handleAuthentication(this, info8, data); return authenticationHandler.handleAuthentication(this, info7, data);
} else { } else {
return response; return response;
} }
@@ -19217,8 +19217,8 @@ var require_lib = __commonJS({
} }
} }
} }
info8 = this._prepareRequest(verb, parsedRedirectUrl, headers); info7 = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = yield this.requestRaw(info8, data); response = yield this.requestRaw(info7, data);
redirectsRemaining--; redirectsRemaining--;
} }
if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) { if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -19247,7 +19247,7 @@ var require_lib = __commonJS({
* @param info * @param info
* @param data * @param data
*/ */
requestRaw(info8, data) { requestRaw(info7, data) {
return __awaiter2(this, void 0, void 0, function* () { return __awaiter2(this, void 0, void 0, function* () {
return new Promise((resolve13, reject) => { return new Promise((resolve13, reject) => {
function callbackForResult(err, res) { function callbackForResult(err, res) {
@@ -19259,7 +19259,7 @@ var require_lib = __commonJS({
resolve13(res); resolve13(res);
} }
} }
this.requestRawWithCallback(info8, data, callbackForResult); this.requestRawWithCallback(info7, data, callbackForResult);
}); });
}); });
} }
@@ -19269,12 +19269,12 @@ var require_lib = __commonJS({
* @param data * @param data
* @param onResult * @param onResult
*/ */
requestRawWithCallback(info8, data, onResult) { requestRawWithCallback(info7, data, onResult) {
if (typeof data === "string") { if (typeof data === "string") {
if (!info8.options.headers) { if (!info7.options.headers) {
info8.options.headers = {}; info7.options.headers = {};
} }
info8.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8"); info7.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
} }
let callbackCalled = false; let callbackCalled = false;
function handleResult(err, res) { function handleResult(err, res) {
@@ -19283,7 +19283,7 @@ var require_lib = __commonJS({
onResult(err, res); onResult(err, res);
} }
} }
const req = info8.httpModule.request(info8.options, (msg) => { const req = info7.httpModule.request(info7.options, (msg) => {
const res = new HttpClientResponse(msg); const res = new HttpClientResponse(msg);
handleResult(void 0, res); handleResult(void 0, res);
}); });
@@ -19295,7 +19295,7 @@ var require_lib = __commonJS({
if (socket) { if (socket) {
socket.end(); socket.end();
} }
handleResult(new Error(`Request timeout: ${info8.options.path}`)); handleResult(new Error(`Request timeout: ${info7.options.path}`));
}); });
req.on("error", function(err) { req.on("error", function(err) {
handleResult(err); handleResult(err);
@@ -19331,27 +19331,27 @@ var require_lib = __commonJS({
return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
} }
_prepareRequest(method, requestUrl, headers) { _prepareRequest(method, requestUrl, headers) {
const info8 = {}; const info7 = {};
info8.parsedUrl = requestUrl; info7.parsedUrl = requestUrl;
const usingSsl = info8.parsedUrl.protocol === "https:"; const usingSsl = info7.parsedUrl.protocol === "https:";
info8.httpModule = usingSsl ? https3 : http; info7.httpModule = usingSsl ? https3 : http;
const defaultPort = usingSsl ? 443 : 80; const defaultPort = usingSsl ? 443 : 80;
info8.options = {}; info7.options = {};
info8.options.host = info8.parsedUrl.hostname; info7.options.host = info7.parsedUrl.hostname;
info8.options.port = info8.parsedUrl.port ? parseInt(info8.parsedUrl.port) : defaultPort; info7.options.port = info7.parsedUrl.port ? parseInt(info7.parsedUrl.port) : defaultPort;
info8.options.path = (info8.parsedUrl.pathname || "") + (info8.parsedUrl.search || ""); info7.options.path = (info7.parsedUrl.pathname || "") + (info7.parsedUrl.search || "");
info8.options.method = method; info7.options.method = method;
info8.options.headers = this._mergeHeaders(headers); info7.options.headers = this._mergeHeaders(headers);
if (this.userAgent != null) { if (this.userAgent != null) {
info8.options.headers["user-agent"] = this.userAgent; info7.options.headers["user-agent"] = this.userAgent;
} }
info8.options.agent = this._getAgent(info8.parsedUrl); info7.options.agent = this._getAgent(info7.parsedUrl);
if (this.handlers) { if (this.handlers) {
for (const handler2 of this.handlers) { for (const handler2 of this.handlers) {
handler2.prepareRequest(info8.options); handler2.prepareRequest(info7.options);
} }
} }
return info8; return info7;
} }
_mergeHeaders(headers) { _mergeHeaders(headers) {
if (this.requestOptions && this.requestOptions.headers) { if (this.requestOptions && this.requestOptions.headers) {
@@ -21406,7 +21406,7 @@ var require_core = __commonJS({
exports2.error = error3; exports2.error = error3;
exports2.warning = warning14; exports2.warning = warning14;
exports2.notice = notice; exports2.notice = notice;
exports2.info = info8; exports2.info = info7;
exports2.startGroup = startGroup4; exports2.startGroup = startGroup4;
exports2.endGroup = endGroup4; exports2.endGroup = endGroup4;
exports2.group = group; exports2.group = group;
@@ -21503,7 +21503,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
function notice(message, properties = {}) { function notice(message, properties = {}) {
(0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
} }
function info8(message) { function info7(message) {
process.stdout.write(message + os7.EOL); process.stdout.write(message + os7.EOL);
} }
function startGroup4(name) { function startGroup4(name) {
@@ -42402,12 +42402,12 @@ var require_operationHelpers = __commonJS({
if (hasOriginalRequest(request3)) { if (hasOriginalRequest(request3)) {
return getOperationRequestInfo(request3[originalRequestSymbol]); return getOperationRequestInfo(request3[originalRequestSymbol]);
} }
let info8 = state_js_1.state.operationRequestMap.get(request3); let info7 = state_js_1.state.operationRequestMap.get(request3);
if (!info8) { if (!info7) {
info8 = {}; info7 = {};
state_js_1.state.operationRequestMap.set(request3, info8); state_js_1.state.operationRequestMap.set(request3, info7);
} }
return info8; return info7;
} }
} }
}); });
@@ -76954,9 +76954,9 @@ var require_reflection_type_check = __commonJS({
var reflection_info_1 = require_reflection_info(); var reflection_info_1 = require_reflection_info();
var oneof_1 = require_oneof(); var oneof_1 = require_oneof();
var ReflectionTypeCheck = class { var ReflectionTypeCheck = class {
constructor(info8) { constructor(info7) {
var _a; var _a;
this.fields = (_a = info8.fields) !== null && _a !== void 0 ? _a : []; this.fields = (_a = info7.fields) !== null && _a !== void 0 ? _a : [];
} }
prepare() { prepare() {
if (this.data) if (this.data)
@@ -77202,8 +77202,8 @@ var require_reflection_json_reader = __commonJS({
var assert_1 = require_assert(); var assert_1 = require_assert();
var reflection_long_convert_1 = require_reflection_long_convert(); var reflection_long_convert_1 = require_reflection_long_convert();
var ReflectionJsonReader = class { var ReflectionJsonReader = class {
constructor(info8) { constructor(info7) {
this.info = info8; this.info = info7;
} }
prepare() { prepare() {
var _a; var _a;
@@ -77499,9 +77499,9 @@ var require_reflection_json_writer = __commonJS({
var reflection_info_1 = require_reflection_info(); var reflection_info_1 = require_reflection_info();
var assert_1 = require_assert(); var assert_1 = require_assert();
var ReflectionJsonWriter = class { var ReflectionJsonWriter = class {
constructor(info8) { constructor(info7) {
var _a; var _a;
this.fields = (_a = info8.fields) !== null && _a !== void 0 ? _a : []; this.fields = (_a = info7.fields) !== null && _a !== void 0 ? _a : [];
} }
/** /**
* Converts the message to a JSON object, based on the field descriptors. * Converts the message to a JSON object, based on the field descriptors.
@@ -77754,8 +77754,8 @@ var require_reflection_binary_reader = __commonJS({
var reflection_long_convert_1 = require_reflection_long_convert(); var reflection_long_convert_1 = require_reflection_long_convert();
var reflection_scalar_default_1 = require_reflection_scalar_default(); var reflection_scalar_default_1 = require_reflection_scalar_default();
var ReflectionBinaryReader = class { var ReflectionBinaryReader = class {
constructor(info8) { constructor(info7) {
this.info = info8; this.info = info7;
} }
prepare() { prepare() {
var _a; var _a;
@@ -77928,8 +77928,8 @@ var require_reflection_binary_writer = __commonJS({
var assert_1 = require_assert(); var assert_1 = require_assert();
var pb_long_1 = require_pb_long(); var pb_long_1 = require_pb_long();
var ReflectionBinaryWriter = class { var ReflectionBinaryWriter = class {
constructor(info8) { constructor(info7) {
this.info = info8; this.info = info7;
} }
prepare() { prepare() {
if (!this.fields) { if (!this.fields) {
@@ -78179,9 +78179,9 @@ var require_reflection_merge_partial = __commonJS({
"use strict"; "use strict";
Object.defineProperty(exports2, "__esModule", { value: true }); Object.defineProperty(exports2, "__esModule", { value: true });
exports2.reflectionMergePartial = void 0; exports2.reflectionMergePartial = void 0;
function reflectionMergePartial(info8, target, source) { function reflectionMergePartial(info7, target, source) {
let fieldValue, input = source, output; let fieldValue, input = source, output;
for (let field of info8.fields) { for (let field of info7.fields) {
let name = field.localName; let name = field.localName;
if (field.oneof) { if (field.oneof) {
const group = input[field.oneof]; const group = input[field.oneof];
@@ -78250,12 +78250,12 @@ var require_reflection_equals = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true }); Object.defineProperty(exports2, "__esModule", { value: true });
exports2.reflectionEquals = void 0; exports2.reflectionEquals = void 0;
var reflection_info_1 = require_reflection_info(); var reflection_info_1 = require_reflection_info();
function reflectionEquals(info8, a, b) { function reflectionEquals(info7, a, b) {
if (a === b) if (a === b)
return true; return true;
if (!a || !b) if (!a || !b)
return false; return false;
for (let field of info8.fields) { for (let field of info7.fields) {
let localName = field.localName; let localName = field.localName;
let val_a = field.oneof ? a[field.oneof][localName] : a[localName]; let val_a = field.oneof ? a[field.oneof][localName] : a[localName];
let val_b = field.oneof ? b[field.oneof][localName] : b[localName]; let val_b = field.oneof ? b[field.oneof][localName] : b[localName];
@@ -91275,7 +91275,7 @@ var require_async = __commonJS({
} }
} }
var sortBy$1 = awaitify(sortBy, 3); var sortBy$1 = awaitify(sortBy, 3);
function timeout(asyncFn, milliseconds, info8) { function timeout(asyncFn, milliseconds, info7) {
var fn = wrapAsync(asyncFn); var fn = wrapAsync(asyncFn);
return initialParams((args, callback) => { return initialParams((args, callback) => {
var timedOut = false; var timedOut = false;
@@ -91284,8 +91284,8 @@ var require_async = __commonJS({
var name = asyncFn.name || "anonymous"; var name = asyncFn.name || "anonymous";
var error3 = new Error('Callback function "' + name + '" timed out.'); var error3 = new Error('Callback function "' + name + '" timed out.');
error3.code = "ETIMEDOUT"; error3.code = "ETIMEDOUT";
if (info8) { if (info7) {
error3.info = info8; error3.info = info7;
} }
timedOut = true; timedOut = true;
callback(error3); callback(error3);
@@ -114681,12 +114681,12 @@ var require_lib4 = __commonJS({
throw new Error("Client has already been disposed."); throw new Error("Client has already been disposed.");
} }
const parsedUrl = new URL(requestUrl); const parsedUrl = new URL(requestUrl);
let info8 = this._prepareRequest(verb, parsedUrl, headers); let info7 = this._prepareRequest(verb, parsedUrl, headers);
const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
let numTries = 0; let numTries = 0;
let response; let response;
do { do {
response = yield this.requestRaw(info8, data); response = yield this.requestRaw(info7, data);
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
let authenticationHandler; let authenticationHandler;
for (const handler2 of this.handlers) { for (const handler2 of this.handlers) {
@@ -114696,7 +114696,7 @@ var require_lib4 = __commonJS({
} }
} }
if (authenticationHandler) { if (authenticationHandler) {
return authenticationHandler.handleAuthentication(this, info8, data); return authenticationHandler.handleAuthentication(this, info7, data);
} else { } else {
return response; return response;
} }
@@ -114719,8 +114719,8 @@ var require_lib4 = __commonJS({
} }
} }
} }
info8 = this._prepareRequest(verb, parsedRedirectUrl, headers); info7 = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = yield this.requestRaw(info8, data); response = yield this.requestRaw(info7, data);
redirectsRemaining--; redirectsRemaining--;
} }
if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) { if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -114749,7 +114749,7 @@ var require_lib4 = __commonJS({
* @param info * @param info
* @param data * @param data
*/ */
requestRaw(info8, data) { requestRaw(info7, data) {
return __awaiter2(this, void 0, void 0, function* () { return __awaiter2(this, void 0, void 0, function* () {
return new Promise((resolve13, reject) => { return new Promise((resolve13, reject) => {
function callbackForResult(err, res) { function callbackForResult(err, res) {
@@ -114761,7 +114761,7 @@ var require_lib4 = __commonJS({
resolve13(res); resolve13(res);
} }
} }
this.requestRawWithCallback(info8, data, callbackForResult); this.requestRawWithCallback(info7, data, callbackForResult);
}); });
}); });
} }
@@ -114771,12 +114771,12 @@ var require_lib4 = __commonJS({
* @param data * @param data
* @param onResult * @param onResult
*/ */
requestRawWithCallback(info8, data, onResult) { requestRawWithCallback(info7, data, onResult) {
if (typeof data === "string") { if (typeof data === "string") {
if (!info8.options.headers) { if (!info7.options.headers) {
info8.options.headers = {}; info7.options.headers = {};
} }
info8.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8"); info7.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
} }
let callbackCalled = false; let callbackCalled = false;
function handleResult(err, res) { function handleResult(err, res) {
@@ -114785,7 +114785,7 @@ var require_lib4 = __commonJS({
onResult(err, res); onResult(err, res);
} }
} }
const req = info8.httpModule.request(info8.options, (msg) => { const req = info7.httpModule.request(info7.options, (msg) => {
const res = new HttpClientResponse(msg); const res = new HttpClientResponse(msg);
handleResult(void 0, res); handleResult(void 0, res);
}); });
@@ -114797,7 +114797,7 @@ var require_lib4 = __commonJS({
if (socket) { if (socket) {
socket.end(); socket.end();
} }
handleResult(new Error(`Request timeout: ${info8.options.path}`)); handleResult(new Error(`Request timeout: ${info7.options.path}`));
}); });
req.on("error", function(err) { req.on("error", function(err) {
handleResult(err); handleResult(err);
@@ -114833,27 +114833,27 @@ var require_lib4 = __commonJS({
return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
} }
_prepareRequest(method, requestUrl, headers) { _prepareRequest(method, requestUrl, headers) {
const info8 = {}; const info7 = {};
info8.parsedUrl = requestUrl; info7.parsedUrl = requestUrl;
const usingSsl = info8.parsedUrl.protocol === "https:"; const usingSsl = info7.parsedUrl.protocol === "https:";
info8.httpModule = usingSsl ? https3 : http; info7.httpModule = usingSsl ? https3 : http;
const defaultPort = usingSsl ? 443 : 80; const defaultPort = usingSsl ? 443 : 80;
info8.options = {}; info7.options = {};
info8.options.host = info8.parsedUrl.hostname; info7.options.host = info7.parsedUrl.hostname;
info8.options.port = info8.parsedUrl.port ? parseInt(info8.parsedUrl.port) : defaultPort; info7.options.port = info7.parsedUrl.port ? parseInt(info7.parsedUrl.port) : defaultPort;
info8.options.path = (info8.parsedUrl.pathname || "") + (info8.parsedUrl.search || ""); info7.options.path = (info7.parsedUrl.pathname || "") + (info7.parsedUrl.search || "");
info8.options.method = method; info7.options.method = method;
info8.options.headers = this._mergeHeaders(headers); info7.options.headers = this._mergeHeaders(headers);
if (this.userAgent != null) { if (this.userAgent != null) {
info8.options.headers["user-agent"] = this.userAgent; info7.options.headers["user-agent"] = this.userAgent;
} }
info8.options.agent = this._getAgent(info8.parsedUrl); info7.options.agent = this._getAgent(info7.parsedUrl);
if (this.handlers) { if (this.handlers) {
for (const handler2 of this.handlers) { for (const handler2 of this.handlers) {
handler2.prepareRequest(info8.options); handler2.prepareRequest(info7.options);
} }
} }
return info8; return info7;
} }
_mergeHeaders(headers) { _mergeHeaders(headers) {
if (this.requestOptions && this.requestOptions.headers) { if (this.requestOptions && this.requestOptions.headers) {
@@ -121241,11 +121241,11 @@ var require_dist_node12 = __commonJS({
} }
async function wrapRequest2(state, request3, options) { async function wrapRequest2(state, request3, options) {
const limiter = new Bottleneck2(); const limiter = new Bottleneck2();
limiter.on("failed", function(error3, info8) { limiter.on("failed", function(error3, info7) {
const maxRetries = ~~error3.request.request.retries; const maxRetries = ~~error3.request.request.retries;
const after = ~~error3.request.request.retryAfter; const after = ~~error3.request.request.retryAfter;
options.request.retryCount = info8.retryCount + 1; options.request.retryCount = info7.retryCount + 1;
if (maxRetries > info8.retryCount) { if (maxRetries > info7.retryCount) {
return after * state.retryAfterBaseValue; return after * state.retryAfterBaseValue;
} }
}); });
@@ -122453,12 +122453,12 @@ var require_lib5 = __commonJS({
throw new Error("Client has already been disposed."); throw new Error("Client has already been disposed.");
} }
const parsedUrl = new URL(requestUrl); const parsedUrl = new URL(requestUrl);
let info8 = this._prepareRequest(verb, parsedUrl, headers); let info7 = this._prepareRequest(verb, parsedUrl, headers);
const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
let numTries = 0; let numTries = 0;
let response; let response;
do { do {
response = yield this.requestRaw(info8, data); response = yield this.requestRaw(info7, data);
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
let authenticationHandler; let authenticationHandler;
for (const handler2 of this.handlers) { for (const handler2 of this.handlers) {
@@ -122468,7 +122468,7 @@ var require_lib5 = __commonJS({
} }
} }
if (authenticationHandler) { if (authenticationHandler) {
return authenticationHandler.handleAuthentication(this, info8, data); return authenticationHandler.handleAuthentication(this, info7, data);
} else { } else {
return response; return response;
} }
@@ -122491,8 +122491,8 @@ var require_lib5 = __commonJS({
} }
} }
} }
info8 = this._prepareRequest(verb, parsedRedirectUrl, headers); info7 = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = yield this.requestRaw(info8, data); response = yield this.requestRaw(info7, data);
redirectsRemaining--; redirectsRemaining--;
} }
if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) { if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -122521,7 +122521,7 @@ var require_lib5 = __commonJS({
* @param info * @param info
* @param data * @param data
*/ */
requestRaw(info8, data) { requestRaw(info7, data) {
return __awaiter2(this, void 0, void 0, function* () { return __awaiter2(this, void 0, void 0, function* () {
return new Promise((resolve13, reject) => { return new Promise((resolve13, reject) => {
function callbackForResult(err, res) { function callbackForResult(err, res) {
@@ -122533,7 +122533,7 @@ var require_lib5 = __commonJS({
resolve13(res); resolve13(res);
} }
} }
this.requestRawWithCallback(info8, data, callbackForResult); this.requestRawWithCallback(info7, data, callbackForResult);
}); });
}); });
} }
@@ -122543,12 +122543,12 @@ var require_lib5 = __commonJS({
* @param data * @param data
* @param onResult * @param onResult
*/ */
requestRawWithCallback(info8, data, onResult) { requestRawWithCallback(info7, data, onResult) {
if (typeof data === "string") { if (typeof data === "string") {
if (!info8.options.headers) { if (!info7.options.headers) {
info8.options.headers = {}; info7.options.headers = {};
} }
info8.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8"); info7.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
} }
let callbackCalled = false; let callbackCalled = false;
function handleResult(err, res) { function handleResult(err, res) {
@@ -122557,7 +122557,7 @@ var require_lib5 = __commonJS({
onResult(err, res); onResult(err, res);
} }
} }
const req = info8.httpModule.request(info8.options, (msg) => { const req = info7.httpModule.request(info7.options, (msg) => {
const res = new HttpClientResponse(msg); const res = new HttpClientResponse(msg);
handleResult(void 0, res); handleResult(void 0, res);
}); });
@@ -122569,7 +122569,7 @@ var require_lib5 = __commonJS({
if (socket) { if (socket) {
socket.end(); socket.end();
} }
handleResult(new Error(`Request timeout: ${info8.options.path}`)); handleResult(new Error(`Request timeout: ${info7.options.path}`));
}); });
req.on("error", function(err) { req.on("error", function(err) {
handleResult(err); handleResult(err);
@@ -122605,27 +122605,27 @@ var require_lib5 = __commonJS({
return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
} }
_prepareRequest(method, requestUrl, headers) { _prepareRequest(method, requestUrl, headers) {
const info8 = {}; const info7 = {};
info8.parsedUrl = requestUrl; info7.parsedUrl = requestUrl;
const usingSsl = info8.parsedUrl.protocol === "https:"; const usingSsl = info7.parsedUrl.protocol === "https:";
info8.httpModule = usingSsl ? https3 : http; info7.httpModule = usingSsl ? https3 : http;
const defaultPort = usingSsl ? 443 : 80; const defaultPort = usingSsl ? 443 : 80;
info8.options = {}; info7.options = {};
info8.options.host = info8.parsedUrl.hostname; info7.options.host = info7.parsedUrl.hostname;
info8.options.port = info8.parsedUrl.port ? parseInt(info8.parsedUrl.port) : defaultPort; info7.options.port = info7.parsedUrl.port ? parseInt(info7.parsedUrl.port) : defaultPort;
info8.options.path = (info8.parsedUrl.pathname || "") + (info8.parsedUrl.search || ""); info7.options.path = (info7.parsedUrl.pathname || "") + (info7.parsedUrl.search || "");
info8.options.method = method; info7.options.method = method;
info8.options.headers = this._mergeHeaders(headers); info7.options.headers = this._mergeHeaders(headers);
if (this.userAgent != null) { if (this.userAgent != null) {
info8.options.headers["user-agent"] = this.userAgent; info7.options.headers["user-agent"] = this.userAgent;
} }
info8.options.agent = this._getAgent(info8.parsedUrl); info7.options.agent = this._getAgent(info7.parsedUrl);
if (this.handlers) { if (this.handlers) {
for (const handler2 of this.handlers) { for (const handler2 of this.handlers) {
handler2.prepareRequest(info8.options); handler2.prepareRequest(info7.options);
} }
} }
return info8; return info7;
} }
_mergeHeaders(headers) { _mergeHeaders(headers) {
if (this.requestOptions && this.requestOptions.headers) { if (this.requestOptions && this.requestOptions.headers) {
@@ -124615,10 +124615,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
(0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
} }
exports2.notice = notice; exports2.notice = notice;
function info8(message) { function info7(message) {
process.stdout.write(message + os7.EOL); process.stdout.write(message + os7.EOL);
} }
exports2.info = info8; exports2.info = info7;
function startGroup4(name) { function startGroup4(name) {
(0, command_1.issue)("group", name); (0, command_1.issue)("group", name);
} }
@@ -148062,34 +148062,14 @@ function asHTTPError(arg) {
return void 0; return void 0;
} }
var cachedCodeQlVersion = void 0; var cachedCodeQlVersion = void 0;
function cacheCodeQlVersion(cmd, version) { function cacheCodeQlVersion(version) {
if (cachedCodeQlVersion !== void 0) { if (cachedCodeQlVersion !== void 0) {
throw new Error("cacheCodeQlVersion() should be called only once"); throw new Error("cacheCodeQlVersion() should be called only once");
} }
cachedCodeQlVersion = version; cachedCodeQlVersion = version;
core3.exportVariable(
"CODEQL_ACTION_CLI_VERSION_INFO" /* CODEQL_VERSION_INFO */,
JSON.stringify({ cmd, version })
);
} }
function getCachedCodeQlVersion(cmd) { function getCachedCodeQlVersion() {
if (cachedCodeQlVersion !== void 0) { return cachedCodeQlVersion;
return cachedCodeQlVersion;
}
const serialized = process.env["CODEQL_ACTION_CLI_VERSION_INFO" /* CODEQL_VERSION_INFO */];
if (!serialized) {
return void 0;
}
let persisted;
try {
persisted = JSON.parse(serialized);
} catch {
return void 0;
}
if (typeof persisted?.version?.version !== "string" || cmd !== void 0 && persisted.cmd !== cmd) {
return void 0;
}
return persisted.version;
} }
async function codeQlVersionAtLeast(codeql, requiredVersion) { async function codeQlVersionAtLeast(codeql, requiredVersion) {
return semver.gte((await codeql.getVersion()).version, requiredVersion); return semver.gte((await codeql.getVersion()).version, requiredVersion);
@@ -148386,7 +148366,7 @@ function getDiffRangesJsonFilePath() {
return path2.join(getTemporaryDirectory(), PR_DIFF_RANGE_JSON_FILENAME); return path2.join(getTemporaryDirectory(), PR_DIFF_RANGE_JSON_FILENAME);
} }
function getActionVersion() { function getActionVersion() {
return "4.36.2"; return "4.36.1";
} }
function getWorkflowEventName() { function getWorkflowEventName() {
return getRequiredEnvParam("GITHUB_EVENT_NAME"); return getRequiredEnvParam("GITHUB_EVENT_NAME");
@@ -148689,11 +148669,11 @@ async function errorRequest(state, octokit, error3, options) {
} }
async function wrapRequest(state, octokit, request3, options) { async function wrapRequest(state, octokit, request3, options) {
const limiter = new import_light.default(); const limiter = new import_light.default();
limiter.on("failed", function(error3, info8) { limiter.on("failed", function(error3, info7) {
const maxRetries = ~~error3.request.request?.retries; const maxRetries = ~~error3.request.request?.retries;
const after = ~~error3.request.request?.retryAfter; const after = ~~error3.request.request?.retryAfter;
options.request.retryCount = info8.retryCount + 1; options.request.retryCount = info7.retryCount + 1;
if (maxRetries > info8.retryCount) { if (maxRetries > info7.retryCount) {
return after * state.retryAfterBaseValue; return after * state.retryAfterBaseValue;
} }
}); });
@@ -150430,11 +150410,14 @@ function getUnknownLanguagesError(languages) {
} }
// src/feature-flags/properties.ts // src/feature-flags/properties.ts
var github2 = __toESM(require_github());
var GITHUB_CODEQL_PROPERTY_PREFIX = "github-codeql-"; var GITHUB_CODEQL_PROPERTY_PREFIX = "github-codeql-";
var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => {
RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay";
RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries";
RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs";
RepositoryPropertyName2["TOOLS"] = "github-codeql-tools";
RepositoryPropertyName2["TOOLS_MODE"] = "github-codeql-tools-mode";
return RepositoryPropertyName2; return RepositoryPropertyName2;
})(RepositoryPropertyName || {}); })(RepositoryPropertyName || {});
function isString2(value) { function isString2(value) {
@@ -150452,7 +150435,12 @@ var booleanProperty = {
var repositoryPropertyParsers = { var repositoryPropertyParsers = {
["github-codeql-disable-overlay" /* DISABLE_OVERLAY */]: booleanProperty, ["github-codeql-disable-overlay" /* DISABLE_OVERLAY */]: booleanProperty,
["github-codeql-extra-queries" /* EXTRA_QUERIES */]: stringProperty, ["github-codeql-extra-queries" /* EXTRA_QUERIES */]: stringProperty,
["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty ["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty,
["github-codeql-tools" /* TOOLS */]: stringProperty,
["github-codeql-tools-mode" /* TOOLS_MODE */]: {
validate: isString2,
parse: parseToolsModeRepositoryProperty
}
}; };
async function loadPropertiesFromApi(logger, repositoryNwo) { async function loadPropertiesFromApi(logger, repositoryNwo) {
try { try {
@@ -150505,6 +150493,26 @@ async function loadPropertiesFromApi(logger, repositoryNwo) {
); );
} }
} }
async function loadRepositoryProperties(repositoryNwo, logger) {
const repositoryOwnerType = github2.context.payload.repository?.owner.type;
logger.debug(
`Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`
);
if (repositoryOwnerType === "User") {
logger.debug(
"Skipping loading repository properties because the repository is owned by a user and therefore cannot have repository properties."
);
return new Success({});
}
try {
return new Success(await loadPropertiesFromApi(logger, repositoryNwo));
} catch (error3) {
logger.info(
`Failed to load repository properties: ${getErrorMessage(error3)}`
);
return new Failure(error3);
}
}
function setProperty2(properties, name, value, logger) { function setProperty2(properties, name, value, logger) {
const propertyOptions = repositoryPropertyParsers[name]; const propertyOptions = repositoryPropertyParsers[name];
if (propertyOptions.validate(value)) { if (propertyOptions.validate(value)) {
@@ -150526,6 +150534,15 @@ function parseBooleanRepositoryProperty(name, value, logger) {
function parseStringRepositoryProperty(_name, value) { function parseStringRepositoryProperty(_name, value) {
return value; return value;
} }
function parseToolsModeRepositoryProperty(name, value, logger) {
if (value !== "dynamic" /* Dynamic */ && value !== "enforce" /* Enforce */) {
logger.warning(
`Repository property '${name}' has unexpected value '${value}'. Expected 'dynamic' or 'enforce'. Defaulting to 'enforce'.`
);
return "enforce" /* Enforce */;
}
return value;
}
var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set(
Object.values(RepositoryPropertyName) Object.values(RepositoryPropertyName)
); );
@@ -151731,7 +151748,6 @@ async function initActionState({
extraQueryExclusions: [], extraQueryExclusions: [],
overlayDatabaseMode: "none" /* None */, overlayDatabaseMode: "none" /* None */,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: false,
repositoryProperties, repositoryProperties,
enableFileCoverageInformation enableFileCoverageInformation
}; };
@@ -151860,7 +151876,6 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
return validateOverlayDatabaseMode( return validateOverlayDatabaseMode(
modeEnv, modeEnv,
false, false,
true,
codeql, codeql,
languages, languages,
sourceRoot, sourceRoot,
@@ -151935,7 +151950,6 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
return validateOverlayDatabaseMode( return validateOverlayDatabaseMode(
overlayDatabaseMode, overlayDatabaseMode,
true, true,
false,
codeql, codeql,
languages, languages,
sourceRoot, sourceRoot,
@@ -151944,7 +151958,7 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
logger logger
); );
} }
async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, overlayModeSetExplicitly, codeql, languages, sourceRoot, buildMode, gitVersion, logger) { async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, codeql, languages, sourceRoot, buildMode, gitVersion, logger) {
if (buildMode !== "none" /* None */ && (await Promise.all( if (buildMode !== "none" /* None */ && (await Promise.all(
languages.map( languages.map(
async (l) => l !== "go" /* go */ && // Workaround to allow overlay analysis for Go with any build async (l) => l !== "go" /* go */ && // Workaround to allow overlay analysis for Go with any build
@@ -151988,8 +152002,7 @@ async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDataba
} }
return new Success({ return new Success({
overlayDatabaseMode, overlayDatabaseMode,
useOverlayDatabaseCaching, useOverlayDatabaseCaching
overlayModeSetExplicitly
}); });
} }
async function isTrapCachingEnabled(features, overlayDatabaseMode) { async function isTrapCachingEnabled(features, overlayDatabaseMode) {
@@ -152027,7 +152040,7 @@ function hasQueryCustomisation(userConfig) {
return isDefined2(userConfig["disable-default-queries"]) || isDefined2(userConfig.queries) || isDefined2(userConfig["query-filters"]); return isDefined2(userConfig["disable-default-queries"]) || isDefined2(userConfig.queries) || isDefined2(userConfig["query-filters"]);
} }
async function applyIncrementalAnalysisSettings(config, hasDiffRanges, codeql, logger) { async function applyIncrementalAnalysisSettings(config, hasDiffRanges, codeql, logger) {
if (config.overlayDatabaseMode === "overlay" /* Overlay */ && !hasDiffRanges && !config.overlayModeSetExplicitly) { if (config.overlayDatabaseMode === "overlay" /* Overlay */ && !hasDiffRanges) {
logger.info( logger.info(
`Reverting overlay database mode to ${"none" /* None */} because the PR diff ranges could not be computed.` `Reverting overlay database mode to ${"none" /* None */} because the PR diff ranges could not be computed.`
); );
@@ -152135,17 +152148,12 @@ async function initConfig(features, inputs) {
logger logger
); );
if (overlayDatabaseModeResult.isSuccess()) { if (overlayDatabaseModeResult.isSuccess()) {
const { const { overlayDatabaseMode, useOverlayDatabaseCaching } = overlayDatabaseModeResult.value;
overlayDatabaseMode,
useOverlayDatabaseCaching,
overlayModeSetExplicitly
} = overlayDatabaseModeResult.value;
logger.info( logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ${useOverlayDatabaseCaching ? "with" : "without"} caching.` `Using overlay database mode: ${overlayDatabaseMode} ${useOverlayDatabaseCaching ? "with" : "without"} caching.`
); );
config.overlayDatabaseMode = overlayDatabaseMode; config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching; config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
config.overlayModeSetExplicitly = overlayModeSetExplicitly;
} else { } else {
const overlayDisabledReason = overlayDatabaseModeResult.value; const overlayDisabledReason = overlayDatabaseModeResult.value;
logger.info( logger.info(
@@ -153405,7 +153413,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
); );
} else { } else {
if (allowToolcacheValueFF) { if (allowToolcacheValueFF) {
logger.warning( logger.info(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
); );
} else { } else {
@@ -153893,7 +153901,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
return cmd; return cmd;
}, },
async getVersion() { async getVersion() {
let result = getCachedCodeQlVersion(cmd); let result = getCachedCodeQlVersion();
if (result === void 0) { if (result === void 0) {
const output = await runCli(cmd, ["version", "--format=json"], { const output = await runCli(cmd, ["version", "--format=json"], {
noStreamStdout: true noStreamStdout: true
@@ -153905,12 +153913,12 @@ async function getCodeQLForCmd(cmd, checkVersion) {
`Invalid JSON output from \`version --format=json\`: ${output}` `Invalid JSON output from \`version --format=json\`: ${output}`
); );
} }
cacheCodeQlVersion(cmd, result); cacheCodeQlVersion(result);
} }
return result; return result;
}, },
async printVersion() { async printVersion() {
core11.info(JSON.stringify(await this.getVersion(), null, 2)); await runCli(cmd, ["version", "--format=json"]);
}, },
async supportsFeature(feature) { async supportsFeature(feature) {
return isSupportedToolsFeature(await this.getVersion(), feature); return isSupportedToolsFeature(await this.getVersion(), feature);
@@ -156746,7 +156754,7 @@ var fs19 = __toESM(require("fs"));
var path17 = __toESM(require("path")); var path17 = __toESM(require("path"));
var core14 = __toESM(require_core()); var core14 = __toESM(require_core());
var toolrunner4 = __toESM(require_toolrunner()); var toolrunner4 = __toESM(require_toolrunner());
var github2 = __toESM(require_github()); var github3 = __toESM(require_github());
var io6 = __toESM(require_io()); var io6 = __toESM(require_io());
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) { async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) {
logger.startGroup("Setup CodeQL tools"); logger.startGroup("Setup CodeQL tools");
@@ -156950,7 +156958,7 @@ function logFileCoverageOnPrsDeprecationWarning(logger) {
if (process.env["CODEQL_ACTION_DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION" /* DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION */]) { if (process.env["CODEQL_ACTION_DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION" /* DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION */]) {
return; return;
} }
const repositoryOwnerType = github2.context.payload.repository?.owner.type; const repositoryOwnerType = github3.context.payload.repository?.owner.type;
let message = "Starting April 2026, the CodeQL Action will skip computing file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses."; let message = "Starting April 2026, the CodeQL Action will skip computing file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses.";
const envVarOptOut = "set the `CODEQL_ACTION_FILE_COVERAGE_ON_PRS` environment variable to `true`."; const envVarOptOut = "set the `CODEQL_ACTION_FILE_COVERAGE_ON_PRS` environment variable to `true`.";
const repoPropertyOptOut = 'create a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then set this property to `true` in the repository\'s settings.'; const repoPropertyOptOut = 'create a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then set this property to `true` in the repository\'s settings.';
@@ -158734,10 +158742,50 @@ async function runWrapper3() {
var fs27 = __toESM(require("fs")); var fs27 = __toESM(require("fs"));
var path23 = __toESM(require("path")); var path23 = __toESM(require("path"));
var core21 = __toESM(require_core()); var core21 = __toESM(require_core());
var github3 = __toESM(require_github());
var io7 = __toESM(require_io()); var io7 = __toESM(require_io());
var semver10 = __toESM(require_semver2()); var semver10 = __toESM(require_semver2());
// src/config/resolve-tools-input.ts
function resolveToolsInputWithMetadata(toolsWorkflowInput, isDynamicWorkflow2, repositoryProperties, logger) {
if (toolsWorkflowInput) {
logger.info(
`Setting tools: ${toolsWorkflowInput} based on workflow input.`
);
return {
effectiveToolsInput: toolsWorkflowInput,
effectiveToolsInputSource: "workflow-input" /* WorkflowInput */,
toolsRepoPropertyMode: void 0
};
}
const toolsPropertyValue = repositoryProperties["github-codeql-tools" /* TOOLS */];
const toolsMode = repositoryProperties["github-codeql-tools-mode" /* TOOLS_MODE */] ?? "enforce" /* Enforce */;
if (toolsPropertyValue && toolsMode === "dynamic" /* Dynamic */ && !isDynamicWorkflow2) {
logger.info(
`Ignoring '${"github-codeql-tools" /* TOOLS */}' repository property because '${"github-codeql-tools-mode" /* TOOLS_MODE */}' is set to '${toolsMode}' and this is not a dynamic workflow.`
);
return {
effectiveToolsInput: void 0,
effectiveToolsInputSource: "none" /* None */,
toolsRepoPropertyMode: toolsMode
};
}
if (toolsPropertyValue) {
logger.info(
`Setting tools: ${toolsPropertyValue} based on the '${"github-codeql-tools" /* TOOLS */}' repository property (mode: '${toolsMode}').`
);
return {
effectiveToolsInput: toolsPropertyValue,
effectiveToolsInputSource: "repository-property" /* RepositoryProperty */,
toolsRepoPropertyMode: toolsMode
};
}
return {
effectiveToolsInput: void 0,
effectiveToolsInputSource: "none" /* None */,
toolsRepoPropertyMode: void 0
};
}
// src/workflow.ts // src/workflow.ts
var fs26 = __toESM(require("fs")); var fs26 = __toESM(require("fs"));
var path22 = __toESM(require("path")); var path22 = __toESM(require("path"));
@@ -159028,7 +159076,7 @@ async function sendStartingStatusReport(startedAt, config, logger) {
await sendStatusReport(statusReportBase); await sendStatusReport(statusReportBase);
} }
} }
async function sendCompletedStatusReport2(startedAt, config, configFile, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, overlayBaseDatabaseStats, dependencyCachingResults, logger, error3) { async function sendCompletedStatusReport2(startedAt, config, configFile, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, effectiveToolsInput, effectiveToolsInputSource, toolsRepoPropertyMode, overlayBaseDatabaseStats, dependencyCachingResults, logger, error3) {
const statusReportBase = await createStatusReportBase( const statusReportBase = await createStatusReportBase(
"init" /* Init */, "init" /* Init */,
getActionsStatus(error3), getActionsStatus(error3),
@@ -159046,6 +159094,9 @@ async function sendCompletedStatusReport2(startedAt, config, configFile, toolsDo
const initStatusReport = { const initStatusReport = {
...statusReportBase, ...statusReportBase,
tools_input: getOptionalInput("tools") || "", tools_input: getOptionalInput("tools") || "",
effective_tools_input: effectiveToolsInput || "",
effective_tools_input_source: effectiveToolsInputSource,
tools_repo_property_mode: toolsRepoPropertyMode || "",
tools_resolved_version: toolsVersion, tools_resolved_version: toolsVersion,
tools_source: toolsSource || "UNKNOWN" /* Unknown */, tools_source: toolsSource || "UNKNOWN" /* Unknown */,
workflow_languages: workflowLanguages || "" workflow_languages: workflowLanguages || ""
@@ -159089,6 +159140,9 @@ async function run3(startedAt) {
let toolsSource; let toolsSource;
let toolsVersion; let toolsVersion;
let zstdAvailability; let zstdAvailability;
let effectiveToolsInput;
let effectiveToolsInputSource;
let toolsRepoPropertyMode;
try { try {
initializeEnvironment(getActionVersion()); initializeEnvironment(getActionVersion());
persistInputs(); persistInputs();
@@ -159112,6 +159166,7 @@ async function run3(startedAt) {
repositoryNwo, repositoryNwo,
logger logger
); );
const repositoryProperties = repositoryPropertiesResult.orElse({});
const jobRunUuid = v4_default(); const jobRunUuid = v4_default();
logger.info(`Job run UUID is ${jobRunUuid}.`); logger.info(`Job run UUID is ${jobRunUuid}.`);
core21.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); core21.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid);
@@ -159137,12 +159192,21 @@ async function run3(startedAt) {
} }
const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type); const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const resolvedToolsInput = resolveToolsInputWithMetadata(
getOptionalInput("tools"),
isDynamicWorkflow(),
repositoryProperties,
logger
);
effectiveToolsInput = resolvedToolsInput.effectiveToolsInput;
effectiveToolsInputSource = resolvedToolsInput.effectiveToolsInputSource;
toolsRepoPropertyMode = resolvedToolsInput.toolsRepoPropertyMode;
const rawLanguages = getRawLanguagesNoAutodetect( const rawLanguages = getRawLanguagesNoAutodetect(
getOptionalInput("languages") getOptionalInput("languages")
); );
const useOverlayAwareDefaultCliVersion = analysisKinds?.length === 1 && analysisKinds[0] === "code-scanning" /* CodeScanning */; const useOverlayAwareDefaultCliVersion = analysisKinds?.length === 1 && analysisKinds[0] === "code-scanning" /* CodeScanning */;
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"), effectiveToolsInput,
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
@@ -159178,7 +159242,6 @@ async function run3(startedAt) {
} }
analysisKinds = await getAnalysisKinds(logger, features); analysisKinds = await getAnalysisKinds(logger, features);
const debugMode = getOptionalInput("debug") === "true" || core21.isDebug(); const debugMode = getOptionalInput("debug") === "true" || core21.isDebug();
const repositoryProperties = repositoryPropertiesResult.orElse({});
const fileCoverageResult = await getFileCoverageInformationEnabled( const fileCoverageResult = await getFileCoverageInformationEnabled(
debugMode, debugMode,
codeql, codeql,
@@ -159476,6 +159539,9 @@ exec ${goBinaryPath} "$@"`
toolsFeatureFlagsValid, toolsFeatureFlagsValid,
toolsSource, toolsSource,
toolsVersion, toolsVersion,
effectiveToolsInput,
effectiveToolsInputSource,
toolsRepoPropertyMode,
overlayBaseDatabaseStats, overlayBaseDatabaseStats,
dependencyCachingStatus, dependencyCachingStatus,
logger, logger,
@@ -159493,31 +159559,14 @@ exec ${goBinaryPath} "$@"`
toolsFeatureFlagsValid, toolsFeatureFlagsValid,
toolsSource, toolsSource,
toolsVersion, toolsVersion,
effectiveToolsInput,
effectiveToolsInputSource,
toolsRepoPropertyMode,
overlayBaseDatabaseStats, overlayBaseDatabaseStats,
dependencyCachingStatus, dependencyCachingStatus,
logger logger
); );
} }
async function loadRepositoryProperties(repositoryNwo, logger) {
const repositoryOwnerType = github3.context.payload.repository?.owner.type;
logger.debug(
`Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`
);
if (repositoryOwnerType === "User") {
logger.debug(
"Skipping loading repository properties because the repository is owned by a user and therefore cannot have repository properties."
);
return new Success({});
}
try {
return new Success(await loadPropertiesFromApi(logger, repositoryNwo));
} catch (error3) {
logger.warning(
`Failed to load repository properties: ${getErrorMessage(error3)}`
);
return new Failure(error3);
}
}
async function recordZstdAvailability(config, zstdAvailability) { async function recordZstdAvailability(config, zstdAvailability) {
addNoLanguageDiagnostic( addNoLanguageDiagnostic(
config, config,
@@ -160086,7 +160135,7 @@ async function runWrapper6() {
// src/setup-codeql-action.ts // src/setup-codeql-action.ts
var core24 = __toESM(require_core()); var core24 = __toESM(require_core());
async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger, error3) { async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, effectiveToolsInput, effectiveToolsInputSource, toolsRepoPropertyMode, logger, error3) {
const statusReportBase = await createStatusReportBase( const statusReportBase = await createStatusReportBase(
"setup-codeql" /* SetupCodeQL */, "setup-codeql" /* SetupCodeQL */,
getActionsStatus(error3), getActionsStatus(error3),
@@ -160103,6 +160152,9 @@ async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport,
const initStatusReport = { const initStatusReport = {
...statusReportBase, ...statusReportBase,
tools_input: getOptionalInput("tools") || "", tools_input: getOptionalInput("tools") || "",
effective_tools_input: effectiveToolsInput || "",
effective_tools_input_source: effectiveToolsInputSource,
tools_repo_property_mode: toolsRepoPropertyMode || "",
tools_resolved_version: toolsVersion, tools_resolved_version: toolsVersion,
tools_source: toolsSource || "UNKNOWN" /* Unknown */, tools_source: toolsSource || "UNKNOWN" /* Unknown */,
workflow_languages: "" workflow_languages: ""
@@ -160123,6 +160175,9 @@ async function run6(startedAt) {
let toolsFeatureFlagsValid; let toolsFeatureFlagsValid;
let toolsSource; let toolsSource;
let toolsVersion; let toolsVersion;
let effectiveToolsInput;
let effectiveToolsInputSource;
let toolsRepoPropertyMode;
try { try {
initializeEnvironment(getActionVersion()); initializeEnvironment(getActionVersion());
const apiDetails = { const apiDetails = {
@@ -160157,12 +160212,26 @@ async function run6(startedAt) {
} }
const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type); const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const repositoryPropertiesResult = await loadRepositoryProperties(
repositoryNwo,
logger
);
const repositoryProperties = repositoryPropertiesResult.orElse({});
const resolvedToolsInput = resolveToolsInputWithMetadata(
getOptionalInput("tools"),
isDynamicWorkflow(),
repositoryProperties,
logger
);
effectiveToolsInput = resolvedToolsInput.effectiveToolsInput;
effectiveToolsInputSource = resolvedToolsInput.effectiveToolsInputSource;
toolsRepoPropertyMode = resolvedToolsInput.toolsRepoPropertyMode;
const rawLanguages = getRawLanguagesNoAutodetect( const rawLanguages = getRawLanguagesNoAutodetect(
getOptionalInput("languages") getOptionalInput("languages")
); );
const analysisKinds = await getAnalysisKinds(logger, features); const analysisKinds = await getAnalysisKinds(logger, features);
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"), effectiveToolsInput,
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
@@ -160203,6 +160272,9 @@ async function run6(startedAt) {
toolsFeatureFlagsValid, toolsFeatureFlagsValid,
toolsSource, toolsSource,
toolsVersion, toolsVersion,
effectiveToolsInput,
effectiveToolsInputSource,
toolsRepoPropertyMode,
logger logger
); );
} }
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "codeql", "name": "codeql",
"version": "4.36.2", "version": "4.36.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "codeql", "name": "codeql",
"version": "4.36.2", "version": "4.36.1",
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"pr-checks" "pr-checks"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "codeql", "name": "codeql",
"version": "4.36.2", "version": "4.36.1",
"private": true, "private": true,
"description": "CodeQL action", "description": "CodeQL action",
"scripts": { "scripts": {
+1 -1
View File
@@ -30,7 +30,7 @@ import {
} from "./dependency-caching"; } from "./dependency-caching";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { initFeatures } from "./feature-flags"; import { initFeatures } from "./feature-flags";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { getActionsLogger, Logger } from "./logging"; import { getActionsLogger, Logger } from "./logging";
import { cleanupAndUploadOverlayBaseDatabaseToCache } from "./overlay/caching"; import { cleanupAndUploadOverlayBaseDatabaseToCache } from "./overlay/caching";
import { getRepositoryNwo } from "./repository"; import { getRepositoryNwo } from "./repository";
+1 -1
View File
@@ -14,7 +14,7 @@ import {
} from "./analyze"; } from "./analyze";
import { createStubCodeQL } from "./codeql"; import { createStubCodeQL } from "./codeql";
import { Feature } from "./feature-flags"; import { Feature } from "./feature-flags";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { import {
setupTests, setupTests,
+1 -1
View File
@@ -21,7 +21,7 @@ import {
} from "./diff-informed-analysis-utils"; } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { FeatureEnablement, Feature } from "./feature-flags"; import { FeatureEnablement, Feature } from "./feature-flags";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages/index";
import { Logger, withGroupAsync } from "./logging"; import { Logger, withGroupAsync } from "./logging";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
import type * as sarif from "./sarif"; import type * as sarif from "./sarif";
+1 -1
View File
@@ -10,7 +10,7 @@ import { determineAutobuildLanguages, runAutobuild } from "./autobuild";
import { getCodeQL } from "./codeql"; import { getCodeQL } from "./codeql";
import { Config, getConfig } from "./config-utils"; import { Config, getConfig } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { Language } from "./languages"; import { Language } from "./languages/index";
import { Logger, getActionsLogger } from "./logging"; import { Logger, getActionsLogger } from "./logging";
import { import {
StatusReportBase, StatusReportBase,
+1 -1
View File
@@ -7,7 +7,7 @@ import * as configUtils from "./config-utils";
import { DocUrl } from "./doc-url"; import { DocUrl } from "./doc-url";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { Feature, featureConfig, initFeatures } from "./feature-flags"; import { Feature, featureConfig, initFeatures } from "./feature-flags";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { getRepositoryNwo } from "./repository"; import { getRepositoryNwo } from "./repository";
import { asyncFilter, BuildMode } from "./util"; import { asyncFilter, BuildMode } from "./util";
+1 -1
View File
@@ -21,7 +21,7 @@ import {
import type { Config } from "./config-utils"; import type { Config } from "./config-utils";
import * as defaults from "./defaults.json"; import * as defaults from "./defaults.json";
import { DocUrl } from "./doc-url"; import { DocUrl } from "./doc-url";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { ToolsSource } from "./setup-codeql"; import { ToolsSource } from "./setup-codeql";
import { import {
+4 -5
View File
@@ -22,7 +22,7 @@ import {
FeatureEnablement, FeatureEnablement,
} from "./feature-flags"; } from "./feature-flags";
import { isAnalyzingDefaultBranch } from "./git-utils"; import { isAnalyzingDefaultBranch } from "./git-utils";
import { Language } from "./languages"; import { Language } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "./overlay"; import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "./overlay";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
@@ -523,7 +523,7 @@ async function getCodeQLForCmd(
return cmd; return cmd;
}, },
async getVersion() { async getVersion() {
let result = util.getCachedCodeQlVersion(cmd); let result = util.getCachedCodeQlVersion();
if (result === undefined) { if (result === undefined) {
const output = await runCli(cmd, ["version", "--format=json"], { const output = await runCli(cmd, ["version", "--format=json"], {
noStreamStdout: true, noStreamStdout: true,
@@ -535,13 +535,12 @@ async function getCodeQLForCmd(
`Invalid JSON output from \`version --format=json\`: ${output}`, `Invalid JSON output from \`version --format=json\`: ${output}`,
); );
} }
util.cacheCodeQlVersion(cmd, result); util.cacheCodeQlVersion(result);
} }
return result; return result;
}, },
async printVersion() { async printVersion() {
// Reuse the cached version information rather than invoking the CLI again. await runCli(cmd, ["version", "--format=json"]);
core.info(JSON.stringify(await this.getVersion(), null, 2));
}, },
async supportsFeature(feature: ToolsFeature) { async supportsFeature(feature: ToolsFeature) {
return isSupportedToolsFeature(await this.getVersion(), feature); return isSupportedToolsFeature(await this.getVersion(), feature);
+27 -71
View File
@@ -18,7 +18,7 @@ import { Feature } from "./feature-flags";
import { RepositoryProperties } from "./feature-flags/properties"; import { RepositoryProperties } from "./feature-flags/properties";
import * as gitUtils from "./git-utils"; import * as gitUtils from "./git-utils";
import { GitVersionInfo } from "./git-utils"; import { GitVersionInfo } from "./git-utils";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages/index";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay"; import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
import * as overlayDiagnostics from "./overlay/diagnostics"; import * as overlayDiagnostics from "./overlay/diagnostics";
@@ -1044,7 +1044,6 @@ const checkOverlayEnablementMacro = makeMacro({
| { | {
overlayDatabaseMode: OverlayDatabaseMode; overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean; useOverlayDatabaseCaching: boolean;
overlayModeSetExplicitly?: boolean;
} }
| { | {
disabledReason: OverlayDisabledReason; disabledReason: OverlayDisabledReason;
@@ -1125,13 +1124,7 @@ const checkOverlayEnablementMacro = makeMacro({
if ("disabledReason" in expected) { if ("disabledReason" in expected) {
t.deepEqual(result, new Failure(expected.disabledReason)); t.deepEqual(result, new Failure(expected.disabledReason));
} else { } else {
t.deepEqual( t.deepEqual(result, new Success(expected));
result,
new Success({
overlayModeSetExplicitly: false,
...expected,
}),
);
} }
} finally { } finally {
// Restore the original environment // Restore the original environment
@@ -1150,7 +1143,6 @@ checkOverlayEnablementMacro.serial(
{ {
overlayDatabaseMode: OverlayDatabaseMode.Overlay, overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: true,
}, },
); );
@@ -1162,7 +1154,6 @@ checkOverlayEnablementMacro.serial(
{ {
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase, overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: true,
}, },
); );
@@ -1821,7 +1812,6 @@ checkOverlayEnablementMacro.serial(
{ {
overlayDatabaseMode: OverlayDatabaseMode.Overlay, overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: true,
}, },
); );
@@ -1834,7 +1824,6 @@ checkOverlayEnablementMacro.serial(
{ {
overlayDatabaseMode: OverlayDatabaseMode.Overlay, overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: true,
}, },
); );
@@ -1931,7 +1920,6 @@ checkOverlayEnablementMacro.serial(
{ {
overlayDatabaseMode: OverlayDatabaseMode.Overlay, overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: true,
}, },
); );
@@ -1977,7 +1965,6 @@ checkOverlayEnablementMacro.serial(
{ {
overlayDatabaseMode: OverlayDatabaseMode.Overlay, overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: true,
}, },
); );
@@ -2195,64 +2182,33 @@ test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions w
]); ]);
}); });
test.serial( test("applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable", async (t) => {
"applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable", const config = createTestConfig({
async (t) => { overlayDatabaseMode: OverlayDatabaseMode.Overlay,
const config = createTestConfig({ });
overlayDatabaseMode: OverlayDatabaseMode.Overlay, config.useOverlayDatabaseCaching = true;
}); const codeql = createStubCodeQL({});
config.useOverlayDatabaseCaching = true; const logger = getRunnerLogger(true);
const codeql = createStubCodeQL({}); const addDiagnosticsStub = sinon
const logger = getRunnerLogger(true); .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
const addDiagnosticsStub = sinon .resolves();
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
.resolves();
await configUtils.applyIncrementalAnalysisSettings( await configUtils.applyIncrementalAnalysisSettings(
config, config,
false, false,
codeql, codeql,
logger, logger,
); );
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None); t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.is(config.useOverlayDatabaseCaching, false); t.is(config.useOverlayDatabaseCaching, false);
t.deepEqual(config.extraQueryExclusions, []); t.deepEqual(config.extraQueryExclusions, []);
t.true(addDiagnosticsStub.calledOnce); t.true(addDiagnosticsStub.calledOnce);
t.is( t.is(
addDiagnosticsStub.firstCall.args[2], addDiagnosticsStub.firstCall.args[2],
OverlayDisabledReason.DiffInformedAnalysisNotEnabled, OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
); );
}, });
);
test.serial(
"applyIncrementalAnalysisSettings: keeps overlay mode when set explicitly and diff ranges are unavailable",
async (t) => {
const config = createTestConfig({
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
});
config.useOverlayDatabaseCaching = false;
config.overlayModeSetExplicitly = true;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
const addDiagnosticsStub = sinon
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
.resolves();
await configUtils.applyIncrementalAnalysisSettings(
config,
false,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
t.is(config.useOverlayDatabaseCaching, false);
t.deepEqual(config.extraQueryExclusions, []);
t.true(addDiagnosticsStub.notCalled);
},
);
test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only runs", async (t) => { test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only runs", async (t) => {
const config = createTestConfig({}); const config = createTestConfig({});
+11 -27
View File
@@ -48,7 +48,7 @@ import {
hasSubmodules, hasSubmodules,
isAnalyzingDefaultBranch, isAnalyzingDefaultBranch,
} from "./git-utils"; } from "./git-utils";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay"; import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
import { import {
@@ -243,11 +243,6 @@ export interface Config {
*/ */
useOverlayDatabaseCaching: boolean; useOverlayDatabaseCaching: boolean;
/**
* Whether the overlay database mode was set explicitly.
*/
overlayModeSetExplicitly: boolean;
/** /**
* A partial mapping from repository properties that affect us to their values. * A partial mapping from repository properties that affect us to their values.
*/ */
@@ -578,7 +573,6 @@ export async function initActionState(
extraQueryExclusions: [], extraQueryExclusions: [],
overlayDatabaseMode: OverlayDatabaseMode.None, overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: false,
repositoryProperties, repositoryProperties,
enableFileCoverageInformation, enableFileCoverageInformation,
}; };
@@ -778,7 +772,6 @@ async function checkRunnerResources(
interface EnabledOverlayConfig { interface EnabledOverlayConfig {
overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>; overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>;
useOverlayDatabaseCaching: boolean; useOverlayDatabaseCaching: boolean;
overlayModeSetExplicitly: boolean;
} }
/** /**
@@ -833,7 +826,6 @@ export async function checkOverlayEnablement(
return validateOverlayDatabaseMode( return validateOverlayDatabaseMode(
modeEnv, modeEnv,
false, false,
true,
codeql, codeql,
languages, languages,
sourceRoot, sourceRoot,
@@ -925,7 +917,6 @@ export async function checkOverlayEnablement(
return validateOverlayDatabaseMode( return validateOverlayDatabaseMode(
overlayDatabaseMode, overlayDatabaseMode,
true, true,
false,
codeql, codeql,
languages, languages,
sourceRoot, sourceRoot,
@@ -944,7 +935,6 @@ export async function checkOverlayEnablement(
async function validateOverlayDatabaseMode( async function validateOverlayDatabaseMode(
overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>, overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>,
useOverlayDatabaseCaching: boolean, useOverlayDatabaseCaching: boolean,
overlayModeSetExplicitly: boolean,
codeql: CodeQL, codeql: CodeQL,
languages: Language[], languages: Language[],
sourceRoot: string, sourceRoot: string,
@@ -1016,7 +1006,6 @@ async function validateOverlayDatabaseMode(
return new Success({ return new Success({
overlayDatabaseMode, overlayDatabaseMode,
useOverlayDatabaseCaching, useOverlayDatabaseCaching,
overlayModeSetExplicitly,
}); });
} }
@@ -1091,14 +1080,14 @@ function hasQueryCustomisation(userConfig: UserConfig): boolean {
/** /**
* Finalize the incremental-analysis configuration for this run. * Finalize the incremental-analysis configuration for this run.
* *
* Overlay analysis has only been validated in combination with diff-informed analysis, so if * Overlay analysis has only been validated in combination with diff-informed
* `Overlay` mode was selected for a pull request but the diff ranges could not be computed, fall * analysis, so if `Overlay` mode was selected for a pull request but the diff
* back to a full non-overlay analysis. If the overlay mode was set explicitly, this fallback does * ranges could not be computed, fall back to a full non-overlay analysis.
* not apply.
* *
* Query exclusions for incremental-only queries are then applied whenever the diff ranges are * Query exclusions for incremental-only queries are then applied whenever the
* available — which, after the fallback above, is exactly the set of runs where any kind of * diff ranges are available — which, after the fallback above, is exactly the
* incremental analysis (overlay or diff-informed) is in effect. * set of runs where any kind of incremental analysis (overlay or
* diff-informed) is in effect.
*/ */
export async function applyIncrementalAnalysisSettings( export async function applyIncrementalAnalysisSettings(
config: Config, config: Config,
@@ -1108,8 +1097,7 @@ export async function applyIncrementalAnalysisSettings(
): Promise<void> { ): Promise<void> {
if ( if (
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay && config.overlayDatabaseMode === OverlayDatabaseMode.Overlay &&
!hasDiffRanges && !hasDiffRanges
!config.overlayModeSetExplicitly
) { ) {
logger.info( logger.info(
`Reverting overlay database mode to ${OverlayDatabaseMode.None} ` + `Reverting overlay database mode to ${OverlayDatabaseMode.None} ` +
@@ -1263,18 +1251,14 @@ export async function initConfig(
logger, logger,
); );
if (overlayDatabaseModeResult.isSuccess()) { if (overlayDatabaseModeResult.isSuccess()) {
const { const { overlayDatabaseMode, useOverlayDatabaseCaching } =
overlayDatabaseMode, overlayDatabaseModeResult.value;
useOverlayDatabaseCaching,
overlayModeSetExplicitly,
} = overlayDatabaseModeResult.value;
logger.info( logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ` + `Using overlay database mode: ${overlayDatabaseMode} ` +
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`, `${useOverlayDatabaseCaching ? "with" : "without"} caching.`,
); );
config.overlayDatabaseMode = overlayDatabaseMode; config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching; config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
config.overlayModeSetExplicitly = overlayModeSetExplicitly;
} else { } else {
const overlayDisabledReason = overlayDatabaseModeResult.value; const overlayDisabledReason = overlayDatabaseModeResult.value;
logger.info( logger.info(
+280
View File
@@ -0,0 +1,280 @@
import test from "ava";
import {
EffectiveToolsInputSource,
resolveToolsInput,
resolveToolsInputWithMetadata,
} from "../config/resolve-tools-input";
import {
RepositoryPropertyName,
ToolsModeRepositoryPropertyValue,
} from "../feature-flags/properties";
import type { RepositoryProperties } from "../feature-flags/properties";
import {
getRecordingLogger,
LoggedMessage,
setupTests,
} from "../testing-utils";
setupTests(test);
test("resolveToolsInput returns undefined when no tools input or repository property is set", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const result = resolveToolsInput(undefined, false, {}, logger);
t.is(result, undefined);
t.is(loggedMessages.length, 0);
});
test("resolveToolsInput returns workflow input when only workflow input is provided", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const result = resolveToolsInput("latest", false, {}, logger);
t.is(result, "latest");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: latest based on workflow input.",
);
});
test("resolveToolsInput returns repository property when only repository property is provided", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
};
const result = resolveToolsInput(
undefined,
false,
repositoryProperties,
logger,
);
t.is(result, "toolcache");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: toolcache based on the 'github-codeql-tools' repository property (mode: 'enforce').",
);
});
test("resolveToolsInput prioritizes workflow input over repository property", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
};
const result = resolveToolsInput(
"nightly",
false,
repositoryProperties,
logger,
);
t.is(result, "nightly");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: nightly based on workflow input.",
);
});
test("resolveToolsInput treats empty string workflow input as not set", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
};
const result = resolveToolsInput("", false, repositoryProperties, logger);
t.is(result, "toolcache");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: toolcache based on the 'github-codeql-tools' repository property (mode: 'enforce').",
);
});
test("resolveToolsInput returns undefined when repository property is undefined", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: undefined,
};
const result = resolveToolsInput(
undefined,
false,
repositoryProperties,
logger,
);
t.is(result, undefined);
t.is(loggedMessages.length, 0);
});
test("resolveToolsInput returns repository property when workflow input is not set", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
};
const result = resolveToolsInput(
undefined,
false,
repositoryProperties,
logger,
);
t.is(result, "toolcache");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: toolcache based on the 'github-codeql-tools' repository property (mode: 'enforce').",
);
});
test("resolveToolsInput does not log when workflow input and repository property are not set", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const result = resolveToolsInput(undefined, false, {}, logger);
t.is(result, undefined);
t.is(loggedMessages.length, 0);
});
test("resolveToolsInput applies tools property in enforce mode for static workflows", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
[RepositoryPropertyName.TOOLS_MODE]:
ToolsModeRepositoryPropertyValue.Enforce,
};
const result = resolveToolsInput(
undefined,
false,
repositoryProperties,
logger,
);
t.is(result, "toolcache");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: toolcache based on the 'github-codeql-tools' repository property (mode: 'enforce').",
);
});
test("resolveToolsInput applies tools property in dynamic mode for dynamic workflows", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
[RepositoryPropertyName.TOOLS_MODE]:
ToolsModeRepositoryPropertyValue.Dynamic,
};
const result = resolveToolsInput(
undefined,
true,
repositoryProperties,
logger,
);
t.is(result, "toolcache");
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Setting tools: toolcache based on the 'github-codeql-tools' repository property (mode: 'dynamic').",
);
});
test("resolveToolsInput ignores tools property in dynamic mode for static workflows", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const repositoryProperties: RepositoryProperties = {
[RepositoryPropertyName.TOOLS]: "toolcache",
[RepositoryPropertyName.TOOLS_MODE]:
ToolsModeRepositoryPropertyValue.Dynamic,
};
const result = resolveToolsInput(
undefined,
false,
repositoryProperties,
logger,
);
t.is(result, undefined);
t.is(loggedMessages.length, 1);
t.is(
loggedMessages[0].message,
"Ignoring 'github-codeql-tools' repository property because 'github-codeql-tools-mode' is set to 'dynamic' and this is not a dynamic workflow.",
);
});
test("resolveToolsInputWithMetadata reports workflow input source", (t) => {
const logger = getRecordingLogger([]);
const result = resolveToolsInputWithMetadata("latest", false, {}, logger);
t.is(result.effectiveToolsInput, "latest");
t.is(
result.effectiveToolsInputSource,
EffectiveToolsInputSource.WorkflowInput,
);
t.is(result.toolsRepoPropertyMode, undefined);
});
test("resolveToolsInputWithMetadata reports repository property source and mode", (t) => {
const logger = getRecordingLogger([]);
const result = resolveToolsInputWithMetadata(
undefined,
false,
{
[RepositoryPropertyName.TOOLS]: "toolcache",
[RepositoryPropertyName.TOOLS_MODE]:
ToolsModeRepositoryPropertyValue.Enforce,
},
logger,
);
t.is(result.effectiveToolsInput, "toolcache");
t.is(
result.effectiveToolsInputSource,
EffectiveToolsInputSource.RepositoryProperty,
);
t.is(result.toolsRepoPropertyMode, ToolsModeRepositoryPropertyValue.Enforce);
});
test("resolveToolsInputWithMetadata reports dynamic-mode skip on static workflows", (t) => {
const logger = getRecordingLogger([]);
const result = resolveToolsInputWithMetadata(
undefined,
false,
{
[RepositoryPropertyName.TOOLS]: "toolcache",
[RepositoryPropertyName.TOOLS_MODE]:
ToolsModeRepositoryPropertyValue.Dynamic,
},
logger,
);
t.is(result.effectiveToolsInput, undefined);
t.is(result.effectiveToolsInputSource, EffectiveToolsInputSource.None);
t.is(result.toolsRepoPropertyMode, ToolsModeRepositoryPropertyValue.Dynamic);
});
+100
View File
@@ -0,0 +1,100 @@
import {
RepositoryProperties,
RepositoryPropertyName,
ToolsModeRepositoryPropertyValue,
} from "../feature-flags/properties";
import { Logger } from "../logging";
export enum EffectiveToolsInputSource {
WorkflowInput = "workflow-input",
RepositoryProperty = "repository-property",
None = "none",
}
export type ResolvedToolsInput = {
effectiveToolsInput: string | undefined;
effectiveToolsInputSource: EffectiveToolsInputSource;
toolsRepoPropertyMode: ToolsModeRepositoryPropertyValue | undefined;
};
/**
* Resolves the effective tools input by combining the workflow input and repository properties.
* The explicit `tools` workflow input takes precedence. If none is provided,
* falls back to the repository property (if set). The optional
* `github-codeql-tools-mode` repository property controls whether this fallback
* applies to all workflows (`enforce`) or only dynamic workflows (`dynamic`).
*
* @param toolsWorkflowInput - The value of the `tools` workflow input, if provided.
* @param isDynamicWorkflow - Whether the current workflow is dynamic.
* @param repositoryProperties - The parsed repository properties.
* @param logger - Logger for outputting resolution messages.
* @returns The effective tools input value.
*/
export function resolveToolsInput(
toolsWorkflowInput: string | undefined,
isDynamicWorkflow: boolean,
repositoryProperties: RepositoryProperties,
logger: Logger,
): string | undefined {
return resolveToolsInputWithMetadata(
toolsWorkflowInput,
isDynamicWorkflow,
repositoryProperties,
logger,
).effectiveToolsInput;
}
export function resolveToolsInputWithMetadata(
toolsWorkflowInput: string | undefined,
isDynamicWorkflow: boolean,
repositoryProperties: RepositoryProperties,
logger: Logger,
): ResolvedToolsInput {
if (toolsWorkflowInput) {
logger.info(
`Setting tools: ${toolsWorkflowInput} based on workflow input.`,
);
return {
effectiveToolsInput: toolsWorkflowInput,
effectiveToolsInputSource: EffectiveToolsInputSource.WorkflowInput,
toolsRepoPropertyMode: undefined,
};
}
const toolsPropertyValue = repositoryProperties[RepositoryPropertyName.TOOLS];
const toolsMode =
repositoryProperties[RepositoryPropertyName.TOOLS_MODE] ??
ToolsModeRepositoryPropertyValue.Enforce;
if (
toolsPropertyValue &&
toolsMode === ToolsModeRepositoryPropertyValue.Dynamic &&
!isDynamicWorkflow
) {
logger.info(
`Ignoring '${RepositoryPropertyName.TOOLS}' repository property because '${RepositoryPropertyName.TOOLS_MODE}' is set to '${toolsMode}' and this is not a dynamic workflow.`,
);
return {
effectiveToolsInput: undefined,
effectiveToolsInputSource: EffectiveToolsInputSource.None,
toolsRepoPropertyMode: toolsMode,
};
}
if (toolsPropertyValue) {
logger.info(
`Setting tools: ${toolsPropertyValue} based on the '${RepositoryPropertyName.TOOLS}' repository property (mode: '${toolsMode}').`,
);
return {
effectiveToolsInput: toolsPropertyValue,
effectiveToolsInputSource: EffectiveToolsInputSource.RepositoryProperty,
toolsRepoPropertyMode: toolsMode,
};
}
return {
effectiveToolsInput: undefined,
effectiveToolsInputSource: EffectiveToolsInputSource.None,
toolsRepoPropertyMode: undefined,
};
}
+1 -1
View File
@@ -12,7 +12,7 @@ import { createStubCodeQL } from "./codeql";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { cleanupAndUploadDatabases } from "./database-upload"; import { cleanupAndUploadDatabases } from "./database-upload";
import * as gitUtils from "./git-utils"; import * as gitUtils from "./git-utils";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { RepositoryNwo } from "./repository"; import { RepositoryNwo } from "./repository";
import { import {
checkExpectedLogMessages, checkExpectedLogMessages,
+1 -1
View File
@@ -13,7 +13,7 @@ import { type CodeQL } from "./codeql";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import * as json from "./json"; import * as json from "./json";
import { Language } from "./languages"; import { Language } from "./languages/index";
import { Logger, withGroup } from "./logging"; import { Logger, withGroup } from "./logging";
import { import {
isSafeArtifactUpload, isSafeArtifactUpload,
+1 -1
View File
@@ -27,7 +27,7 @@ import {
CacheStoreResult, CacheStoreResult,
} from "./dependency-caching"; } from "./dependency-caching";
import { Feature } from "./feature-flags"; import { Feature } from "./feature-flags";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { import {
setupTests, setupTests,
createFeatures, createFeatures,
+1 -1
View File
@@ -11,7 +11,7 @@ import { CodeQL } from "./codeql";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature, FeatureEnablement } from "./feature-flags";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { getErrorMessage, getRequiredEnvParam } from "./util"; import { getErrorMessage, getRequiredEnvParam } from "./util";
+1 -1
View File
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, writeFileSync } from "fs";
import path from "path"; import path from "path";
import type { Config } from "./config-utils"; import type { Config } from "./config-utils";
import { Language } from "./languages"; import { Language } from "./languages/index";
import { getActionsLogger } from "./logging"; import { getActionsLogger } from "./logging";
import { getCodeQLDatabasePath } from "./util"; import { getCodeQLDatabasePath } from "./util";
-6
View File
@@ -17,12 +17,6 @@ export enum EnvVar {
*/ */
CLI_VERBOSITY = "CODEQL_VERBOSITY", CLI_VERBOSITY = "CODEQL_VERBOSITY",
/**
* `PersistedVersionInfo` for the CodeQL CLI, so later Actions steps can reuse it instead of
* invoking `codeql version` again.
*/
CODEQL_VERSION_INFO = "CODEQL_ACTION_CLI_VERSION_INFO",
/** Whether the CodeQL Action has invoked the Go autobuilder. */ /** Whether the CodeQL Action has invoked the Go autobuilder. */
DID_AUTOBUILD_GOLANG = "CODEQL_ACTION_DID_AUTOBUILD_GOLANG", DID_AUTOBUILD_GOLANG = "CODEQL_ACTION_DID_AUTOBUILD_GOLANG",
+39 -1
View File
@@ -78,6 +78,8 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => {
url: "", url: "",
data: [ data: [
{ property_name: "github-codeql-extra-queries", value: "+queries" }, { property_name: "github-codeql-extra-queries", value: "+queries" },
{ property_name: "github-codeql-tools", value: "toolcache" },
{ property_name: "github-codeql-tools-mode", value: "dynamic" },
{ property_name: "unknown-property", value: "something" }, { property_name: "unknown-property", value: "something" },
] satisfies properties.GitHubPropertiesResponse, ] satisfies properties.GitHubPropertiesResponse,
}); });
@@ -87,9 +89,45 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => {
logger, logger,
mockRepositoryNwo, mockRepositoryNwo,
); );
t.deepEqual(response, { "github-codeql-extra-queries": "+queries" }); t.deepEqual(response, {
"github-codeql-extra-queries": "+queries",
"github-codeql-tools": "toolcache",
"github-codeql-tools-mode": "dynamic",
});
}); });
test.serial(
"loadPropertiesFromApi warns if tools mode property has unexpected value",
async (t) => {
sinon.stub(api, "getRepositoryProperties").resolves({
headers: {},
status: 200,
url: "",
data: [
{
property_name: "github-codeql-tools-mode",
value: "all",
},
] satisfies properties.GitHubPropertiesResponse,
});
const logger = getRunnerLogger(true);
const warningSpy = sinon.spy(logger, "warning");
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
const response = await properties.loadPropertiesFromApi(
logger,
mockRepositoryNwo,
);
t.deepEqual(response, {
"github-codeql-tools-mode": "enforce",
});
t.true(warningSpy.calledOnce);
t.is(
warningSpy.firstCall.args[0],
"Repository property 'github-codeql-tools-mode' has unexpected value 'all'. Expected 'dynamic' or 'enforce'. Defaulting to 'enforce'.",
);
},
);
test.serial("loadPropertiesFromApi parses true boolean property", async (t) => { test.serial("loadPropertiesFromApi parses true boolean property", async (t) => {
sinon.stub(api, "getRepositoryProperties").resolves({ sinon.stub(api, "getRepositoryProperties").resolves({
headers: {}, headers: {},
+70
View File
@@ -1,7 +1,10 @@
import * as github from "@actions/github";
import { isDynamicWorkflow } from "../actions-util"; import { isDynamicWorkflow } from "../actions-util";
import { getRepositoryProperties } from "../api-client"; import { getRepositoryProperties } from "../api-client";
import { Logger } from "../logging"; import { Logger } from "../logging";
import { RepositoryNwo } from "../repository"; import { RepositoryNwo } from "../repository";
import { getErrorMessage, Result, Success, Failure } from "../util";
/** The common prefix that we expect all of our repository properties to have. */ /** The common prefix that we expect all of our repository properties to have. */
export const GITHUB_CODEQL_PROPERTY_PREFIX = "github-codeql-"; export const GITHUB_CODEQL_PROPERTY_PREFIX = "github-codeql-";
@@ -13,6 +16,13 @@ export enum RepositoryPropertyName {
DISABLE_OVERLAY = "github-codeql-disable-overlay", DISABLE_OVERLAY = "github-codeql-disable-overlay",
EXTRA_QUERIES = "github-codeql-extra-queries", EXTRA_QUERIES = "github-codeql-extra-queries",
FILE_COVERAGE_ON_PRS = "github-codeql-file-coverage-on-prs", FILE_COVERAGE_ON_PRS = "github-codeql-file-coverage-on-prs",
TOOLS = "github-codeql-tools",
TOOLS_MODE = "github-codeql-tools-mode",
}
export enum ToolsModeRepositoryPropertyValue {
Dynamic = "dynamic",
Enforce = "enforce",
} }
/** Parsed types of the known repository properties. */ /** Parsed types of the known repository properties. */
@@ -20,6 +30,8 @@ export type AllRepositoryProperties = {
[RepositoryPropertyName.DISABLE_OVERLAY]: boolean; [RepositoryPropertyName.DISABLE_OVERLAY]: boolean;
[RepositoryPropertyName.EXTRA_QUERIES]: string; [RepositoryPropertyName.EXTRA_QUERIES]: string;
[RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: boolean; [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: boolean;
[RepositoryPropertyName.TOOLS]: string;
[RepositoryPropertyName.TOOLS_MODE]: ToolsModeRepositoryPropertyValue;
}; };
/** Parsed repository properties. */ /** Parsed repository properties. */
@@ -30,6 +42,8 @@ export type RepositoryPropertyApiType = {
[RepositoryPropertyName.DISABLE_OVERLAY]: string; [RepositoryPropertyName.DISABLE_OVERLAY]: string;
[RepositoryPropertyName.EXTRA_QUERIES]: string; [RepositoryPropertyName.EXTRA_QUERIES]: string;
[RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: string; [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: string;
[RepositoryPropertyName.TOOLS]: string;
[RepositoryPropertyName.TOOLS_MODE]: string;
}; };
/** The type of functions which take the `value` from the API and try to convert it to the type we want. */ /** The type of functions which take the `value` from the API and try to convert it to the type we want. */
@@ -77,6 +91,11 @@ const repositoryPropertyParsers: {
[RepositoryPropertyName.DISABLE_OVERLAY]: booleanProperty, [RepositoryPropertyName.DISABLE_OVERLAY]: booleanProperty,
[RepositoryPropertyName.EXTRA_QUERIES]: stringProperty, [RepositoryPropertyName.EXTRA_QUERIES]: stringProperty,
[RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: booleanProperty, [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: booleanProperty,
[RepositoryPropertyName.TOOLS]: stringProperty,
[RepositoryPropertyName.TOOLS_MODE]: {
validate: isString,
parse: parseToolsModeRepositoryProperty,
},
}; };
/** /**
@@ -172,6 +191,38 @@ export async function loadPropertiesFromApi(
} }
} }
/**
* Loads [repository properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) if applicable.
*/
export async function loadRepositoryProperties(
repositoryNwo: RepositoryNwo,
logger: Logger,
): Promise<Result<RepositoryProperties, unknown>> {
// See if we can skip loading repository properties early. In particular,
// repositories owned by users cannot have repository properties, so we can
// skip the API call entirely in that case.
const repositoryOwnerType = github.context.payload.repository?.owner.type;
logger.debug(
`Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`,
);
if (repositoryOwnerType === "User") {
logger.debug(
"Skipping loading repository properties because the repository is owned by a user and " +
"therefore cannot have repository properties.",
);
return new Success({});
}
try {
return new Success(await loadPropertiesFromApi(logger, repositoryNwo));
} catch (error) {
logger.info(
`Failed to load repository properties: ${getErrorMessage(error)}`,
);
return new Failure(error);
}
}
/** /**
* Validate that `value` has the correct type for `K` and, if so, update the partial set of repository * Validate that `value` has the correct type for `K` and, if so, update the partial set of repository
* properties with the parsed value of the specified property. * properties with the parsed value of the specified property.
@@ -217,6 +268,25 @@ function parseStringRepositoryProperty(_name: string, value: string): string {
return value; return value;
} }
/** Parse the tools mode repository property. */
function parseToolsModeRepositoryProperty(
name: string,
value: string,
logger: Logger,
): ToolsModeRepositoryPropertyValue {
if (
value !== ToolsModeRepositoryPropertyValue.Dynamic &&
value !== ToolsModeRepositoryPropertyValue.Enforce
) {
logger.warning(
`Repository property '${name}' has unexpected value '${value}'. Expected 'dynamic' or 'enforce'. Defaulting to 'enforce'.`,
);
return ToolsModeRepositoryPropertyValue.Enforce;
}
return value;
}
/** Set of known repository property names, for fast lookups. */ /** Set of known repository property names, for fast lookups. */
const KNOWN_REPOSITORY_PROPERTY_NAMES = new Set<string>( const KNOWN_REPOSITORY_PROPERTY_NAMES = new Set<string>(
Object.values(RepositoryPropertyName), Object.values(RepositoryPropertyName),
+41 -42
View File
@@ -2,12 +2,12 @@ import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as github from "@actions/github";
import * as io from "@actions/io"; import * as io from "@actions/io";
import * as semver from "semver"; import * as semver from "semver";
import { v4 as uuidV4 } from "uuid"; import { v4 as uuidV4 } from "uuid";
import { import {
isDynamicWorkflow,
FileCmdNotFoundError, FileCmdNotFoundError,
getActionVersion, getActionVersion,
getFileType, getFileType,
@@ -24,6 +24,10 @@ import {
shouldRestoreCache, shouldRestoreCache,
} from "./caching-utils"; } from "./caching-utils";
import { CodeQL } from "./codeql"; import { CodeQL } from "./codeql";
import {
EffectiveToolsInputSource,
resolveToolsInputWithMetadata,
} from "./config/resolve-tools-input";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { import {
DependencyCacheRestoreStatusReport, DependencyCacheRestoreStatusReport,
@@ -40,8 +44,8 @@ import {
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { import {
loadPropertiesFromApi, loadRepositoryProperties,
RepositoryProperties, ToolsModeRepositoryPropertyValue,
} from "./feature-flags/properties"; } from "./feature-flags/properties";
import { import {
checkInstallPython311, checkInstallPython311,
@@ -53,14 +57,14 @@ import {
initConfig, initConfig,
runDatabaseInitCluster, runDatabaseInitCluster,
} from "./init"; } from "./init";
import { JavaEnvVars, BuiltInLanguage } from "./languages"; import { JavaEnvVars, BuiltInLanguage } from "./languages/index";
import { getActionsLogger, Logger, withGroupAsync } from "./logging"; import { getActionsLogger, Logger, withGroupAsync } from "./logging";
import { import {
downloadOverlayBaseDatabaseFromCache, downloadOverlayBaseDatabaseFromCache,
OverlayBaseDatabaseDownloadStats, OverlayBaseDatabaseDownloadStats,
} from "./overlay/caching"; } from "./overlay/caching";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
import { getRepositoryNwo, RepositoryNwo } from "./repository"; import { getRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql"; import { ToolsSource } from "./setup-codeql";
import { import {
ActionName, ActionName,
@@ -93,10 +97,7 @@ import {
checkActionVersion, checkActionVersion,
getErrorMessage, getErrorMessage,
BuildMode, BuildMode,
Result,
getOptionalEnvVar, getOptionalEnvVar,
Success,
Failure,
} from "./util"; } from "./util";
import { checkWorkflow } from "./workflow"; import { checkWorkflow } from "./workflow";
@@ -140,6 +141,9 @@ async function sendCompletedStatusReport(
toolsFeatureFlagsValid: boolean | undefined, toolsFeatureFlagsValid: boolean | undefined,
toolsSource: ToolsSource, toolsSource: ToolsSource,
toolsVersion: string, toolsVersion: string,
effectiveToolsInput: string | undefined,
effectiveToolsInputSource: EffectiveToolsInputSource,
toolsRepoPropertyMode: ToolsModeRepositoryPropertyValue | undefined,
overlayBaseDatabaseStats: OverlayBaseDatabaseDownloadStats | undefined, overlayBaseDatabaseStats: OverlayBaseDatabaseDownloadStats | undefined,
dependencyCachingResults: DependencyCacheRestoreStatusReport | undefined, dependencyCachingResults: DependencyCacheRestoreStatusReport | undefined,
logger: Logger, logger: Logger,
@@ -165,6 +169,9 @@ async function sendCompletedStatusReport(
const initStatusReport: InitStatusReport = { const initStatusReport: InitStatusReport = {
...statusReportBase, ...statusReportBase,
tools_input: getOptionalInput("tools") || "", tools_input: getOptionalInput("tools") || "",
effective_tools_input: effectiveToolsInput || "",
effective_tools_input_source: effectiveToolsInputSource,
tools_repo_property_mode: toolsRepoPropertyMode || "",
tools_resolved_version: toolsVersion, tools_resolved_version: toolsVersion,
tools_source: toolsSource || ToolsSource.Unknown, tools_source: toolsSource || ToolsSource.Unknown,
workflow_languages: workflowLanguages || "", workflow_languages: workflowLanguages || "",
@@ -219,6 +226,9 @@ async function run(startedAt: Date) {
let toolsSource: ToolsSource; let toolsSource: ToolsSource;
let toolsVersion: string; let toolsVersion: string;
let zstdAvailability: ZstdAvailability | undefined; let zstdAvailability: ZstdAvailability | undefined;
let effectiveToolsInput: string | undefined;
let effectiveToolsInputSource: EffectiveToolsInputSource;
let toolsRepoPropertyMode: ToolsModeRepositoryPropertyValue | undefined;
try { try {
initializeEnvironment(getActionVersion()); initializeEnvironment(getActionVersion());
@@ -251,6 +261,7 @@ async function run(startedAt: Date) {
repositoryNwo, repositoryNwo,
logger, logger,
); );
const repositoryProperties = repositoryPropertiesResult.orElse({});
// Create a unique identifier for this run. // Create a unique identifier for this run.
const jobRunUuid = uuidV4(); const jobRunUuid = uuidV4();
@@ -296,6 +307,21 @@ async function run(startedAt: Date) {
const codeQLDefaultVersionInfo = const codeQLDefaultVersionInfo =
await features.getEnabledDefaultCliVersions(gitHubVersion.type); await features.getEnabledDefaultCliVersions(gitHubVersion.type);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
// Determine the effective tools input.
// The explicit `tools` workflow input takes precedence. If none is provided,
// fall back to the 'github-codeql-tools' repository property (if set).
// If 'github-codeql-tools-mode' is set to 'dynamic', this fallback applies
// only to dynamic workflows. Otherwise, it applies to all workflows.
const resolvedToolsInput = resolveToolsInputWithMetadata(
getOptionalInput("tools"),
isDynamicWorkflow(),
repositoryProperties,
logger,
);
effectiveToolsInput = resolvedToolsInput.effectiveToolsInput;
effectiveToolsInputSource = resolvedToolsInput.effectiveToolsInputSource;
toolsRepoPropertyMode = resolvedToolsInput.toolsRepoPropertyMode;
const rawLanguages = configUtils.getRawLanguagesNoAutodetect( const rawLanguages = configUtils.getRawLanguagesNoAutodetect(
getOptionalInput("languages"), getOptionalInput("languages"),
); );
@@ -303,7 +329,7 @@ async function run(startedAt: Date) {
analysisKinds?.length === 1 && analysisKinds?.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning; analysisKinds[0] === AnalysisKind.CodeScanning;
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"), effectiveToolsInput,
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
@@ -350,7 +376,6 @@ async function run(startedAt: Date) {
analysisKinds = await getAnalysisKinds(logger, features); analysisKinds = await getAnalysisKinds(logger, features);
const debugMode = getOptionalInput("debug") === "true" || core.isDebug(); const debugMode = getOptionalInput("debug") === "true" || core.isDebug();
const repositoryProperties = repositoryPropertiesResult.orElse({});
const fileCoverageResult = await getFileCoverageInformationEnabled( const fileCoverageResult = await getFileCoverageInformationEnabled(
debugMode, debugMode,
codeql, codeql,
@@ -769,6 +794,9 @@ async function run(startedAt: Date) {
toolsFeatureFlagsValid, toolsFeatureFlagsValid,
toolsSource, toolsSource,
toolsVersion, toolsVersion,
effectiveToolsInput,
effectiveToolsInputSource,
toolsRepoPropertyMode,
overlayBaseDatabaseStats, overlayBaseDatabaseStats,
dependencyCachingStatus, dependencyCachingStatus,
logger, logger,
@@ -786,44 +814,15 @@ async function run(startedAt: Date) {
toolsFeatureFlagsValid, toolsFeatureFlagsValid,
toolsSource, toolsSource,
toolsVersion, toolsVersion,
effectiveToolsInput,
effectiveToolsInputSource,
toolsRepoPropertyMode,
overlayBaseDatabaseStats, overlayBaseDatabaseStats,
dependencyCachingStatus, dependencyCachingStatus,
logger, logger,
); );
} }
/**
* Loads [repository properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) if applicable.
*/
async function loadRepositoryProperties(
repositoryNwo: RepositoryNwo,
logger: Logger,
): Promise<Result<RepositoryProperties, unknown>> {
// See if we can skip loading repository properties early. In particular,
// repositories owned by users cannot have repository properties, so we can
// skip the API call entirely in that case.
const repositoryOwnerType = github.context.payload.repository?.owner.type;
logger.debug(
`Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`,
);
if (repositoryOwnerType === "User") {
logger.debug(
"Skipping loading repository properties because the repository is owned by a user and " +
"therefore cannot have repository properties.",
);
return new Success({});
}
try {
return new Success(await loadPropertiesFromApi(logger, repositoryNwo));
} catch (error) {
logger.warning(
`Failed to load repository properties: ${getErrorMessage(error)}`,
);
return new Failure(error);
}
}
async function recordZstdAvailability( async function recordZstdAvailability(
config: configUtils.Config, config: configUtils.Config,
zstdAvailability: ZstdAvailability, zstdAvailability: ZstdAvailability,
+1 -1
View File
@@ -15,7 +15,7 @@ import {
getFileCoverageInformationEnabled, getFileCoverageInformationEnabled,
logFileCoverageOnPrsDeprecationWarning, logFileCoverageOnPrsDeprecationWarning,
} from "./init"; } from "./init";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { import {
createFeatures, createFeatures,
LoggedMessage, LoggedMessage,
+1 -1
View File
@@ -26,7 +26,7 @@ import {
RepositoryProperties, RepositoryProperties,
RepositoryPropertyName, RepositoryPropertyName,
} from "./feature-flags/properties"; } from "./feature-flags/properties";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages/index";
import { Logger, withGroupAsync } from "./logging"; import { Logger, withGroupAsync } from "./logging";
import { ToolsSource } from "./setup-codeql"; import { ToolsSource } from "./setup-codeql";
import { ZstdAvailability } from "./tar"; import { ZstdAvailability } from "./tar";
+45 -1
View File
@@ -2,6 +2,7 @@ import * as core from "@actions/core";
import { v4 as uuidV4 } from "uuid"; import { v4 as uuidV4 } from "uuid";
import { import {
isDynamicWorkflow,
getActionVersion, getActionVersion,
getOptionalInput, getOptionalInput,
getRequiredInput, getRequiredInput,
@@ -10,9 +11,17 @@ import {
import { AnalysisKind, getAnalysisKinds } from "./analyses"; import { AnalysisKind, getAnalysisKinds } from "./analyses";
import { getGitHubVersion } from "./api-client"; import { getGitHubVersion } from "./api-client";
import { CodeQL } from "./codeql"; import { CodeQL } from "./codeql";
import {
EffectiveToolsInputSource,
resolveToolsInputWithMetadata,
} from "./config/resolve-tools-input";
import { getRawLanguagesNoAutodetect } from "./config-utils"; import { getRawLanguagesNoAutodetect } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { initFeatures } from "./feature-flags"; import { initFeatures } from "./feature-flags";
import {
loadRepositoryProperties,
ToolsModeRepositoryPropertyValue,
} from "./feature-flags/properties";
import { initCodeQL } from "./init"; import { initCodeQL } from "./init";
import { getActionsLogger, Logger } from "./logging"; import { getActionsLogger, Logger } from "./logging";
import { getRepositoryNwo } from "./repository"; import { getRepositoryNwo } from "./repository";
@@ -48,6 +57,9 @@ async function sendCompletedStatusReport(
toolsFeatureFlagsValid: boolean | undefined, toolsFeatureFlagsValid: boolean | undefined,
toolsSource: ToolsSource, toolsSource: ToolsSource,
toolsVersion: string, toolsVersion: string,
effectiveToolsInput: string | undefined,
effectiveToolsInputSource: EffectiveToolsInputSource,
toolsRepoPropertyMode: ToolsModeRepositoryPropertyValue | undefined,
logger: Logger, logger: Logger,
error?: Error, error?: Error,
): Promise<void> { ): Promise<void> {
@@ -69,6 +81,9 @@ async function sendCompletedStatusReport(
const initStatusReport: InitStatusReport = { const initStatusReport: InitStatusReport = {
...statusReportBase, ...statusReportBase,
tools_input: getOptionalInput("tools") || "", tools_input: getOptionalInput("tools") || "",
effective_tools_input: effectiveToolsInput || "",
effective_tools_input_source: effectiveToolsInputSource,
tools_repo_property_mode: toolsRepoPropertyMode || "",
tools_resolved_version: toolsVersion, tools_resolved_version: toolsVersion,
tools_source: toolsSource || ToolsSource.Unknown, tools_source: toolsSource || ToolsSource.Unknown,
workflow_languages: "", workflow_languages: "",
@@ -99,6 +114,9 @@ async function run(startedAt: Date): Promise<void> {
let toolsFeatureFlagsValid: boolean | undefined; let toolsFeatureFlagsValid: boolean | undefined;
let toolsSource: ToolsSource; let toolsSource: ToolsSource;
let toolsVersion: string; let toolsVersion: string;
let effectiveToolsInput: string | undefined;
let effectiveToolsInputSource: EffectiveToolsInputSource;
let toolsRepoPropertyMode: ToolsModeRepositoryPropertyValue | undefined;
try { try {
initializeEnvironment(getActionVersion()); initializeEnvironment(getActionVersion());
@@ -141,12 +159,35 @@ async function run(startedAt: Date): Promise<void> {
const codeQLDefaultVersionInfo = const codeQLDefaultVersionInfo =
await features.getEnabledDefaultCliVersions(gitHubVersion.type); await features.getEnabledDefaultCliVersions(gitHubVersion.type);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
// Fetch the values of known repository properties that affect us.
const repositoryPropertiesResult = await loadRepositoryProperties(
repositoryNwo,
logger,
);
const repositoryProperties = repositoryPropertiesResult.orElse({});
// Determine the effective tools input.
// The explicit `tools` workflow input takes precedence. If none is provided,
// fall back to the 'github-codeql-tools' repository property (if set).
// If 'github-codeql-tools-mode' is set to 'dynamic', this fallback applies
// only to dynamic workflows. Otherwise, it applies to all workflows.
const resolvedToolsInput = resolveToolsInputWithMetadata(
getOptionalInput("tools"),
isDynamicWorkflow(),
repositoryProperties,
logger,
);
effectiveToolsInput = resolvedToolsInput.effectiveToolsInput;
effectiveToolsInputSource = resolvedToolsInput.effectiveToolsInputSource;
toolsRepoPropertyMode = resolvedToolsInput.toolsRepoPropertyMode;
const rawLanguages = getRawLanguagesNoAutodetect( const rawLanguages = getRawLanguagesNoAutodetect(
getOptionalInput("languages"), getOptionalInput("languages"),
); );
const analysisKinds = await getAnalysisKinds(logger, features); const analysisKinds = await getAnalysisKinds(logger, features);
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"), effectiveToolsInput,
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
@@ -191,6 +232,9 @@ async function run(startedAt: Date): Promise<void> {
toolsFeatureFlagsValid, toolsFeatureFlagsValid,
toolsSource, toolsSource,
toolsVersion, toolsVersion,
effectiveToolsInput,
effectiveToolsInputSource,
toolsRepoPropertyMode,
logger, logger,
); );
} }
+1 -1
View File
@@ -559,7 +559,7 @@ export async function getCodeQLSource(
); );
} else { } else {
if (allowToolcacheValueFF) { if (allowToolcacheValueFF) {
logger.warning( logger.info(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`, `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`,
); );
} else { } else {
+1 -1
View File
@@ -6,7 +6,7 @@ import * as core from "@actions/core";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import { getGitHubVersion } from "./api-client"; import { getGitHubVersion } from "./api-client";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; import { BuiltInLanguage, parseBuiltInLanguage } from "./languages/index";
import { getActionsLogger, Logger } from "./logging"; import { getActionsLogger, Logger } from "./logging";
import { getRepositoryNwo } from "./repository"; import { getRepositoryNwo } from "./repository";
import { import {
+1 -1
View File
@@ -10,7 +10,7 @@ import * as defaults from "./defaults.json";
import { setUpFeatureFlagTests } from "./feature-flags/testing-util"; import { setUpFeatureFlagTests } from "./feature-flags/testing-util";
import { UnvalidatedObject, validateSchema } from "./json"; import { UnvalidatedObject, validateSchema } from "./json";
import { makeFromSchema } from "./json/testing-util"; import { makeFromSchema } from "./json/testing-util";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { getRunnerLogger, Logger } from "./logging"; import { getRunnerLogger, Logger } from "./logging";
import * as startProxyExports from "./start-proxy"; import * as startProxyExports from "./start-proxy";
import * as statusReport from "./status-report"; import * as statusReport from "./status-report";
+1 -1
View File
@@ -18,7 +18,7 @@ import {
FeatureEnablement, FeatureEnablement,
} from "./feature-flags"; } from "./feature-flags";
import * as json from "./json"; import * as json from "./json";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { import {
Address, Address,
+64 -1
View File
@@ -2,9 +2,10 @@ import test from "ava";
import * as sinon from "sinon"; import * as sinon from "sinon";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import { EffectiveToolsInputSource } from "./config/resolve-tools-input";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { ToolsSource } from "./setup-codeql"; import { ToolsSource } from "./setup-codeql";
import { import {
@@ -316,6 +317,9 @@ const testCreateInitWithConfigStatusReport = makeMacro({
const initStatusReport: InitStatusReport = { const initStatusReport: InitStatusReport = {
...statusReportBase, ...statusReportBase,
tools_input: "", tools_input: "",
effective_tools_input: "",
effective_tools_input_source: EffectiveToolsInputSource.None,
tools_repo_property_mode: "",
tools_resolved_version: "foo", tools_resolved_version: "foo",
tools_source: ToolsSource.Unknown, tools_source: ToolsSource.Unknown,
workflow_languages: "actions", workflow_languages: "actions",
@@ -347,6 +351,8 @@ testCreateInitWithConfigStatusReport.serial(
languages: [BuiltInLanguage.java, BuiltInLanguage.swift], languages: [BuiltInLanguage.java, BuiltInLanguage.swift],
}), }),
{ {
effective_tools_input_source: EffectiveToolsInputSource.None,
tools_repo_property_mode: "",
trap_cache_download_size_bytes: 1024, trap_cache_download_size_bytes: 1024,
registries: "[]", registries: "[]",
query_filters: "[]", query_filters: "[]",
@@ -354,6 +360,63 @@ testCreateInitWithConfigStatusReport.serial(
}, },
); );
test.serial(
"createInitWithConfigStatusReport preserves tools telemetry fields",
async (t) => {
await withTmpDir(async (tmpDir: string) => {
setupEnvironmentAndStub(tmpDir);
const config = createTestConfig({
buildMode: BuildMode.None,
languages: [BuiltInLanguage.java],
});
const statusReportBase = await createStatusReportBase(
ActionName.Init,
"failure",
new Date("May 19, 2023 05:19:00"),
config,
{ numAvailableBytes: 100, numTotalBytes: 500 },
getRunnerLogger(false),
"failure cause",
"exception stack trace",
);
if (t.truthy(statusReportBase)) {
const initStatusReport: InitStatusReport = {
...statusReportBase,
tools_input: "",
effective_tools_input: "toolcache",
effective_tools_input_source:
EffectiveToolsInputSource.RepositoryProperty,
tools_repo_property_mode: "dynamic",
tools_resolved_version: "foo",
tools_source: ToolsSource.Unknown,
workflow_languages: "actions",
};
const initWithConfigStatusReport =
await createInitWithConfigStatusReport(
config,
initStatusReport,
undefined,
1024,
undefined,
undefined,
);
if (t.truthy(initWithConfigStatusReport)) {
t.is(
initWithConfigStatusReport.effective_tools_input_source,
EffectiveToolsInputSource.RepositoryProperty,
);
t.is(initWithConfigStatusReport.tools_repo_property_mode, "dynamic");
}
}
});
},
);
testCreateInitWithConfigStatusReport.serial( testCreateInitWithConfigStatusReport.serial(
"includes packs for a single language", "includes packs for a single language",
createTestConfig({ createTestConfig({
+7
View File
@@ -12,6 +12,7 @@ import {
isSelfHostedRunner, isSelfHostedRunner,
} from "./actions-util"; } from "./actions-util";
import { getAnalysisKey, getApiClient } from "./api-client"; import { getAnalysisKey, getApiClient } from "./api-client";
import { EffectiveToolsInputSource } from "./config/resolve-tools-input";
import { parseRegistriesWithoutCredentials, type Config } from "./config-utils"; import { parseRegistriesWithoutCredentials, type Config } from "./config-utils";
import { DependencyCacheRestoreStatusReport } from "./dependency-caching"; import { DependencyCacheRestoreStatusReport } from "./dependency-caching";
import { DocUrl } from "./doc-url"; import { DocUrl } from "./doc-url";
@@ -482,6 +483,12 @@ export async function sendStatusReport<S extends StatusReportBase>(
export interface InitStatusReport extends StatusReportBase { export interface InitStatusReport extends StatusReportBase {
/** Value given by the user as the "tools" input. */ /** Value given by the user as the "tools" input. */
tools_input: string; tools_input: string;
/** The effective tools input that was used, after applying defaults and repository properties. */
effective_tools_input: string;
/** Indicates where the effective tools input was resolved from. */
effective_tools_input_source: EffectiveToolsInputSource;
/** The value of the tools repository property mode, if relevant. */
tools_repo_property_mode: string;
/** Version of the bundle used. */ /** Version of the bundle used. */
tools_resolved_version: string; tools_resolved_version: string;
/** Where the bundle originated from. */ /** Where the bundle originated from. */
-1
View File
@@ -585,7 +585,6 @@ export function createTestConfig(overrides: Partial<Config>): Config {
extraQueryExclusions: [], extraQueryExclusions: [],
overlayDatabaseMode: OverlayDatabaseMode.None, overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false, useOverlayDatabaseCaching: false,
overlayModeSetExplicitly: false,
repositoryProperties: {}, repositoryProperties: {},
enableFileCoverageInformation: true, enableFileCoverageInformation: true,
} satisfies Config, } satisfies Config,
+1 -1
View File
@@ -6,7 +6,7 @@ import * as sinon from "sinon";
import { CodeQL, getCodeQLForTesting } from "./codeql"; import { CodeQL, getCodeQLForTesting } from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { createTestConfig, makeVersionInfo, setupTests } from "./testing-utils"; import { createTestConfig, makeVersionInfo, setupTests } from "./testing-utils";
import { ToolsFeature } from "./tools-features"; import { ToolsFeature } from "./tools-features";
import { getCombinedTracerConfig } from "./tracer-config"; import { getCombinedTracerConfig } from "./tracer-config";
+1 -1
View File
@@ -15,7 +15,7 @@ import {
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { Feature } from "./feature-flags"; import { Feature } from "./feature-flags";
import * as gitUtils from "./git-utils"; import * as gitUtils from "./git-utils";
import { BuiltInLanguage } from "./languages"; import { BuiltInLanguage } from "./languages/index";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { import {
createFeatures, createFeatures,
+1 -1
View File
@@ -10,7 +10,7 @@ import { type Config } from "./config-utils";
import { DocUrl } from "./doc-url"; import { DocUrl } from "./doc-url";
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature, FeatureEnablement } from "./feature-flags";
import * as gitUtils from "./git-utils"; import * as gitUtils from "./git-utils";
import { Language } from "./languages"; import { Language } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { import {
asHTTPError, asHTTPError,
-23
View File
@@ -532,26 +532,3 @@ test("Failure.orElse returns the default value for a failure result", (t) => {
const result = new util.Failure(new Error("test error")); const result = new util.Failure(new Error("test error"));
t.is(result.orElse("default value"), "default value"); t.is(result.orElse("default value"), "default value");
}); });
test("getCachedCodeQlVersion reuses a version persisted by an earlier step", (t) => {
process.env[EnvVar.CODEQL_VERSION_INFO] = JSON.stringify({
cmd: "/path/to/codeql",
version: { version: "2.20.0" },
});
t.deepEqual(util.getCachedCodeQlVersion("/path/to/codeql"), {
version: "2.20.0",
});
});
test("getCachedCodeQlVersion ignores a persisted version from a different CLI", (t) => {
process.env[EnvVar.CODEQL_VERSION_INFO] = JSON.stringify({
cmd: "/path/to/other-codeql",
version: { version: "2.20.0" },
});
t.is(util.getCachedCodeQlVersion("/path/to/codeql"), undefined);
});
test("getCachedCodeQlVersion ignores a malformed persisted value", (t) => {
process.env[EnvVar.CODEQL_VERSION_INFO] = "not valid json";
t.is(util.getCachedCodeQlVersion("/path/to/codeql"), undefined);
});
+4 -40
View File
@@ -15,7 +15,7 @@ import type { Pack } from "./config/db-config";
import type { Config } from "./config-utils"; import type { Config } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import * as json from "./json"; import * as json from "./json";
import { Language } from "./languages"; import { Language } from "./languages/index";
import { Logger } from "./logging"; import { Logger } from "./logging";
/** /**
@@ -619,51 +619,15 @@ export function asHTTPError(arg: any): HTTPError | undefined {
let cachedCodeQlVersion: undefined | VersionInfo = undefined; let cachedCodeQlVersion: undefined | VersionInfo = undefined;
/** The persisted version together with the CLI path it was obtained from. */ export function cacheCodeQlVersion(version: VersionInfo): void {
interface PersistedVersionInfo {
cmd: string;
version: VersionInfo;
}
export function cacheCodeQlVersion(cmd: string, version: VersionInfo): void {
if (cachedCodeQlVersion !== undefined) { if (cachedCodeQlVersion !== undefined) {
throw new Error("cacheCodeQlVersion() should be called only once"); throw new Error("cacheCodeQlVersion() should be called only once");
} }
cachedCodeQlVersion = version; cachedCodeQlVersion = version;
// Persist the version so that subsequent Actions steps, which run in separate
// processes, can reuse it rather than invoking `codeql version` again. We
// record the CLI path so that a different step using a different CodeQL bundle
// doesn't pick up a stale version.
core.exportVariable(
EnvVar.CODEQL_VERSION_INFO,
JSON.stringify({ cmd, version }),
);
} }
export function getCachedCodeQlVersion(cmd?: string): undefined | VersionInfo { export function getCachedCodeQlVersion(): undefined | VersionInfo {
if (cachedCodeQlVersion !== undefined) { return cachedCodeQlVersion;
return cachedCodeQlVersion;
}
// Fall back to the value persisted by an earlier Actions step, if any. This is
// best-effort: any malformed or mismatched value is ignored so that the caller
// invokes `codeql version` instead.
const serialized = process.env[EnvVar.CODEQL_VERSION_INFO];
if (!serialized) {
return undefined;
}
let persisted: PersistedVersionInfo;
try {
persisted = JSON.parse(serialized) as PersistedVersionInfo;
} catch {
return undefined;
}
if (
typeof persisted?.version?.version !== "string" ||
(cmd !== undefined && persisted.cmd !== cmd)
) {
return undefined;
}
return persisted.version;
} }
export async function codeQlVersionAtLeast( export async function codeQlVersionAtLeast(