Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
a691497
Clean up `resolve_supported_languages_using_cli` FF
henrymercer Oct 22, 2025
c228fec
Update changelog and version after v4.31.2
github-actions[bot] Oct 30, 2025
65da12b
Rebuild
github-actions[bot] Oct 30, 2025
9bd8638
Merge pull request #3262 from github/mergeback/v4.31.2-to-main-0499de31
henrymercer Oct 30, 2025
64db1da
Create immutable action version on tag push
mbg Oct 31, 2025
338146c
Merge pull request #3264 from github/mbg/ci/publish-on-tag
mbg Oct 31, 2025
7d1bed2
Bump @octokit/types from 15.0.1 to 16.0.0
dependabot[bot] Nov 3, 2025
8fa298d
Bump @actions/http-client from 2.2.3 to 3.0.0
dependabot[bot] Nov 3, 2025
5313cd1
Rebuild
github-actions[bot] Nov 3, 2025
61bcb70
Rebuild
github-actions[bot] Nov 3, 2025
7ad64f0
Merge pull request #3270 from github/dependabot/npm_and_yarn/actions/…
henrymercer Nov 3, 2025
97580d7
Merge pull request #3267 from github/dependabot/npm_and_yarn/octokit/…
henrymercer Nov 3, 2025
a3ea4ef
Bump the npm-minor group with 7 updates
dependabot[bot] Nov 3, 2025
85eb524
Rebuild
github-actions[bot] Nov 4, 2025
98e0ffe
Merge pull request #3266 from github/dependabot/npm_and_yarn/npm-mino…
henrymercer Nov 4, 2025
58f5e3d
Bump @types/archiver from 6.0.4 to 7.0.0
dependabot[bot] Nov 4, 2025
f23547c
Rebuild
github-actions[bot] Nov 4, 2025
493ffd8
Merge pull request #3268 from github/dependabot/npm_and_yarn/types/ar…
henrymercer Nov 4, 2025
a53b496
Bump @actions/io from 1.1.3 to 2.0.0
dependabot[bot] Nov 4, 2025
238f5f2
Rebuild
github-actions[bot] Nov 4, 2025
95b1867
Merge pull request #3269 from github/dependabot/npm_and_yarn/actions/…
henrymercer Nov 4, 2025
1aade29
Update deprecation warnings for CodeQL Action to v4
mario-campos Nov 4, 2025
5a9b49d
Update CHANGELOG to reflect warning for v3 users migrating to v4 of C…
mario-campos Nov 4, 2025
ba82f9b
Fix deprecation warning to reflect that v3 is not actually deprecated…
mario-campos Nov 4, 2025
f1ca6a4
Update tests to reflect deprecation status of CodeQL Action v3
mario-campos Nov 4, 2025
08dc635
Restore use of `sinon.match()`.
mario-campos Nov 4, 2025
b32a1e0
Update test cases for GitHub Enterprise Server versions 3.11 and 3.12…
mario-campos Nov 4, 2025
c443dff
Simplify warning language to not enumerate deprecated versions.
mario-campos Nov 4, 2025
9366f80
Reference GHES 3.20 in the comment, not 3.19.
mario-campos Nov 4, 2025
a570795
Clarify the CHANGELOG.md entry to reflect the whole action, and not j…
mario-campos Nov 4, 2025
9d5565f
Remove `macos-13` from `codeql` workflow
mbg Nov 4, 2025
d03fd76
Filter CCR jobs in `update-required-checks.sh`
mbg Nov 4, 2025
b00addd
Merge pull request #3274 from github/mbg/macos-13
mbg Nov 5, 2025
862f566
Merge pull request #3275 from github/mbg/checks/filter-ccr
mbg Nov 5, 2025
5aa2d63
Merge branch 'main' into mario-campos/v4-warning
mbg Nov 5, 2025
33684ef
Add `setup-python` step to `update-bundle` workflow
mbg Nov 5, 2025
c9f82f2
Move python script to file
mbg Nov 5, 2025
6dd11f7
Update .github/workflows/script/bundle_changelog.py
mbg Nov 5, 2025
423d14e
Merge pull request #3277 from github/mbg/ci/update-bundle-python
mbg Nov 5, 2025
e2ef519
Merge pull request #3224 from github/henrymercer/clean-up-resolve-lan…
henrymercer Nov 5, 2025
6a63bc6
Change warning message to just v3 (exclude v1, v2).
mario-campos Nov 5, 2025
ecee3ea
Update CHANGELOG.md.
mario-campos Nov 5, 2025
74f6621
Reformat with eslint
mario-campos Nov 5, 2025
b5e5a25
Merge branch 'main' into mario-campos/v4-warning
mario-campos Nov 5, 2025
1ca20ab
Add `CsharpNewCacheKey` FF
mbg Sep 17, 2025
2aa1f55
Propagate `features` into `cachePrefix` function
mbg Sep 17, 2025
2a7680f
Change `getDefaultCacheConfig` to be a `const` by turning `paths` int…
mbg Sep 17, 2025
ab1c842
Change `hash` to be a function that can use `Features`
mbg Sep 17, 2025
320a6b6
Merge pull request #3272 from github/mario-campos/v4-warning
mario-campos Nov 5, 2025
6b48207
Move check whether there are files for hashing into `getHashPatterns`
mbg Sep 17, 2025
0324490
Use additional files for C# key hashes if `Feature.CsharpNewCacheKey`…
mbg Sep 17, 2025
0cbd930
Move `createCacheKeyHash` to `caching-utils`
mbg Nov 5, 2025
03b2dc2
Add and use `getFeaturePrefix` for dependency caching
mbg Nov 5, 2025
2680455
Use `undefined` instead of `NoMatchingFilesError`
mbg Nov 5, 2025
04285cb
Use generic types for durations in status report
henrymercer Nov 5, 2025
71d0a56
Merge pull request #3278 from github/henrymercer/type-fun
henrymercer Nov 6, 2025
46e03b4
Fix JSDoc param name
mbg Nov 9, 2025
5b58b8f
Linter: check JSDoc parameter names exist
mbg Nov 9, 2025
71abac7
Fix comment in `getCsharpHashPatterns`
mbg Nov 9, 2025
35c91ef
Add tests for `getCsharpHashPatterns`
mbg Nov 9, 2025
b0e9dfc
Restore missing `status.push` resulting from a bad merge
mbg Nov 9, 2025
a47d550
Restore earlier log messages for `checkHashPatterns`
mbg Nov 9, 2025
4885eb2
Insert new `featurePrefix` after general cache key `prefix`
mbg Nov 9, 2025
48a56f6
Add some tests for `downloadDependencyCaches` related to feature pref…
mbg Nov 9, 2025
04bd5c6
Merge pull request #3279 from github/mbg/lint/jsdoc-param-names
mbg Nov 10, 2025
63bb415
Bump the npm-minor group with 4 updates
dependabot[bot] Nov 10, 2025
3d7be7b
Rebuild
github-actions[bot] Nov 10, 2025
1d9f357
Merge pull request #3281 from github/dependabot/npm_and_yarn/npm-mino…
henrymercer Nov 11, 2025
534824e
Merge pull request #3117 from github/mbg/csharp/new-cache-key-calcula…
mbg Nov 12, 2025
71c3720
Run `npm ci` in `update-supported-enterprise-server-versions.yml`
mbg Nov 12, 2025
a7e52b6
Perform sparse checkout
mbg Nov 12, 2025
fd830db
Trigger on PR for relevant changes
mbg Nov 12, 2025
7a7cd85
Don't push for PR event
mbg Nov 12, 2025
ba454b8
Merge pull request #3284 from github/mbg/ci/fix-enterprise-workflow
mbg Nov 12, 2025
362f8d1
Update default bundle to codeql-bundle-v2.23.5
github-actions[bot] Nov 13, 2025
8d3d400
Add changelog note
github-actions[bot] Nov 13, 2025
f20e021
Add support for adding `setup-dotnet` steps to `sync.sh`
mbg Nov 13, 2025
58c9eb6
Add `global.json`
mbg Nov 13, 2025
38a3a72
Enable `installDotNet` in all workflows that analyse C#
mbg Nov 13, 2025
3fac49c
Update remaining workflows
mbg Nov 13, 2025
456a74a
Merge pull request #3289 from github/mbg/ci/setup-dotnet
henrymercer Nov 13, 2025
9777b01
Merge branch 'main' into update-bundle/codeql-bundle-v2.23.5
mbg Nov 13, 2025
8c10e89
Merge pull request #3288 from github/update-bundle/codeql-bundle-v2.23.5
mbg Nov 13, 2025
14d898e
Update changelog for v4.31.3
github-actions[bot] Nov 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use undefined instead of NoMatchingFilesError
Add tests for `makePatternCheck` and `checkHashPatterns`
  • Loading branch information
