diff --git a/.github/workflows/__go-tracing-autobuilder.yml b/.github/workflows/__go-tracing-autobuilder.yml index ccbb1b5a6..fb471c5ea 100644 --- a/.github/workflows/__go-tracing-autobuilder.yml +++ b/.github/workflows/__go-tracing-autobuilder.yml @@ -44,8 +44,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest - version: stable-v2.19.4 - os: ubuntu-latest version: stable-v2.20.7 - os: ubuntu-latest @@ -56,6 +54,8 @@ jobs: version: stable-v2.23.9 - os: ubuntu-latest version: stable-v2.24.3 + - os: ubuntu-latest + version: stable-v2.25.6 - os: ubuntu-latest version: default - os: ubuntu-latest diff --git a/.github/workflows/__go-tracing-custom-build-steps.yml b/.github/workflows/__go-tracing-custom-build-steps.yml index 2acc617cb..b3b043def 100644 --- a/.github/workflows/__go-tracing-custom-build-steps.yml +++ b/.github/workflows/__go-tracing-custom-build-steps.yml @@ -44,8 +44,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest - version: stable-v2.19.4 - os: ubuntu-latest version: stable-v2.20.7 - os: ubuntu-latest @@ -56,6 +54,8 @@ jobs: version: stable-v2.23.9 - os: ubuntu-latest version: stable-v2.24.3 + - os: ubuntu-latest + version: stable-v2.25.6 - os: ubuntu-latest version: default - os: ubuntu-latest diff --git a/.github/workflows/__go-tracing-legacy-workflow.yml b/.github/workflows/__go-tracing-legacy-workflow.yml index a43705b70..20bdea695 100644 --- a/.github/workflows/__go-tracing-legacy-workflow.yml +++ b/.github/workflows/__go-tracing-legacy-workflow.yml @@ -44,8 +44,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest - version: stable-v2.19.4 - os: ubuntu-latest version: stable-v2.20.7 - os: ubuntu-latest @@ -56,6 +54,8 @@ jobs: version: stable-v2.23.9 - os: ubuntu-latest version: stable-v2.24.3 + - os: ubuntu-latest + version: stable-v2.25.6 - os: ubuntu-latest version: default - os: ubuntu-latest diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index b1cd53ce1..320138bb4 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -54,10 +54,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest - version: stable-v2.19.4 - - os: macos-15-xlarge - version: stable-v2.19.4 - os: ubuntu-latest version: stable-v2.20.7 - os: macos-15-xlarge @@ -78,6 +74,10 @@ jobs: version: stable-v2.24.3 - os: macos-latest-xlarge version: stable-v2.24.3 + - os: ubuntu-latest + version: stable-v2.25.6 + - os: macos-latest-xlarge + version: stable-v2.25.6 - os: ubuntu-latest version: default - os: macos-latest-xlarge diff --git a/.github/workflows/__rust.yml b/.github/workflows/__rust.yml index b3638ca6d..f26b4eb2e 100644 --- a/.github/workflows/__rust.yml +++ b/.github/workflows/__rust.yml @@ -35,7 +35,7 @@ jobs: matrix: include: - os: ubuntu-latest - version: stable-v2.19.4 + version: stable-v2.20.7 - os: ubuntu-latest version: stable-v2.22.1 - os: ubuntu-latest diff --git a/.github/workflows/debug-artifacts-failure-safe.yml b/.github/workflows/debug-artifacts-failure-safe.yml index f67cef5c7..936fe6e95 100644 --- a/.github/workflows/debug-artifacts-failure-safe.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -30,7 +30,7 @@ jobs: fail-fast: false matrix: version: - - stable-v2.20.3 + - stable-v2.20.7 - default - linked - nightly-latest diff --git a/.github/workflows/debug-artifacts-safe.yml b/.github/workflows/debug-artifacts-safe.yml index c27f19511..8792aea32 100644 --- a/.github/workflows/debug-artifacts-safe.yml +++ b/.github/workflows/debug-artifacts-safe.yml @@ -29,7 +29,7 @@ jobs: fail-fast: false matrix: version: - - stable-v2.20.3 + - stable-v2.20.7 - default - linked - nightly-latest @@ -85,7 +85,7 @@ jobs: uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - name: Check expected artifacts exist run: | - VERSIONS="stable-v2.20.3 default linked nightly-latest" + VERSIONS="stable-v2.20.7 default linked nightly-latest" LANGUAGES="cpp csharp go java javascript python" for version in $VERSIONS; do pushd "./my-debug-artifacts-${version//./}" diff --git a/CHANGELOG.md b/CHANGELOG.md index e25a66e3c..8ce2edd61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th ## [UNRELEASED] -No user facing changes. +- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205) ## 4.38.3 - 08 Oct 2026 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 216097f89..1436c9bb3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,6 +53,7 @@ Here are a few things you can do that will increase the likelihood of your pull - Write tests. - Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). +- For user-facing changes, add a change-note file. See [unreleased-change-notes/README.md](unreleased-change-notes/README.md). ## Releasing (write access required) diff --git a/lib/entry-points.js b/lib/entry-points.js index e1e1dfc66..348b28db4 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -27216,8 +27216,8 @@ var require_gte = __commonJS({ "node_modules/semver/functions/gte.js"(exports2, module2) { "use strict"; var compare3 = require_compare(); - var gte8 = (a, b, loose) => compare3(a, b, loose) >= 0; - module2.exports = gte8; + var gte7 = (a, b, loose) => compare3(a, b, loose) >= 0; + module2.exports = gte7; } }); @@ -27238,7 +27238,7 @@ var require_cmp = __commonJS({ var eq = require_eq(); var neq = require_neq(); var gt = require_gt(); - var gte8 = require_gte(); + var gte7 = require_gte(); var lt2 = require_lt(); var lte2 = require_lte(); var cmp = (a, op, b, loose) => { @@ -27268,7 +27268,7 @@ var require_cmp = __commonJS({ case ">": return gt(a, b, loose); case ">=": - return gte8(a, b, loose); + return gte7(a, b, loose); case "<": return lt2(a, b, loose); case "<=": @@ -28076,7 +28076,7 @@ var require_outside = __commonJS({ var gt = require_gt(); var lt2 = require_lt(); var lte2 = require_lte(); - var gte8 = require_gte(); + var gte7 = require_gte(); var outside = (version, range2, hilo, options) => { version = new SemVer(version, options); range2 = new Range2(range2, options); @@ -28091,7 +28091,7 @@ var require_outside = __commonJS({ break; case "<": gtfn = lt2; - ltefn = gte8; + ltefn = gte7; ltfn = gt; comp = "<"; ecomp = "<="; @@ -28406,7 +28406,7 @@ var require_semver2 = __commonJS({ var lt2 = require_lt(); var eq = require_eq(); var neq = require_neq(); - var gte8 = require_gte(); + var gte7 = require_gte(); var lte2 = require_lte(); var cmp = require_cmp(); var coerce3 = require_coerce(); @@ -28445,7 +28445,7 @@ var require_semver2 = __commonJS({ lt: lt2, eq, neq, - gte: gte8, + gte: gte7, lte: lte2, cmp, coerce: coerce3, @@ -31736,7 +31736,7 @@ var require_brace_expansion = __commonJS({ function lte2(i, y) { return i <= y; } - function gte8(i, y) { + function gte7(i, y) { return i >= y; } function combine2(acc, base, pre, values, max, maxLength, dropEmpties, outBase) { @@ -31769,7 +31769,7 @@ var require_brace_expansion = __commonJS({ var reverse = y < x; if (reverse) { incr *= -1; - test = gte8; + test = gte7; } var pad = n.some(isPadded2); var length = 0; @@ -33921,8 +33921,8 @@ var require_semver3 = __commonJS({ function neq(a, b, loose) { return compare3(a, b, loose) !== 0; } - exports2.gte = gte8; - function gte8(a, b, loose) { + exports2.gte = gte7; + function gte7(a, b, loose) { return compare3(a, b, loose) >= 0; } exports2.lte = lte2; @@ -33953,7 +33953,7 @@ var require_semver3 = __commonJS({ case ">": return gt(a, b, loose); case ">=": - return gte8(a, b, loose); + return gte7(a, b, loose); case "<": return lt2(a, b, loose); case "<=": @@ -34498,7 +34498,7 @@ var require_semver3 = __commonJS({ break; case "<": gtfn = lt2; - ltefn = gte8; + ltefn = gte7; ltfn = gt; comp = "<"; ecomp = "<="; @@ -34719,7 +34719,7 @@ var require_cacheUtils = __commonJS({ var crypto3 = __importStar2(require("crypto")); var fs33 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - var semver12 = __importStar2(require_semver3()); + var semver11 = __importStar2(require_semver3()); var util4 = __importStar2(require("util")); var constants_1 = require_constants7(); var versionSalt = "1.0"; @@ -34812,7 +34812,7 @@ var require_cacheUtils = __commonJS({ function getCompressionMethod() { return __awaiter2(this, void 0, void 0, function* () { const versionOutput = yield getVersion("zstd", ["--quiet"]); - const version = semver12.clean(versionOutput); + const version = semver11.clean(versionOutput); core29.debug(`zstd version: ${version}`); if (versionOutput === "") { return constants_1.CompressionMethod.Gzip; @@ -106346,7 +106346,7 @@ var require_manifest = __commonJS({ exports2._findMatch = _findMatch; exports2._getOsVersion = _getOsVersion; exports2._readLinuxVersionFile = _readLinuxVersionFile; - var semver12 = __importStar2(require_semver2()); + var semver11 = __importStar2(require_semver2()); var core_1 = require_core(); var os8 = require("os"); var cp = require("child_process"); @@ -106360,7 +106360,7 @@ var require_manifest = __commonJS({ for (const candidate of candidates) { const version = candidate.version; (0, core_1.debug)(`check ${version} satisfies ${versionSpec}`); - if (semver12.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { + if (semver11.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { file = candidate.files.find((item) => { (0, core_1.debug)(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); let chk = item.arch === archFilter && item.platform === platFilter; @@ -106369,7 +106369,7 @@ var require_manifest = __commonJS({ if (osVersion === item.platform_version) { chk = true; } else { - chk = semver12.satisfies(osVersion, item.platform_version); + chk = semver11.satisfies(osVersion, item.platform_version); } } return chk; @@ -106629,7 +106629,7 @@ var require_tool_cache = __commonJS({ var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var httpm = __importStar2(require_lib()); - var semver12 = __importStar2(require_semver2()); + var semver11 = __importStar2(require_semver2()); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var assert_1 = require("assert"); @@ -106902,7 +106902,7 @@ var require_tool_cache = __commonJS({ } function cacheDir2(sourceDir, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - version = semver12.clean(version) || version; + version = semver11.clean(version) || version; arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source dir: ${sourceDir}`); @@ -106920,7 +106920,7 @@ var require_tool_cache = __commonJS({ } function cacheFile(sourceFile, targetFile, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - version = semver12.clean(version) || version; + version = semver11.clean(version) || version; arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source file: ${sourceFile}`); @@ -106950,7 +106950,7 @@ var require_tool_cache = __commonJS({ } let toolPath = ""; if (versionSpec) { - versionSpec = semver12.clean(versionSpec) || ""; + versionSpec = semver11.clean(versionSpec) || ""; const cachePath = path30.join(_getCacheDirectory(), toolName, versionSpec, arch2); core29.debug(`checking cache: ${cachePath}`); if (fs33.existsSync(cachePath) && fs33.existsSync(`${cachePath}.complete`)) { @@ -107030,7 +107030,7 @@ var require_tool_cache = __commonJS({ } function _createToolPath(tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); + const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); core29.debug(`destination ${folderPath}`); const markerPath = `${folderPath}.complete`; yield io9.rmRF(folderPath); @@ -107040,15 +107040,15 @@ var require_tool_cache = __commonJS({ }); } function _completeToolPath(tool, version, arch2) { - const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); + const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; fs33.writeFileSync(markerPath, ""); core29.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { - const c = semver12.clean(versionSpec) || ""; + const c = semver11.clean(versionSpec) || ""; core29.debug(`isExplicit: ${c}`); - const valid4 = semver12.valid(c) != null; + const valid4 = semver11.valid(c) != null; core29.debug(`explicit? ${valid4}`); return valid4; } @@ -107056,14 +107056,14 @@ var require_tool_cache = __commonJS({ let version = ""; core29.debug(`evaluating ${versions.length} versions`); versions = versions.sort((a, b) => { - if (semver12.gt(a, b)) { + if (semver11.gt(a, b)) { return 1; } return -1; }); for (let i = versions.length - 1; i >= 0; i--) { const potential = versions[i]; - const satisfied = semver12.satisfies(potential, versionSpec); + const satisfied = semver11.satisfies(potential, versionSpec); if (satisfied) { version = potential; break; @@ -113555,7 +113555,7 @@ var require_brace_expansion2 = __commonJS({ function lte2(i, y) { return i <= y; } - function gte8(i, y) { + function gte7(i, y) { return i >= y; } function combine2(acc, pre, values, max, maxLength, dropEmpties) { @@ -113587,7 +113587,7 @@ var require_brace_expansion2 = __commonJS({ var reverse = y < x; if (reverse) { incr *= -1; - test = gte8; + test = gte7; } var pad = n.some(isPadded2); var length = 0; @@ -170185,7 +170185,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.38.4"; + return "4.39.0"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); @@ -171728,6 +171728,9 @@ async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error } // src/action-common.ts +function extendActionState(state, extra) { + return { ...state, ...extra }; +} async function runInActions(action) { const startedAt = /* @__PURE__ */ new Date(); const logger2 = getActionsLogger(); @@ -171764,7 +171767,7 @@ async function runInActions(action) { // src/feature-flags.ts var fs7 = __toESM(require("fs")); var path6 = __toESM(require("path")); -var semver4 = __toESM(require_semver2()); +var semver3 = __toESM(require_semver2()); // src/defaults.json var bundleVersion = "codeql-bundle-v2.27.2"; @@ -171884,14 +171887,9 @@ async function getDiffRangeFilePaths(sourceRoot, logger2) { } // src/tools-features.ts -var semver3 = __toESM(require_semver2()); function isSupportedToolsFeature(versionInfo, feature) { return !!versionInfo.features && versionInfo.features[feature]; } -var SafeArtifactUploadVersion = "2.20.3"; -function isSafeArtifactUpload(codeQlVersion) { - return !codeQlVersion ? true : semver3.gte(codeQlVersion, SafeArtifactUploadVersion); -} // src/feature-flags.ts var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; @@ -171931,7 +171929,7 @@ var featureConfig = { defaultValue: false, envVar: "CODEQL_EXTRACTOR_CPP_AUTOINSTALL_DEPENDENCIES", legacyApi: true, - minimumVersion: "2.15.0" + minimumVersion: void 0 }, ["csharp_cache_bmn" /* CsharpCacheBuildModeNone */]: { defaultValue: false, @@ -172342,7 +172340,7 @@ var GitHubFeatureFlags = class { DEFAULT_VERSION_FEATURE_FLAG_PREFIX.length, f.length - DEFAULT_VERSION_FEATURE_FLAG_SUFFIX.length ).replace(/_/g, "."); - if (!semver4.valid(version)) { + if (!semver3.valid(version)) { this.logger.warning( `Ignoring feature flag ${f} as it does not specify a valid CodeQL version.` ); @@ -172359,7 +172357,7 @@ var GitHubFeatureFlags = class { const response = await this.getAllFeatures(); const sortedCliVersions = Object.entries(response).map( ([f, isEnabled]) => isEnabled ? this.getCliVersionFromFeatureFlag(f) : void 0 - ).filter((f) => f !== void 0).sort(semver4.rcompare); + ).filter((f) => f !== void 0).sort(semver3.rcompare); if (sortedCliVersions.length === 0) { this.logger.warning( `Feature flags do not specify a default CLI version. Falling back to the CLI version shipped with the Action. This is ${cliVersion}.` @@ -172966,7 +172964,7 @@ function getDependencyCachingEnabled() { // src/config/db-config.ts var path8 = __toESM(require("path")); var jsonschema = __toESM(require_lib2()); -var semver5 = __toESM(require_semver2()); +var semver4 = __toESM(require_semver2()); // src/diagnostics.ts var import_fs = require("fs"); @@ -173381,7 +173379,7 @@ function parsePacksSpecification(packStr) { } if (version) { try { - new semver5.Range(version); + new semver4.Range(version); } catch { throw new ConfigurationError(getPacksStrInvalid(packStr)); } @@ -175235,7 +175233,7 @@ var path13 = __toESM(require("path")); var import_perf_hooks4 = require("perf_hooks"); var toolcache3 = __toESM(require_tool_cache()); var import_fast_deep_equal = __toESM(require_fast_deep_equal()); -var semver10 = __toESM(require_semver2()); +var semver9 = __toESM(require_semver2()); // src/codeql-bundle.ts function getCodeQLBundleName(compressionMethod, platform2, language) { @@ -175269,7 +175267,7 @@ function getCodeQLBundleFromUrl(url2) { // src/overlay/caching.ts var fs12 = __toESM(require("fs")); var actionsCache3 = __toESM(require_cache4()); -var semver6 = __toESM(require_semver2()); +var semver5 = __toESM(require_semver2()); var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6; var CACHE_VERSION2 = 1; @@ -175546,7 +175544,7 @@ async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger2) { if (!cache.key) continue; const suffix = cache.key.substring(cacheKeyPrefix.length); const match2 = suffix.match(versionRegex); - if (match2 && semver6.valid(match2[1])) { + if (match2 && semver5.valid(match2[1])) { versionSet.add(match2[1]); } } @@ -175556,7 +175554,7 @@ async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger2) { ); return []; } - const versions = [...versionSet].sort(semver6.rcompare); + const versions = [...versionSet].sort(semver5.rcompare); logger2.info( `Found overlay databases for the following CodeQL versions in the Actions cache: ${versions.join(", ")}` ); @@ -175564,7 +175562,7 @@ async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger2) { } // src/per-language-bundles.ts -var semver7 = __toESM(require_semver2()); +var semver6 = __toESM(require_semver2()); // src/platform.ts function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) { @@ -175671,7 +175669,7 @@ async function getPerLanguageBundleLanguage({ if (cliVersion2 === void 0) { return explain("the requested CLI version is unknown"); } - if (!semver7.gte(cliVersion2, MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION)) { + if (!semver6.gte(cliVersion2, MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION)) { return explain( `the requested CodeQL version ${cliVersion2} is older than ${MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION}, which is the first version for which per-language bundles are published` ); @@ -175697,7 +175695,7 @@ var stream = __toESM(require("stream")); var import_toolrunner = __toESM(require_toolrunner()); var io4 = __toESM(require_io()); var toolcache = __toESM(require_tool_cache()); -var semver8 = __toESM(require_semver2()); +var semver7 = __toESM(require_semver2()); var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; async function getTarVersion() { @@ -175739,9 +175737,9 @@ async function isZstdAvailable(logger2) { case "gnu": return { available: foundZstdBinary && // GNU tar only uses major and minor version numbers - semver8.gte( - semver8.coerce(version), - semver8.coerce(MIN_REQUIRED_GNU_TAR_VERSION) + semver7.gte( + semver7.coerce(version), + semver7.coerce(MIN_REQUIRED_GNU_TAR_VERSION) ), foundZstdBinary, version: tarVersion @@ -175750,7 +175748,7 @@ async function isZstdAvailable(logger2) { return { available: foundZstdBinary && // Do a loose comparison since these version numbers don't contain // a patch version number. - semver8.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), + semver7.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), foundZstdBinary, version: tarVersion }; @@ -175859,7 +175857,7 @@ var core11 = __toESM(require_core()); var import_http_client = __toESM(require_lib()); var toolcache2 = __toESM(require_tool_cache()); var import_follow_redirects = __toESM(require_follow_redirects()); -var semver9 = __toESM(require_semver2()); +var semver8 = __toESM(require_semver2()); var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; var STREAMING_STALL_TIMEOUT_MS = 5 * 60 * 1e3; var TOOLCACHE_TOOL_NAME = "CodeQL"; @@ -175985,7 +175983,7 @@ function getToolcacheToolDirectory(env) { ); } function getToolcacheVersionDirectoryName(version) { - return semver9.clean(version) || version; + return semver8.clean(version) || version; } function getToolcacheDirectory(version) { return path12.join( @@ -176165,13 +176163,13 @@ function tryGetTagNameFromUrl(url2, logger2) { return match2[1]; } function convertToSemVer(version, logger2) { - if (!semver10.valid(version)) { + if (!semver9.valid(version)) { logger2.debug( `Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.` ); version = `0.0.0-${version}`; } - const s = semver10.clean(version); + const s = semver9.clean(version); if (!s) { throw new Error(`Bundle version ${version} is not in SemVer format.`); } @@ -176387,7 +176385,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe url2 = toolsInput; if (tagName) { const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger2); - if (bundleVersion3 !== void 0 && semver10.valid(bundleVersion3)) { + if (bundleVersion3 !== void 0 && semver9.valid(bundleVersion3)) { cliVersion2 = convertToSemVer(bundleVersion3, logger2); } } @@ -176769,7 +176767,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp async function useZstdBundle(cliVersion2, tarSupportsZstd) { return ( // In testing, gzip performs better than zstd on Windows. - process.platform !== "win32" && tarSupportsZstd && semver10.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) + process.platform !== "win32" && tarSupportsZstd && semver9.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) ); } function getTempExtractionDir(tempDir) { @@ -176823,7 +176821,7 @@ async function getLatestNightlyBundle(action, rawLanguages, otherLanguagePacksRe } } function getLatestToolcacheVersion(logger2) { - const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver10.compare(b, a)); + const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver9.compare(b, a)); logger2.debug( `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( allVersions @@ -176911,7 +176909,7 @@ async function getCombinedTracerConfig(logger2, codeql, config) { // src/codeql.ts var cachedCodeQL = void 0; -var CODEQL_MINIMUM_VERSION = "2.19.4"; +var CODEQL_MINIMUM_VERSION = "2.20.7"; var CODEQL_NEXT_MINIMUM_VERSION = "2.21.3"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.17"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2026-09-24"; @@ -177558,7 +177556,7 @@ async function determineAutobuildLanguages(codeql, config, logger2) { } return languages; } -async function setupCppAutobuild(codeql, logger2) { +async function setupCppAutobuild(logger2) { const envVar = featureConfig["cpp_dependency_installation_enabled" /* CppDependencyInstallation */].envVar; const featureName = "C++ automatic installation of dependencies"; const gitHubVersion = await getGitHubVersion(); @@ -177569,7 +177567,7 @@ async function setupCppAutobuild(codeql, logger2) { getTemporaryDirectory(), logger2 ); - if (await features.getValue("cpp_dependency_installation_enabled" /* CppDependencyInstallation */, codeql)) { + if (await features.getValue("cpp_dependency_installation_enabled" /* CppDependencyInstallation */)) { if (process.env["RUNNER_ENVIRONMENT" /* RUNNER_ENVIRONMENT */] === "self-hosted" && process.env[envVar] !== "true") { logger2.info( `Disabling ${featureName} as we are on a self-hosted runner.${getWorkflowEventName() !== "dynamic" ? ` To override this, set the ${envVar} environment variable to 'true' in your workflow. See ${"https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow" /* DEFINE_ENV_VARIABLES */} for more information.` : ""}` @@ -177590,7 +177588,7 @@ async function runAutobuild(config, language, logger2) { logger2.startGroup(`Attempting to automatically build ${language} code`); const codeQL = await getCodeQL(logger2, config.codeQLCmd); if (language === "cpp" /* cpp */) { - await setupCppAutobuild(codeQL, logger2); + await setupCppAutobuild(logger2); } if (config.buildMode) { await codeQL.extractUsingBuildMode(config, language); @@ -177914,7 +177912,7 @@ async function runExtraction(codeql, features, config, logger2) { } if (config.buildMode) { if (language === "cpp" /* cpp */ && config.buildMode === "autobuild" /* Autobuild */) { - await setupCppAutobuild(codeql, logger2); + await setupCppAutobuild(logger2); } if (language === "java" /* java */ && config.buildMode === "none" /* None */) { process.env["CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_DEPENDENCY_DIR"] = getJavaTempDependencyDir(); @@ -180674,11 +180672,6 @@ async function run({ "`expect-error` input parameter is for internal use only. It should only be set by codeql-action or a fork." ); } - if (process.env.CODEQL_PROXY_HOST === "" && !await codeQlVersionAtLeast(codeql, "2.20.7")) { - delete process.env.CODEQL_PROXY_HOST; - delete process.env.CODEQL_PROXY_PORT; - delete process.env.CODEQL_PROXY_CA_CERTIFICATE; - } if (getOptionalInput("cleanup-level")) { logger2.info( "The 'cleanup-level' input is ignored since the CodeQL Action now automatically manages database cleanup. This input can safely be removed from your workflow." @@ -181047,7 +181040,7 @@ function isPadded(el) { function lte(i, y) { return i <= y; } -function gte7(i, y) { +function gte6(i, y) { return i >= y; } function combine(acc, pre, values, max, maxLength, dropEmpties) { @@ -181082,7 +181075,7 @@ function expandSequence(body, isAlphaSequence, max, maxLength) { const reverse = y < x; if (reverse) { incr *= -1; - test = gte7; + test = gte6; } const pad = n.some(isPadded); let length = 0; @@ -185543,7 +185536,7 @@ async function scanArtifactsForTokens(filesToScan, logger2) { function sanitizeArtifactName(name) { return name.replace(/[^a-zA-Z0-9_-]+/g, ""); } -async function uploadCombinedSarifArtifacts(logger2, gitHubVariant, codeQlVersion) { +async function uploadCombinedSarifArtifacts(logger2, gitHubVariant) { const tempDir = getTemporaryDirectory(); if (process.env["CODEQL_ACTION_DEBUG_COMBINED_SARIF"] === "true") { await withGroup("Uploading combined SARIF debug artifact", async () => { @@ -185562,13 +185555,12 @@ async function uploadCombinedSarifArtifacts(logger2, gitHubVariant, codeQlVersio } } try { - await uploadDebugArtifacts( + await uploadArtifacts( logger2, toUpload, baseTempDir, "combined-sarif-artifacts", - gitHubVariant, - codeQlVersion + gitHubVariant ); } catch (e) { logger2.warning( @@ -185627,7 +185619,7 @@ async function tryBundleDatabase(codeql, config, language, logger2) { return void 0; } } -async function tryUploadAllAvailableDebugArtifacts(codeql, config, logger2, codeQlVersion) { +async function tryUploadAllAvailableDebugArtifacts(codeql, config, logger2) { const filesToUpload = []; try { for (const language of config.languages) { @@ -185680,13 +185672,12 @@ async function tryUploadAllAvailableDebugArtifacts(codeql, config, logger2, code try { await withGroup( "Uploading debug artifacts", - async () => uploadDebugArtifacts( + async () => uploadArtifacts( logger2, filesToUpload, config.dbLocation, config.debugArtifactName, - config.gitHubVersion.type, - codeQlVersion + config.gitHubVersion.type ) ); } catch (e) { @@ -185714,16 +185705,6 @@ function getArtifactSuffix(matrix) { } return suffix; } -async function uploadDebugArtifacts(logger2, toUpload, rootDir, artifactName, ghVariant, codeQlVersion) { - const uploadSupported = isSafeArtifactUpload(codeQlVersion); - if (!uploadSupported) { - core15.info( - `Skipping debug artifact upload because the current CLI does not support safe upload. Please upgrade to CLI v${SafeArtifactUploadVersion} or later.` - ); - return "upload-not-supported"; - } - return uploadArtifacts(logger2, toUpload, rootDir, artifactName, ghVariant); -} async function uploadArtifacts(logger2, toUpload, rootDir, artifactName, ghVariant) { if (toUpload.length === 0) { return "no-artifacts-to-upload"; @@ -185814,12 +185795,9 @@ async function runWrapper2() { logger2 ); if (config !== void 0) { - const codeql = await getCodeQL(logger2, config.codeQLCmd); - const version = await codeql.getVersion(); await uploadCombinedSarifArtifacts( logger2, - config.gitHubVersion.type, - version.version + config.gitHubVersion.type ); } } @@ -185945,7 +185923,7 @@ var fs30 = __toESM(require("fs")); var path25 = __toESM(require("path")); var core19 = __toESM(require_core()); var io7 = __toESM(require_io()); -var semver11 = __toESM(require_semver2()); +var semver10 = __toESM(require_semver2()); // src/config/inputs.ts async function getToolsInput(action, repositoryProperties) { @@ -186388,7 +186366,9 @@ async function run3(actionState) { `Failed to parse analysis kinds for 'starting' status report: ${getErrorMessage(err)}` ); } - const actionStateWithFeatures = { ...actionState, features }; + const actionStateWithFeatures = extendActionState(actionState, { + features + }); configFile = await getConfigFileInput( actionStateWithFeatures, repositoryProperties, @@ -186446,15 +186426,9 @@ async function run3(actionState) { // requested rust - don't enable it via language autodetection. getRawLanguagesNoAutodetect(getOptionalInput("languages")).includes("rust" /* rust */) ) { - const experimental = "2.19.3"; const publicPreview = "2.22.1"; const actualVer = (await codeql.getVersion()).version; - if (semver11.lt(actualVer, experimental)) { - throw new ConfigurationError( - `Rust analysis is supported by CodeQL CLI version ${experimental} or higher, but found version ${actualVer}` - ); - } - if (semver11.lt(actualVer, publicPreview)) { + if (semver10.lt(actualVer, publicPreview)) { actionState.env.export("CODEQL_ENABLE_EXPERIMENTAL_FEATURES" /* EXPERIMENTAL_FEATURES */, "true"); logger2.info("Experimental Rust analysis enabled"); } @@ -186654,10 +186628,6 @@ exec ${goBinaryPath} "$@"` if (await features.getValue("force_jgit" /* ForceJGit */)) { actionState.env.export("CODEQL_GIT_BACKEND", "jgit"); } - const kotlinLimitVar = "CODEQL_EXTRACTOR_KOTLIN_OVERRIDE_MAXIMUM_VERSION_LIMIT"; - if (await codeQlVersionAtLeast(codeql, "2.20.3") && !await codeQlVersionAtLeast(codeql, "2.20.4")) { - actionState.env.export(kotlinLimitVar, "2.1.20"); - } if (shouldRestoreCache(config.dependencyCachingEnabled)) { const dependencyCachingResult = await downloadDependencyCaches( codeql, @@ -186967,13 +186937,7 @@ async function uploadFailureInfo(uploadAllAvailableDebugArtifacts, printDebugLog logger2.info( "Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts..." ); - const version = await codeql.getVersion(); - await uploadAllAvailableDebugArtifacts( - codeql, - config, - logger2, - version.version - ); + await uploadAllAvailableDebugArtifacts(codeql, config, logger2); await printDebugLogs2(config); } if (isSelfHostedRunner()) { @@ -187410,7 +187374,9 @@ async function run6(actionState) { logger2 ); const repositoryProperties = repositoryPropertiesResult.orElse({}); - const actionStateWithFeatures = { ...actionState, features }; + const actionStateWithFeatures = extendActionState(actionState, { + features + }); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, "starting", @@ -188205,7 +188171,8 @@ async function run7(action) { all_credentials: credentials, ca }; - const proxyBin = await getProxyBinaryPath({ ...action, features }); + const actionWithFeatures = extendActionState(action, { features }); + const proxyBin = await getProxyBinaryPath(actionWithFeatures); const proxyInfo = await startProxy( proxyBin, proxyConfig, @@ -188444,13 +188411,7 @@ async function runWrapper11() { } await withGroup( "Uploading combined SARIF debug artifact", - () => uploadCombinedSarifArtifacts( - logger2, - gitHubVersion.type, - // The codeqlVersion is not applicable for uploading non-codeql sarif. - // We can assume all versions are safe to upload. - void 0 - ) + () => uploadCombinedSarifArtifacts(logger2, gitHubVersion.type) ); } } catch (error3) { diff --git a/package-lock.json b/package-lock.json index ab107dd2b..050ff1e48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.38.4", + "version": "4.39.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.38.4", + "version": "4.39.0", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index b866e7f8c..51fd4a450 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.38.4", + "version": "4.39.0", "private": true, "description": "CodeQL action", "scripts": { diff --git a/pr-checks/changenotes.ts b/pr-checks/changenotes.ts index 933d255cd..26035527b 100755 --- a/pr-checks/changenotes.ts +++ b/pr-checks/changenotes.ts @@ -28,12 +28,12 @@ interface ChangenoteFile { /** * Returns the absolute file paths of all files in - * {@link CHANGENOTES_DIR} (except ".gitkeep"). + * {@link CHANGENOTES_DIR} (except ".gitkeep" and "README.md"). * */ function listUnreleasedChangenoteDir(): string[] { return fs .readdirSync(CHANGENOTES_DIR) - .filter((name) => name !== ".gitkeep") + .filter((name) => ![".gitkeep", "README.md"].includes(name)) .map((name) => path.join(CHANGENOTES_DIR, name)); } diff --git a/pr-checks/checks/multi-language-autodetect.yml b/pr-checks/checks/multi-language-autodetect.yml index 4588475c0..f84993356 100644 --- a/pr-checks/checks/multi-language-autodetect.yml +++ b/pr-checks/checks/multi-language-autodetect.yml @@ -10,7 +10,6 @@ operatingSystems: - os: macos runner-image: macos-15-xlarge codeql-versions: - - stable-v2.19.4 - stable-v2.20.7 - stable-v2.21.4 - stable-v2.22.4 diff --git a/pr-checks/checks/rust.yml b/pr-checks/checks/rust.yml index 8589ba80e..e0b91ae9c 100644 --- a/pr-checks/checks/rust.yml +++ b/pr-checks/checks/rust.yml @@ -1,8 +1,8 @@ name: "Rust analysis" description: "Tests creation of a Rust database" versions: - # experimental rust support introduced, requires action to set `CODEQL_ENABLE_EXPERIMENTAL_FEATURES` - - stable-v2.19.4 + # oldest CodeQL version supported by the Action, where Rust support is experimental and requires the Action to set `CODEQL_ENABLE_EXPERIMENTAL_FEATURES` + - stable-v2.20.7 # first public preview version - stable-v2.22.1 - linked diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 9b40c2e41..8dc1dd1d1 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -136,8 +136,6 @@ type LanguageSetups = Partial>; // The default set of CodeQL Bundle versions to use for the PR checks. const defaultTestVersions = [ // The oldest supported CodeQL version. If bumping, update `CODEQL_MINIMUM_VERSION` in `codeql.ts` - "stable-v2.19.4", - // The last CodeQL release in the 2.20 series. "stable-v2.20.7", // The last CodeQL release in the 2.21 series. "stable-v2.21.4", @@ -147,6 +145,8 @@ const defaultTestVersions = [ "stable-v2.23.9", // The last CodeQL release in the 2.24 series. "stable-v2.24.3", + // The last CodeQL release in the 2.25 series. + "stable-v2.25.6", // The default version of CodeQL for Dotcom, as determined by feature flags. "default", // The version of CodeQL shipped with the Action in `defaults.json`. During the release process diff --git a/src/action-common.ts b/src/action-common.ts index 516325926..3b7774703 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -66,6 +66,29 @@ export interface FeatureState { /** Identifies a type of state an Action may have. */ export type StateFeature = keyof FeatureState; +/** + * The `Env` feature implies the availability of the `ReadOnlyEnv` feature. + * + * If `T` is `Env`, this returns `Env | ReadOnlyEnv`. + * Otherwise, it is the identity and returns T. + */ +type ImpliedFeatures = T extends "Env" + ? "Env" | "ReadOnlyEnv" + : T; + +/** + * Given an object type `Obj`, this tries to lookup a corresponding `StateFeature` + * to which the object type belongs in `FeatureState`. Resolves to `never` if there + * is no match. + */ +type FeatureNameFor = { + [K in StateFeature]: [Obj] extends [FeatureState[K]] + ? [FeatureState[K]] extends [Obj] + ? K + : never + : never; +}[StateFeature]; + /** Constructs the intersection of all state types identifies by `Fs`. */ export type FieldsOf = Fs extends [] ? Record @@ -76,8 +99,54 @@ export type FieldsOf = Fs extends [] ? FeatureState[Head] & FieldsOf : never; +/** + * Symbol used for a field in `ActionState` that carries the type array of state features. + * This is a Symbol so that it doesn't clash with any property names we might want to have. + */ +const stateFeatures = Symbol(); + /** Describes the state of an Action that has access to the state corresponding to `Fs`. */ -export type ActionState = FieldsOf; +export type ActionState = FieldsOf & { + /** + * When given a chance, TypeScript will simplify an `ActionState` type as much as possible, + * which results in a concrete object type that doesn't mention `Fs`. + * + * That causes problems for functions which accept `ActionState` values, but need to know the + * feature keys `Fs`. This property here explicitly captures `Fs` in the concrete object type + * that results from simplifying `ActionState`. + * + * This is a function rather than a field, because we want to be able to provide values of type + * `ActionState` to functions expecting `ActionState` where `As` is a subset of `Fs`. + * + * Since function types are contravariant in the types of their parameters, using a function + * type here allows that to happen. + * + * Because the field is optional, we don't have to explicitly provide a value + * for it anywhere while the type is still inferred. + * + * `Fs[number]` returns the union of all features in `Fs`. We wrap it in `ImpliedFeatures` + * so that `Env` is expanded into `Env | ReadOnlyEnv`, allowing functions that expect the + * `ReadOnlyEnv` feature to be provided with an `ActionState` that has the `Env` feature + * without requiring this to be made explicit. + */ + readonly [stateFeatures]?: (ts: ImpliedFeatures) => void; +}; + +/** Extends `state` with an `extra` feature. */ +export function extendActionState< + // In first position, so that it can be explicitly provided if `FeatureNameFor` + // should not work on `extra`. + F extends StateFeature, + Fs extends readonly StateFeature[], + E extends FeatureState[F], +>( + state: ActionState, + extra: E, +): ActionState<[...Fs, FeatureNameFor & F]> { + return { ...state, ...extra } as unknown as ActionState< + [...Fs, FeatureNameFor & F] + >; +} /** The type of an Action's main entry point. This is a function that is provided * with a basic `ActionState` object with features that are always available. diff --git a/src/analyze-action-post.ts b/src/analyze-action-post.ts index 3f9b2fafb..a8d6dc433 100644 --- a/src/analyze-action-post.ts +++ b/src/analyze-action-post.ts @@ -9,7 +9,6 @@ import * as core from "@actions/core"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; -import { getCodeQL } from "./codeql"; import { getConfig } from "./config-utils"; import * as debugArtifacts from "./debug-artifacts"; import { @@ -38,12 +37,9 @@ export async function runWrapper() { logger, ); if (config !== undefined) { - const codeql = await getCodeQL(logger, config.codeQLCmd); - const version = await codeql.getVersion(); await debugArtifacts.uploadCombinedSarifArtifacts( logger, config.gitHubVersion.type, - version.version, ); } } diff --git a/src/analyze-action.ts b/src/analyze-action.ts index a01933285..865564741 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -268,17 +268,6 @@ async function run({ ); } - // Unset the CODEQL_PROXY_* environment variables when using older CodeQL - // CLIs, as they are not needed and can cause issues. - if ( - process.env.CODEQL_PROXY_HOST === "" && - !(await util.codeQlVersionAtLeast(codeql, "2.20.7")) - ) { - delete process.env.CODEQL_PROXY_HOST; - delete process.env.CODEQL_PROXY_PORT; - delete process.env.CODEQL_PROXY_CA_CERTIFICATE; - } - if (actionsUtil.getOptionalInput("cleanup-level")) { logger.info( "The 'cleanup-level' input is ignored since the CodeQL Action now automatically " + diff --git a/src/analyze.ts b/src/analyze.ts index d585fd6d8..4eeb447e1 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -124,7 +124,7 @@ export async function runExtraction( language === BuiltInLanguage.cpp && config.buildMode === BuildMode.Autobuild ) { - await setupCppAutobuild(codeql, logger); + await setupCppAutobuild(logger); } // The Java and C# `build-mode: none` extractors place dependencies in the diff --git a/src/autobuild.ts b/src/autobuild.ts index 46412a0f4..44f6abd0c 100644 --- a/src/autobuild.ts +++ b/src/autobuild.ts @@ -110,7 +110,7 @@ export async function determineAutobuildLanguages( return languages; } -export async function setupCppAutobuild(codeql: CodeQL, logger: Logger) { +export async function setupCppAutobuild(logger: Logger) { const envVar = featureConfig[Feature.CppDependencyInstallation].envVar; const featureName = "C++ automatic installation of dependencies"; const gitHubVersion = await getGitHubVersion(); @@ -121,7 +121,7 @@ export async function setupCppAutobuild(codeql: CodeQL, logger: Logger) { getTemporaryDirectory(), logger, ); - if (await features.getValue(Feature.CppDependencyInstallation, codeql)) { + if (await features.getValue(Feature.CppDependencyInstallation)) { // disable autoinstall on self-hosted runners unless explicitly requested if ( process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] === "self-hosted" && @@ -155,7 +155,7 @@ export async function runAutobuild( logger.startGroup(`Attempting to automatically build ${language} code`); const codeQL = await getCodeQL(logger, config.codeQLCmd); if (language === BuiltInLanguage.cpp) { - await setupCppAutobuild(codeQL, logger); + await setupCppAutobuild(logger); } if (config.buildMode) { await codeQL.extractUsingBuildMode(config, language); diff --git a/src/codeql.ts b/src/codeql.ts index 25f30f877..717e089bb 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -253,7 +253,7 @@ let cachedCodeQL: CodeQL | undefined = undefined; * The version flags below can be used to conditionally enable certain features * on versions newer than this. */ -const CODEQL_MINIMUM_VERSION = "2.19.4"; +const CODEQL_MINIMUM_VERSION = "2.20.7"; /** * This version will shortly become the oldest version of CodeQL that the Action will run with. diff --git a/src/debug-artifacts.test.ts b/src/debug-artifacts.test.ts index 370816aef..16ecb6d5d 100644 --- a/src/debug-artifacts.test.ts +++ b/src/debug-artifacts.test.ts @@ -55,25 +55,20 @@ test("getArtifactSuffix", (t) => { } }); -// These next tests check the correctness of the logic to determine whether or not -// artifacts are uploaded in debug mode. Since it's not easy to mock the actual -// call to upload an artifact, we just check that we get an "upload-failed" result, -// instead of actually uploading the artifact. -// -// For tests where we expect artifact upload to be blocked, we check for a different -// response from the function. +// These next tests check whether `uploadArtifacts` attempts to upload an artifact. Since it's not +// easy to mock the actual call to upload an artifact, we check that we get an "upload-failed" +// result, instead of actually uploading the artifact. -test("uploadDebugArtifacts when artifacts empty should emit 'no-artifacts-to-upload'", async (t) => { +test("uploadArtifacts returns 'no-artifacts-to-upload' when there are no files to upload", async (t) => { // Test that no error is thrown if artifacts list is empty. const logger = getActionsLogger(); await t.notThrowsAsync(async () => { - const uploaded = await debugArtifacts.uploadDebugArtifacts( + const uploaded = await debugArtifacts.uploadArtifacts( logger, [], "i-dont-exist", "artifactName", GitHubVariant.DOTCOM, - undefined, ); t.is( uploaded, @@ -83,17 +78,15 @@ test("uploadDebugArtifacts when artifacts empty should emit 'no-artifacts-to-upl }); }); -test("uploadDebugArtifacts when no codeql version is used should invoke artifact upload", async (t) => { - // Test that the artifact is uploaded. +test("uploadArtifacts attempts an upload when there are files to upload", async (t) => { const logger = getActionsLogger(); await t.notThrowsAsync(async () => { - const uploaded = await debugArtifacts.uploadDebugArtifacts( + const uploaded = await debugArtifacts.uploadArtifacts( logger, ["hucairz"], "i-dont-exist", "artifactName", GitHubVariant.DOTCOM, - undefined, ); t.is( uploaded, @@ -103,44 +96,3 @@ test("uploadDebugArtifacts when no codeql version is used should invoke artifact ); }); }); - -test("uploadDebugArtifacts when new codeql version is used should invoke artifact upload", async (t) => { - // Test that the artifact is uploaded. - const logger = getActionsLogger(); - await t.notThrowsAsync(async () => { - const uploaded = await debugArtifacts.uploadDebugArtifacts( - logger, - ["hucairz"], - "i-dont-exist", - "artifactName", - GitHubVariant.DOTCOM, - "2.20.3", - ); - t.is( - uploaded, - // The failure is expected since we don't want to actually upload any artifacts in unit tests. - "upload-failed", - "Expect failure to upload artifacts since root dir does not exist", - ); - }); -}); - -test("uploadDebugArtifacts when old codeql is used should avoid trying to upload artifacts", async (t) => { - // Test that the artifact is not uploaded. - const logger = getActionsLogger(); - await t.notThrowsAsync(async () => { - const uploaded = await debugArtifacts.uploadDebugArtifacts( - logger, - ["hucairz"], - "i-dont-exist", - "artifactName", - GitHubVariant.DOTCOM, - "2.20.2", - ); - t.is( - uploaded, - "upload-not-supported", - "Expected artifact upload to be blocked because of old CodeQL version", - ); - }); -}); diff --git a/src/debug-artifacts.ts b/src/debug-artifacts.ts index afb3d3d1c..70c9a0ebd 100644 --- a/src/debug-artifacts.ts +++ b/src/debug-artifacts.ts @@ -15,10 +15,6 @@ import { EnvVar, exportEnvVar } from "./environment"; import * as json from "./json"; import { Language } from "./languages"; import { Logger, withGroup } from "./logging"; -import { - isSafeArtifactUpload, - SafeArtifactUploadVersion, -} from "./tools-features"; import { bundleDb, doesDirectoryExist, @@ -40,7 +36,6 @@ export function sanitizeArtifactName(name: string): string { export async function uploadCombinedSarifArtifacts( logger: Logger, gitHubVariant: GitHubVariant, - codeQlVersion: string | undefined, ) { const tempDir = getTemporaryDirectory(); @@ -70,13 +65,12 @@ export async function uploadCombinedSarifArtifacts( } try { - await uploadDebugArtifacts( + await uploadArtifacts( logger, toUpload, baseTempDir, "combined-sarif-artifacts", gitHubVariant, - codeQlVersion, ); } catch (e) { logger.warning( @@ -172,7 +166,6 @@ export async function tryUploadAllAvailableDebugArtifacts( codeql: CodeQL, config: Config, logger: Logger, - codeQlVersion: string | undefined, ) { const filesToUpload: string[] = []; try { @@ -231,13 +224,12 @@ export async function tryUploadAllAvailableDebugArtifacts( try { await withGroup("Uploading debug artifacts", async () => - uploadDebugArtifacts( + uploadArtifacts( logger, filesToUpload, config.dbLocation, config.debugArtifactName, config.gitHubVersion.type, - codeQlVersion, ), ); } catch (e) { @@ -283,26 +275,6 @@ export type UploadArtifactsResult = | "upload-successful" | "upload-failed"; -export async function uploadDebugArtifacts( - logger: Logger, - toUpload: string[], - rootDir: string, - artifactName: string, - ghVariant: GitHubVariant, - codeQlVersion: string | undefined, -): Promise { - const uploadSupported = isSafeArtifactUpload(codeQlVersion); - - if (!uploadSupported) { - core.info( - `Skipping debug artifact upload because the current CLI does not support safe upload. Please upgrade to CLI v${SafeArtifactUploadVersion} or later.`, - ); - return "upload-not-supported"; - } - - return uploadArtifacts(logger, toUpload, rootDir, artifactName, ghVariant); -} - /** * Uploads the specified files as a single workflow artifact. * diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 59b50e2df..f74d0bd25 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -240,7 +240,7 @@ export const featureConfig = { defaultValue: false, envVar: "CODEQL_EXTRACTOR_CPP_AUTOINSTALL_DEPENDENCIES", legacyApi: true, - minimumVersion: "2.15.0", + minimumVersion: undefined, }, [Feature.CsharpCacheBuildModeNone]: { defaultValue: false, diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index 0e6dae13a..93ee391aa 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -326,7 +326,6 @@ export async function uploadFailureInfo( codeql: CodeQL, config: Config, logger: Logger, - codeQlVersion: string, ) => Promise, printDebugLogs: (config: Config) => Promise, codeql: CodeQL, @@ -381,13 +380,7 @@ export async function uploadFailureInfo( logger.info( "Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts...", ); - const version = await codeql.getVersion(); - await uploadAllAvailableDebugArtifacts( - codeql, - config, - logger, - version.version, - ); + await uploadAllAvailableDebugArtifacts(codeql, config, logger); await printDebugLogs(config); } diff --git a/src/init-action.ts b/src/init-action.ts index 245957fd5..b759782ef 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -5,7 +5,12 @@ import * as core from "@actions/core"; import * as io from "@actions/io"; import * as semver from "semver"; -import { Action, ActionState, runInActions } from "./action-common"; +import { + Action, + ActionState, + extendActionState, + runInActions, +} from "./action-common"; import { FileCmdNotFoundError, getActionVersion, @@ -277,7 +282,9 @@ async function run( } // Compute the value of the `config-file` input. - const actionStateWithFeatures = { ...actionState, features }; + const actionStateWithFeatures = extendActionState(actionState, { + features, + }); configFile = await getConfigFileInput( actionStateWithFeatures, repositoryProperties, @@ -348,7 +355,7 @@ async function run( // to the workflow log. No exceptions are thrown. await checkWorkflow(logger, codeql); - // Set CODEQL_ENABLE_EXPERIMENTAL_FEATURES for Rust if between 2.19.3 (included) and 2.22.1 (excluded) + // Set CODEQL_ENABLE_EXPERIMENTAL_FEATURES for Rust if the CLI is older than 2.22.1. // We need to set this environment variable before initializing the config, otherwise Rust // analysis will not be enabled (experimental language packs are only active with that environment // variable set to `true`). @@ -359,14 +366,8 @@ async function run( .getRawLanguagesNoAutodetect(getOptionalInput("languages")) .includes(BuiltInLanguage.rust) ) { - const experimental = "2.19.3"; const publicPreview = "2.22.1"; const actualVer = (await codeql.getVersion()).version; - if (semver.lt(actualVer, experimental)) { - throw new ConfigurationError( - `Rust analysis is supported by CodeQL CLI version ${experimental} or higher, but found version ${actualVer}`, - ); - } if (semver.lt(actualVer, publicPreview)) { actionState.env.export(EnvVar.EXPERIMENTAL_FEATURES, "true"); logger.info("Experimental Rust analysis enabled"); @@ -632,15 +633,6 @@ async function run( actionState.env.export("CODEQL_GIT_BACKEND", "jgit"); } - const kotlinLimitVar = - "CODEQL_EXTRACTOR_KOTLIN_OVERRIDE_MAXIMUM_VERSION_LIMIT"; - if ( - (await codeQlVersionAtLeast(codeql, "2.20.3")) && - !(await codeQlVersionAtLeast(codeql, "2.20.4")) - ) { - actionState.env.export(kotlinLimitVar, "2.1.20"); - } - // Restore dependency cache(s), if they exist. if (shouldRestoreCache(config.dependencyCachingEnabled)) { const dependencyCachingResult = await downloadDependencyCaches( diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index ccd68288d..1344b66b7 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -1,6 +1,11 @@ import * as core from "@actions/core"; -import { Action, ActionState, runInActions } from "./action-common"; +import { + Action, + ActionState, + extendActionState, + runInActions, +} from "./action-common"; import { getActionVersion, getOptionalInput, @@ -131,7 +136,9 @@ async function run( ); const repositoryProperties = repositoryPropertiesResult.orElse({}); - const actionStateWithFeatures = { ...actionState, features }; + const actionStateWithFeatures = extendActionState(actionState, { + features, + }); const statusReportBase = await createStatusReportBase( ActionName.SetupCodeQL, diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index d965a2dd6..bc3351da5 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -3,7 +3,12 @@ import * as path from "path"; import * as core from "@actions/core"; -import { Action, ActionState, runInActions } from "./action-common"; +import { + Action, + ActionState, + extendActionState, + runInActions, +} from "./action-common"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; import { FeatureEnablement, initFeatures } from "./feature-flags"; @@ -98,7 +103,8 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { }; // Start the Proxy - const proxyBin = await getProxyBinaryPath({ ...action, features }); + const actionWithFeatures = extendActionState(action, { features }); + const proxyBin = await getProxyBinaryPath(actionWithFeatures); const proxyInfo = await startProxy( proxyBin, proxyConfig, diff --git a/src/tools-features.ts b/src/tools-features.ts index 4931be65b..35e626c88 100644 --- a/src/tools-features.ts +++ b/src/tools-features.ts @@ -1,5 +1,3 @@ -import * as semver from "semver"; - import type { VersionInfo } from "./cli/types"; export enum ToolsFeature { @@ -23,21 +21,3 @@ export function isSupportedToolsFeature( ): boolean { return !!versionInfo.features && versionInfo.features[feature]; } - -export const SafeArtifactUploadVersion = "2.20.3"; - -/** - * The first version of the CodeQL CLI where artifact upload is safe to use - * for failed runs. This is not really a feature flag, but it is easiest to - * model the behavior as a feature flag. - * - * This was not captured in a tools feature, so we need to use semver. - * - * @param codeQlVersion The version of the CodeQL CLI to check. If not provided, it is assumed to be safe. - * @returns True if artifact upload is safe to use for failed runs or false otherwise. - */ -export function isSafeArtifactUpload(codeQlVersion?: string): boolean { - return !codeQlVersion - ? true - : semver.gte(codeQlVersion, SafeArtifactUploadVersion); -} diff --git a/src/upload-sarif-action-post.ts b/src/upload-sarif-action-post.ts index bc0e1361c..82961842e 100644 --- a/src/upload-sarif-action-post.ts +++ b/src/upload-sarif-action-post.ts @@ -34,13 +34,7 @@ export async function runWrapper() { return; } await withGroup("Uploading combined SARIF debug artifact", () => - debugArtifacts.uploadCombinedSarifArtifacts( - logger, - gitHubVersion.type, - // The codeqlVersion is not applicable for uploading non-codeql sarif. - // We can assume all versions are safe to upload. - undefined, - ), + debugArtifacts.uploadCombinedSarifArtifacts(logger, gitHubVersion.type), ); } } catch (error) { diff --git a/unreleased-change-notes/README.md b/unreleased-change-notes/README.md new file mode 100644 index 000000000..60778c795 --- /dev/null +++ b/unreleased-change-notes/README.md @@ -0,0 +1,24 @@ +## Change notes + +Change-notes are Markdown files used to document user-facing changes. When making a change that affects users, create a Markdown file here that describes the change. During the next release, the change-note files in `unreleased-change-notes/` will automatically be added to `CHANGELOG.md`. + +### Change-note file format + +Change-note files must follow a certain format so that they can be automatically validated and processed. Failure to follow the format will result in a failed PR check. + +You may validate your change-note file locally by running `npx tsx pr-checks/changenotes.ts validate`. This command will scan all change-note files in `unreleased-change-notes/` and report any errors. + + +#### Body + +The body of the change-note file must: + +- Be written in valid [GitHub-Flavored Markdown](https://github.github.com/gfm/). +- Be structured as a single unordered Markdown list with hyphen (`-`) bullets. Each list item should describe a single change. If there are multiple changes, use multiple list items. + +### Example change-note file + +``` +- Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#4061](https://github.com/github/codeql-action/pull/4061) +- Fix incorrect minimum required Git version for [improved incremental analysis](https://github.com/github/roadmap/issues/1158): it should have been 2.36.0, not 2.11.0. [#3781](https://github.com/github/codeql-action/pull/3781) +```