Skip to content

Commit 6b48207

Browse files
committed
Move check whether there are files for hashing into getHashPatterns
1 parent ab1c842 commit 6b48207

File tree

3 files changed

+176
-59
lines changed

3 files changed

+176
-59
lines changed

lib/analyze-action.js

Lines changed: 39 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/init-action.js

Lines changed: 39 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/dependency-caching.ts

Lines changed: 98 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,27 @@ import { KnownLanguage, Language } from "./languages";
1515
import { Logger } from "./logging";
1616
import { getErrorMessage, getRequiredEnvParam } from "./util";
1717

18+
class NoMatchingFilesError extends Error {
19+
constructor(msg?: string) {
20+
super(msg);
21+
22+
this.name = "NoMatchingFilesError";
23+
}
24+
}
25+
1826
/**
1927
* Caching configuration for a particular language.
2028
*/
2129
interface CacheConfig {
2230
/** Gets the paths of directories on the runner that should be included in the cache. */
2331
getDependencyPaths: () => string[];
2432
/**
25-
* Gets patterns for the paths of files whose contents affect which dependencies are used
26-
* by a project. We find all files which match these patterns, calculate a hash for
27-
* their contents, and use that hash as part of the cache key.
33+
* Gets an array of glob patterns for the paths of files whose contents affect which dependencies are used
34+
* by a project. This function also checks whether there are any matching files and throws
35+
* a `NoMatchingFilesError` error if no files match.
36+
*
37+
* The glob patterns are intended to be used for cache keys, where we find all files which match these
38+
* patterns, calculate a hash for their contents, and use that hash as part of the cache key.
2839
*/
2940
getHashPatterns: (codeql: CodeQL, features: Features) => Promise<string[]>;
3041
}
@@ -60,36 +71,55 @@ export function getJavaDependencyDirs(): string[] {
6071
];
6172
}
6273

74+
/**
75+
* Checks that there are files which match `patterns`. If there are matching files for any of the patterns,
76+
* this function returns all `patterns`. Otherwise, a `NoMatchingFilesError` is thrown.
77+
*
78+
* @param patterns The glob patterns to find matching files for.
79+
* @returns The array of glob patterns if there are matching files.
80+
*/
81+
async function makePatternCheck(patterns: string[]): Promise<string[]> {
82+
const globber = await makeGlobber(patterns);
83+
84+
if ((await globber.glob()).length === 0) {
85+
throw new NoMatchingFilesError();
86+
}
87+
88+
return patterns;
89+
}
90+
6391
/**
6492
* Default caching configurations per language.
6593
*/
6694
const defaultCacheConfigs: { [language: string]: CacheConfig } = {
6795
java: {
6896
getDependencyPaths: getJavaDependencyDirs,
69-
getHashPatterns: async () => [
70-
// Maven
71-
"**/pom.xml",
72-
// Gradle
73-
"**/*.gradle*",
74-
"**/gradle-wrapper.properties",
75-
"buildSrc/**/Versions.kt",
76-
"buildSrc/**/Dependencies.kt",
77-
"gradle/*.versions.toml",
78-
"**/versions.properties",
79-
],
97+
getHashPatterns: async () =>
98+
makePatternCheck([
99+
// Maven
100+
"**/pom.xml",
101+
// Gradle
102+
"**/*.gradle*",
103+
"**/gradle-wrapper.properties",
104+
"buildSrc/**/Versions.kt",
105+
"buildSrc/**/Dependencies.kt",
106+
"gradle/*.versions.toml",
107+
"**/versions.properties",
108+
]),
80109
},
81110
csharp: {
82111
getDependencyPaths: () => [join(os.homedir(), ".nuget", "packages")],
83-
getHashPatterns: async () => [
84-
// NuGet
85-
"**/packages.lock.json",
86-
// Paket
87-
"**/paket.lock",
88-
],
112+
getHashPatterns: async () =>
113+
makePatternCheck([
114+
// NuGet
115+
"**/packages.lock.json",
116+
// Paket
117+
"**/paket.lock",
118+
]),
89119
},
90120
go: {
91121
getDependencyPaths: () => [join(os.homedir(), "go", "pkg", "mod")],
92-
getHashPatterns: async () => ["**/go.sum"],
122+
getHashPatterns: async () => makePatternCheck(["**/go.sum"]),
93123
},
94124
};
95125

@@ -119,6 +149,37 @@ export interface DependencyCacheRestoreStatus {
119149
/** An array of `DependencyCacheRestoreStatus` objects for each analysed language with a caching configuration. */
120150
export type DependencyCacheRestoreStatusReport = DependencyCacheRestoreStatus[];
121151

152+
/**
153+
* A wrapper around `cacheConfig.getHashPatterns` which catches `NoMatchingFilesError` errors,
154+
* and logs that there are no files to calculate a hash for the cache key from.
155+
*
156+
* @param codeql The CodeQL instance to use.
157+
* @param features Information about which FFs are enabled.
158+
* @param language The language the `CacheConfig` is for. For use in the log message.
159+
* @param cacheConfig The caching configuration to call `getHashPatterns` on.
160+
* @param logger The logger to write the log message to if there is an error.
161+
* @returns An array of glob patterns to use for hashing files, or `undefined` if there are no matching files.
162+
*/
163+
async function checkHashPatterns(
164+
codeql: CodeQL,
165+
features: Features,
166+
language: Language,
167+
cacheConfig: CacheConfig,
168+
logger: Logger,
169+
): Promise<string[] | undefined> {
170+
try {
171+
return cacheConfig.getHashPatterns(codeql, features);
172+
} catch (err) {
173+
if (err instanceof NoMatchingFilesError) {
174+
logger.info(
175+
`Skipping download of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
176+
);
177+
return undefined;
178+
}
179+
throw err;
180+
}
181+
}
182+
122183
/**
123184
* Attempts to restore dependency caches for the languages being analyzed.
124185
*
@@ -149,14 +210,15 @@ export async function downloadDependencyCaches(
149210

150211
// Check that we can find files to calculate the hash for the cache key from, so we don't end up
151212
// with an empty string.
152-
const patterns = await cacheConfig.getHashPatterns(codeql, features);
153-
const globber = await makeGlobber(patterns);
154-
155-
if ((await globber.glob()).length === 0) {
213+
const patterns = await checkHashPatterns(
214+
codeql,
215+
features,
216+
language,
217+
cacheConfig,
218+
logger,
219+
);
220+
if (patterns === undefined) {
156221
status.push({ language, hit_kind: CacheHitKind.NoHash });
157-
logger.info(
158-
`Skipping download of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
159-
);
160222
continue;
161223
}
162224

@@ -245,14 +307,14 @@ export async function uploadDependencyCaches(
245307

246308
// Check that we can find files to calculate the hash for the cache key from, so we don't end up
247309
// with an empty string.
248-
const patterns = await cacheConfig.getHashPatterns(codeql, features);
249-
const globber = await makeGlobber(patterns);
250-
251-
if ((await globber.glob()).length === 0) {
252-
status.push({ language, result: CacheStoreResult.NoHash });
253-
logger.info(
254-
`Skipping upload of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
255-
);
310+
const patterns = await checkHashPatterns(
311+
codeql,
312+
features,
313+
language,
314+
cacheConfig,
315+
logger,
316+
);
317+
if (patterns === undefined) {
256318
continue;
257319
}
258320

0 commit comments

Comments
 (0)