mbg committed Nov 5, 2025
commit 26804552e4e731f906550537f732e8dc17c10d0d
26 changes: 8 additions & 18 deletions lib/analyze-action.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 8 additions & 18 deletions lib/init-action.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 91 additions & 2 deletions src/dependency-caching.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,104 @@
import * as fs from "fs";
import path from "path";

import test from "ava";

// import * as sinon from "sinon";

import { cacheKeyHashLength } from "./caching-utils";
import { createStubCodeQL } from "./codeql";
import { getFeaturePrefix } from "./dependency-caching";
import {
CacheConfig,
checkHashPatterns,
getFeaturePrefix,
makePatternCheck,
} from "./dependency-caching";
import { Feature } from "./feature-flags";
import { KnownLanguage } from "./languages";
import { setupTests, createFeatures } from "./testing-utils";
import {
setupTests,
createFeatures,
getRecordingLogger,
checkExpectedLogMessages,
LoggedMessage,
} from "./testing-utils";
import { withTmpDir } from "./util";

setupTests(test);

function makeAbsolutePatterns(tmpDir: string, patterns: string[]): string[] {
return patterns.map((pattern) => path.join(tmpDir, pattern));
}

test("makePatternCheck - returns undefined if no patterns match", async (t) => {
await withTmpDir(async (tmpDir) => {
fs.writeFileSync(path.join(tmpDir, "test.java"), "");
const result = await makePatternCheck(
makeAbsolutePatterns(tmpDir, ["**/*.cs"]),
);
t.is(result, undefined);
});
});

