From 4046d536aa62b4a6734435960bf2a5051190fcc2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 24 Oct 2024 14:00:18 +0200 Subject: [PATCH] cli: fixes for success cache hashing for workspace path and .eslintignore Signed-off-by: Patrik Oldsberg --- .changeset/afraid-bananas-behave.md | 5 +++++ .changeset/short-geckos-sniff.md | 5 +++++ packages/cli/src/commands/repo/lint.ts | 16 ++++++++++------ packages/cli/src/commands/repo/test.ts | 6 ++++-- packages/cli/src/lib/cache/SuccessCache.ts | 10 ++++++++++ 5 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 .changeset/afraid-bananas-behave.md create mode 100644 .changeset/short-geckos-sniff.md diff --git a/.changeset/afraid-bananas-behave.md b/.changeset/afraid-bananas-behave.md new file mode 100644 index 0000000000..624b798c17 --- /dev/null +++ b/.changeset/afraid-bananas-behave.md @@ -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. diff --git a/.changeset/short-geckos-sniff.md b/.changeset/short-geckos-sniff.md new file mode 100644 index 0000000000..4d31ca436b --- /dev/null +++ b/.changeset/short-geckos-sniff.md @@ -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. diff --git a/packages/cli/src/commands/repo/lint.ts b/packages/cli/src/commands/repo/lint.ts index 9b1ce4ee3e..50ea09046b 100644 --- a/packages/cli/src/commands/repo/lint.ts +++ b/packages/cli/src/commands/repo/lint.ts @@ -125,8 +125,7 @@ export async function command(opts: OptionValues, cmd: Command): Promise { 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 { 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'); } diff --git a/packages/cli/src/commands/repo/test.ts b/packages/cli/src/commands/repo/test.ts index 5ce6bca342..7699c39dce 100644 --- a/packages/cli/src/commands/repo/test.ts +++ b/packages/cli/src/commands/repo/test.ts @@ -300,7 +300,9 @@ export async function command(opts: OptionValues, cmd: Command): Promise { 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 { // 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'); diff --git a/packages/cli/src/lib/cache/SuccessCache.ts b/packages/cli/src/lib/cache/SuccessCache.ts index 5370958537..a799970b4d 100644 --- a/packages/cli/src/lib/cache/SuccessCache.ts +++ b/packages/cli/src/lib/cache/SuccessCache.ts @@ -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); }