cli: fixes for success cache hashing for workspace path and .eslintignore

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-10-24 14:00:18 +02:00
parent 58789bd199
commit 4046d536aa
5 changed files with 34 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Fixed an issue where the `--successCache` option for the `repo test` and `repo lint` commands would be include the workspace path in generated cache keys. This previously broke caching in environments where the workspace path varies across builds.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Fixed an issue with the `repo lint` command where the cache key for the `--successCache` option would not properly ignore files that should be ignored according to `.eslintignore`s.
+10 -6
View File
@@ -125,8 +125,7 @@ export async function command(opts: OptionValues, cmd: Command): Promise<void> {
const globby = require('globby') as typeof import('globby');
const { readFile } =
require('fs/promises') as typeof import('fs/promises');
const { relative: workerRelativePath } =
require('path') as typeof import('path');
const workerPath = require('path') as typeof import('path');
return async ({
fullDir,
@@ -163,15 +162,20 @@ export async function command(opts: OptionValues, cmd: Command): Promise<void> {
hash.update('\0');
for (const path of result.sort()) {
if (await eslint.isPathIgnored(path)) {
const absPath = workerPath.resolve(rootDir, path);
const pathInPackage = workerPath.relative(fullDir, absPath);
if (await eslint.isPathIgnored(pathInPackage)) {
continue;
}
hash.update(workerRelativePath(fullDir, path));
hash.update(pathInPackage);
hash.update('\0');
hash.update(await readFile(path));
hash.update(await readFile(absPath));
hash.update('\0');
hash.update(
JSON.stringify(await eslint.calculateConfigForFile(path)),
JSON.stringify(
await eslint.calculateConfigForFile(pathInPackage),
).replaceAll(rootDir, ''),
);
hash.update('\0');
}
+4 -2
View File
@@ -300,7 +300,9 @@ export async function command(opts: OptionValues, cmd: Command): Promise<void> {
baseHash.update('\0');
baseHash.update(process.version); // Node.js version
baseHash.update('\0');
baseHash.update(JSON.stringify(globalRootConfig)); // Variable global jest config
baseHash.update(
SuccessCache.trimPaths(JSON.stringify(globalRootConfig)),
); // Variable global jest config
const baseSha = baseHash.digest('hex');
return projectConfigs.filter(project => {
@@ -326,7 +328,7 @@ export async function command(opts: OptionValues, cmd: Command): Promise<void> {
// The project ID is a hash of the transform configuration, which helps
// us bust the cache when any changes are made to the transform implementation.
hash.update(JSON.stringify(project));
hash.update(SuccessCache.trimPaths(JSON.stringify(project)));
hash.update(lockfile.getDependencyTreeHash(packageName));
const sha = hash.digest('hex');
+10
View File
@@ -16,6 +16,7 @@
import fs from 'fs-extra';
import { resolve as resolvePath } from 'node:path';
import { paths } from '../paths';
const DEFAULT_CACHE_BASE_PATH = 'node_modules/.cache/backstage-cli';
@@ -24,6 +25,15 @@ const CACHE_MAX_AGE_MS = 7 * 24 * 3600_000;
export class SuccessCache {
readonly #path: string;
/**
* Trim any occurrences of the workspace root path from the input string. This
* is useful to ensure stable hashes that don't vary based on the workspace
* location.
*/
static trimPaths(input: string) {
return input.replaceAll(paths.targetRoot, '');
}
constructor(name: string, basePath?: string) {
this.#path = resolvePath(basePath ?? DEFAULT_CACHE_BASE_PATH, name);
}