diff --git a/.changeset/seven-ladybugs-fetch.md b/.changeset/seven-ladybugs-fetch.md new file mode 100644 index 0000000000..31c670f181 --- /dev/null +++ b/.changeset/seven-ladybugs-fetch.md @@ -0,0 +1,5 @@ +--- +'yarn-plugin-backstage': patch +--- + +Add additional check before packing workspace to verify that all backstage:^ versions have been removed. diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts index ca99b88437..d156182923 100644 --- a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts @@ -28,6 +28,14 @@ jest.mock('@backstage/release-manifests', () => ({ name: '@backstage/core', version: '3.2.1', }, + { + name: '@backstage/plugin-1', + version: '6.5.4', + }, + { + name: '@backstage/plugin-2', + version: '9.8.7', + }, ], }), })); @@ -100,7 +108,29 @@ describe('beforeWorkspacePacking', () => { await expect(() => beforeWorkspacePacking(makeWorkspace(result), result), - ).rejects.toThrow(); + ).rejects.toThrow(/unexpected version range/i); + }); + + it(`throws an error if the final manifest unexpectedly contains backstage: versions`, async () => { + const result = { + name: 'test-package', + [dependencyType]: { + get ['@backstage/core']() { + return 'backstage:^'; + }, + set ['@backstage/core'](_value: unknown) { + // ignore the attempt to set the value to + // allow testing the validation logic at + // the end of the hook. + }, + '@backstage/plugin-1': 'backstage:^', + '@backstage/plugin-2': 'backstage:^', + }, + }; + + await expect(() => + beforeWorkspacePacking(makeWorkspace(result), result), + ).rejects.toThrow(/failed to replace all "backstage:" ranges/i); }); it('converts backstage:^ versions to the corresponding package version prefixed by ^', async () => { diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts index b804f64226..41014a55a6 100644 --- a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts @@ -15,9 +15,13 @@ */ import { Descriptor, Workspace, structUtils } from '@yarnpkg/core'; +import { some } from 'lodash'; import { getCurrentBackstageVersion, getPackageVersion } from '../util'; import { PROTOCOL } from '../constants'; +const hasBackstageVersion = (range: string) => + structUtils.parseRange(range).protocol === PROTOCOL; + const getFinalDependencyType = ( dependencyType: string, descriptor: Descriptor, @@ -69,4 +73,15 @@ export const beforeWorkspacePacking = async ( )}`; } } + + if ( + some( + ['dependencies', 'devDependencies', 'optionalDependencies'], + dependencyType => some(rawManifest[dependencyType], hasBackstageVersion), + ) + ) { + throw new Error( + `Failed to replace all "backstage:" ranges in manifest for ${rawManifest.name}`, + ); + } };