test("makePatternCheck - returns all patterns if any pattern matches", async (t) => {
await withTmpDir(async (tmpDir) => {
fs.writeFileSync(path.join(tmpDir, "test.java"), "");
const patterns = makeAbsolutePatterns(tmpDir, ["**/*.cs", "**/*.java"]);
const result = await makePatternCheck(patterns);
t.deepEqual(result, patterns);
});
});

test("checkHashPatterns - logs when no patterns match", async (t) => {
const codeql = createStubCodeQL({});
const features = createFeatures([]);
const messages: LoggedMessage[] = [];
const config: CacheConfig = {
getDependencyPaths: () => [],
getHashPatterns: async () => undefined,
};

const result = await checkHashPatterns(
codeql,
features,
KnownLanguage.csharp,
config,
getRecordingLogger(messages),
);

t.is(result, undefined);
checkExpectedLogMessages(t, messages, [
"Skipping download of dependency cache",
]);
});

test("checkHashPatterns - returns patterns when patterns match", async (t) => {
await withTmpDir(async (tmpDir) => {
const codeql = createStubCodeQL({});
const features = createFeatures([]);
const messages: LoggedMessage[] = [];
const patterns = makeAbsolutePatterns(tmpDir, ["**/*.cs", "**/*.java"]);

fs.writeFileSync(path.join(tmpDir, "test.java"), "");

const config: CacheConfig = {
getDependencyPaths: () => [],
getHashPatterns: async () => makePatternCheck(patterns),
};

const result = await checkHashPatterns(
codeql,
features,
KnownLanguage.csharp,
config,
getRecordingLogger(messages),
);

t.deepEqual(result, patterns);
t.deepEqual(messages, []);
});
});

