Address review feedback

- Remove cli changeset, piggy-back on existing ones
- Rename getHasYarnPlugin -> hasYarnPlugin(workspaceDir?)
- Make SuccessCache constructor private, add static create()
- Consolidate duplicate @backstage/cli-node imports

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2026-02-25 12:46:55 +01:00
parent 3c811bf8a9
commit 968570bbb5
11 changed files with 49 additions and 44 deletions
+5 -1
View File
@@ -40,7 +40,11 @@ export class SuccessCache {
return input.replaceAll(targetPaths.rootDir, '');
}
constructor(name: string, basePath?: string) {
static create(name: string, basePath?: string): SuccessCache {
return new SuccessCache(name, basePath);
}
private constructor(name: string, basePath?: string) {
this.#path = resolvePath(basePath ?? DEFAULT_CACHE_BASE_PATH, name);
}
+1 -1
View File
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { getHasYarnPlugin } from './yarnPlugin';
export { hasYarnPlugin } from './yarnPlugin';
+15 -14
View File
@@ -16,12 +16,12 @@
import { createMockDirectory } from '@backstage/backend-test-utils';
import { overrideTargetPaths } from '@backstage/cli-common/testUtils';
import { getHasYarnPlugin } from './yarnPlugin';
import { hasYarnPlugin } from './yarnPlugin';
const mockDir = createMockDirectory();
overrideTargetPaths(mockDir.path);
describe('getHasYarnPlugin', () => {
describe('hasYarnPlugin', () => {
beforeEach(() => {
mockDir.clear();
});
@@ -29,7 +29,7 @@ describe('getHasYarnPlugin', () => {
it('should return false when .yarnrc.yml does not exist', async () => {
mockDir.setContent({});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin();
expect(result).toBe(false);
});
@@ -38,7 +38,7 @@ describe('getHasYarnPlugin', () => {
'.yarnrc.yml': '',
});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin();
expect(result).toBe(false);
});
@@ -47,7 +47,7 @@ describe('getHasYarnPlugin', () => {
'.yarnrc.yml': 'plugins: []',
});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin();
expect(result).toBe(false);
});
@@ -60,7 +60,7 @@ plugins:
`,
});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin();
expect(result).toBe(false);
});
@@ -74,7 +74,7 @@ plugins:
`,
});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin();
expect(result).toBe(true);
});
@@ -86,7 +86,7 @@ plugins:
`,
});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin();
expect(result).toBe(true);
});
@@ -95,7 +95,7 @@ plugins:
'.yarnrc.yml': 'invalid: yaml: content: [',
});
await expect(getHasYarnPlugin()).rejects.toThrow();
await expect(hasYarnPlugin()).rejects.toThrow();
});
it('should throw error when .yarnrc.yml has unexpected structure', async () => {
@@ -105,21 +105,22 @@ plugins: "not an array"
`,
});
await expect(getHasYarnPlugin()).rejects.toThrow(
await expect(hasYarnPlugin()).rejects.toThrow(
'Unexpected content in .yarnrc.yml',
);
});
it('should handle plugins with different structure', async () => {
it('should resolve from a custom workspace directory', async () => {
mockDir.setContent({
'.yarnrc.yml': `
'custom-dir': {
'.yarnrc.yml': `
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-backstage.cjs
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
`,
},
});
const result = await getHasYarnPlugin();
const result = await hasYarnPlugin(mockDir.resolve('custom-dir'));
expect(result).toBe(true);
});
});
+9 -4
View File
@@ -15,6 +15,7 @@
*/
import fs from 'fs-extra';
import { resolve as resolvePath } from 'node:path';
import yaml from 'yaml';
import z from 'zod';
import { targetPaths } from '@backstage/cli-common';
@@ -30,13 +31,17 @@ const yarnRcSchema = z.object({
});
/**
* Detects whether the Backstage Yarn plugin is installed in the target repository.
* Detects whether the Backstage Yarn plugin is installed in the given workspace directory.
*
* @returns Promise<boolean> - true if the plugin is installed, false otherwise
* @param workspaceDir - The workspace root directory to check. Defaults to the target root.
* @returns Promise resolving to true if the plugin is installed, false otherwise
* @public
*/
export async function getHasYarnPlugin(): Promise<boolean> {
const yarnRcPath = targetPaths.resolveRoot('.yarnrc.yml');
export async function hasYarnPlugin(workspaceDir?: string): Promise<boolean> {
const yarnRcPath = resolvePath(
workspaceDir ?? targetPaths.rootDir,
'.yarnrc.yml',
);
const yarnRcContent = await fs.readFile(yarnRcPath, 'utf-8').catch(e => {
if (e.code === 'ENOENT') {
return '';