test("getFeaturePrefix - returns empty string if no features are enabled", async (t) => {
const codeql = createStubCodeQL({});
const features = createFeatures([]);
Expand Down
61 changes: 28 additions & 33 deletions src/dependency-caching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,24 @@ import { KnownLanguage, Language } from "./languages";
import { Logger } from "./logging";
import { getErrorMessage, getRequiredEnvParam } from "./util";

class NoMatchingFilesError extends Error {
constructor(msg?: string) {
super(msg);

this.name = "NoMatchingFilesError";
}
}

/**
* Caching configuration for a particular language.
*/
interface CacheConfig {
export interface CacheConfig {
/** Gets the paths of directories on the runner that should be included in the cache. */
getDependencyPaths: () => string[];
/**
* Gets an array of glob patterns for the paths of files whose contents affect which dependencies are used
* by a project. This function also checks whether there are any matching files and throws
* a `NoMatchingFilesError` error if no files match.
* by a project. This function also checks whether there are any matching files and returns
* `undefined` if no files match.
*
* The glob patterns are intended to be used for cache keys, where we find all files which match these
* patterns, calculate a hash for their contents, and use that hash as part of the cache key.
*/
getHashPatterns: (codeql: CodeQL, features: Features) => Promise<string[]>;
getHashPatterns: (
codeql: CodeQL,
features: FeatureEnablement,
) => Promise<string[] | undefined>;
}

const CODEQL_DEPENDENCY_CACHE_PREFIX = "codeql-dependencies";
Expand Down Expand Up @@ -73,16 +68,18 @@ export function getJavaDependencyDirs(): string[] {

/**
* Checks that there are files which match `patterns`. If there are matching files for any of the patterns,
* this function returns all `patterns`. Otherwise, a `NoMatchingFilesError` is thrown.
* this function returns all `patterns`. Otherwise, `undefined` is returned.
*
* @param patterns The glob patterns to find matching files for.
* @returns The array of glob patterns if there are matching files.
* @returns The array of glob patterns if there are matching files, or `undefined` otherwise.
*/
async function makePatternCheck(patterns: string[]): Promise<string[]> {
export async function makePatternCheck(
patterns: string[],
): Promise<string[] | undefined> {
const globber = await makeGlobber(patterns);

if ((await globber.glob()).length === 0) {
throw new NoMatchingFilesError();
return undefined;
}

return patterns;
Expand All @@ -98,8 +95,8 @@ async function makePatternCheck(patterns: string[]): Promise<string[]> {
*/
async function getCsharpHashPatterns(
codeql: CodeQL,
features: Features,
): Promise<string[]> {
features: FeatureEnablement,
): Promise<string[] | undefined> {
// These files contain accurate information about dependencies, including the exact versions
// that the relevant package manager has determined for the project. Using these gives us
// stable hashes unless the dependencies change.
Expand Down Expand Up @@ -133,7 +130,7 @@ async function getCsharpHashPatterns(
// If we get to this point, the `basePatterns` didn't find any files,
// and `Feature.CsharpNewCacheKey` is either not enabled or we didn't
// find any files using those patterns either.
throw new NoMatchingFilesError();
return undefined;
}

/**
Expand Down Expand Up @@ -192,8 +189,8 @@ export interface DependencyCacheRestoreStatus {
export type DependencyCacheRestoreStatusReport = DependencyCacheRestoreStatus[];

/**
* A wrapper around `cacheConfig.getHashPatterns` which catches `NoMatchingFilesError` errors,
* and logs that there are no files to calculate a hash for the cache key from.
* A wrapper around `cacheConfig.getHashPatterns` which logs when there are no files to calculate
* a hash for the cache key from.
*
* @param codeql The CodeQL instance to use.
* @param features Information about which FFs are enabled.
Expand All @@ -202,24 +199,22 @@ export type DependencyCacheRestoreStatusReport = DependencyCacheRestoreStatus[];
* @param logger The logger to write the log message to if there is an error.
* @returns An array of glob patterns to use for hashing files, or `undefined` if there are no matching files.
*/
async function checkHashPatterns(
export async function checkHashPatterns(
codeql: CodeQL,
features: Features,
features: FeatureEnablement,
language: Language,
cacheConfig: CacheConfig,
logger: Logger,
): Promise<string[] | undefined> {
try {
return cacheConfig.getHashPatterns(codeql, features);
} catch (err) {
if (err instanceof NoMatchingFilesError) {
logger.info(
`Skipping download of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
);
return undefined;
}
throw err;
const patterns = await cacheConfig.getHashPatterns(codeql, features);

if (patterns === undefined) {
logger.info(
`Skipping download of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
);
}

return patterns;
}

/**
Expand Down
Loading