From 999345432edd624f4bcb9107c21853aa29c015ea Mon Sep 17 00:00:00 2001 From: Cristiano Belloni Date: Tue, 9 Aug 2022 17:06:19 +0100 Subject: [PATCH] Adapt implementation and tests to new interface --- .../utils/getChangedWorkspaces.test.ts | 283 ++++++++++++++---- .../src/utils/getAllWorkspaces.ts | 5 +- .../src/utils/getChangedWorkspaces.ts | 32 +- 3 files changed, 247 insertions(+), 73 deletions(-) diff --git a/packages/modular-scripts/src/__tests__/utils/getChangedWorkspaces.test.ts b/packages/modular-scripts/src/__tests__/utils/getChangedWorkspaces.test.ts index ab20013c5..96747def7 100644 --- a/packages/modular-scripts/src/__tests__/utils/getChangedWorkspaces.test.ts +++ b/packages/modular-scripts/src/__tests__/utils/getChangedWorkspaces.test.ts @@ -1,24 +1,73 @@ import { matchWorkspaces } from '../../utils/getChangedWorkspaces'; +import type { WorkspaceContent } from '../../utils/getAllWorkspaces'; describe('matchWorkspaces', () => { it('matches absolute manifests paths with holes and duplication to subset of workspace entries', () => { - const workspaces = { - 'workspace-1': { - location: 'packages/workspace-1', - workspaceDependencies: ['workspace-2', 'workspace-3'], - mismatchedWorkspaceDependencies: [], - }, - 'workspace-2': { - location: 'packages/workspace-2', - workspaceDependencies: ['workspace-3'], - mismatchedWorkspaceDependencies: [], - }, - 'workspace-3': { - location: 'packages/workspace-3', - workspaceDependencies: [], - mismatchedWorkspaceDependencies: [], + const workspacesContent: WorkspaceContent = [ + new Map( + Object.entries({ + 'workspace-1': { + path: 'w1', + location: 'w1', + name: 'workspace-1', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + 'workspace-2': { + path: 'w2', + location: '/w2', + name: 'workspace-3', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + 'workspace-3': { + path: 'w3', + location: '/w3', + name: 'workspace-3', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + }), + ), + { + 'workspace-1': { + location: 'packages/workspace-1', + workspaceDependencies: ['workspace-2', 'workspace-3'], + mismatchedWorkspaceDependencies: [], + }, + 'workspace-2': { + location: 'packages/workspace-2', + workspaceDependencies: ['workspace-3'], + mismatchedWorkspaceDependencies: [], + }, + 'workspace-3': { + location: 'packages/workspace-3', + workspaceDependencies: [], + mismatchedWorkspaceDependencies: [], + }, }, - }; + ]; const listOfPackageManifests = [ '/my/path/packages/workspace-1/package.json', @@ -28,62 +77,178 @@ describe('matchWorkspaces', () => { ]; expect( - matchWorkspaces(listOfPackageManifests, '/my/path', workspaces), - ).toEqual({ - 'workspace-1': { - location: 'packages/workspace-1', - workspaceDependencies: ['workspace-2', 'workspace-3'], - mismatchedWorkspaceDependencies: [], - }, - 'workspace-3': { - location: 'packages/workspace-3', - workspaceDependencies: [], - mismatchedWorkspaceDependencies: [], + matchWorkspaces(listOfPackageManifests, '/my/path', workspacesContent), + ).toEqual([ + new Map( + Object.entries({ + 'workspace-1': { + path: 'w1', + location: 'w1', + name: 'workspace-1', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + 'workspace-3': { + path: 'w3', + location: '/w3', + name: 'workspace-3', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + }), + ), + { + 'workspace-1': { + location: 'packages/workspace-1', + workspaceDependencies: ['workspace-2', 'workspace-3'], + mismatchedWorkspaceDependencies: [], + }, + 'workspace-3': { + location: 'packages/workspace-3', + workspaceDependencies: [], + mismatchedWorkspaceDependencies: [], + }, }, - }); + ]); }); it('does not match paths outside of known workspaces', () => { - const workspaces = { - 'workspace-1': { - location: 'packages/workspace-1', - workspaceDependencies: ['workspace-2', 'workspace-3'], - mismatchedWorkspaceDependencies: [], - }, - 'workspace-2': { - location: 'packages/workspace-2', - workspaceDependencies: ['workspace-3'], - mismatchedWorkspaceDependencies: [], - }, - 'workspace-3': { - location: 'packages/workspace-3', - workspaceDependencies: [], - mismatchedWorkspaceDependencies: [], + const workspacesContent: WorkspaceContent = [ + new Map( + Object.entries({ + 'workspace-1': { + path: 'w1', + location: 'w1', + name: 'workspace-1', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + 'workspace-2': { + path: 'w2', + location: '/w2', + name: 'workspace-3', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + 'workspace-3': { + path: 'w3', + location: '/w3', + name: 'workspace-3', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + }), + ), + { + 'workspace-1': { + location: 'packages/workspace-1', + workspaceDependencies: ['workspace-2', 'workspace-3'], + mismatchedWorkspaceDependencies: [], + }, + 'workspace-2': { + location: 'packages/workspace-2', + workspaceDependencies: ['workspace-3'], + mismatchedWorkspaceDependencies: [], + }, + 'workspace-3': { + location: 'packages/workspace-3', + workspaceDependencies: [], + mismatchedWorkspaceDependencies: [], + }, }, - }; + ]; const listOfPackageManifests = [ '/my/path/packages/workspace-nope/package.json', ]; expect( - matchWorkspaces(listOfPackageManifests, '/my/path', workspaces), - ).toEqual({}); + matchWorkspaces(listOfPackageManifests, '/my/path', workspacesContent), + ).toEqual([new Map([]), {}]); }); it('works with a root workspace', () => { - const workspaces = { - 'workspace-root': { - location: '', - workspaceDependencies: [], - mismatchedWorkspaceDependencies: [], - }, - 'workspace-non-root': { - location: 'packages/workspace-non-root', - workspaceDependencies: [], - mismatchedWorkspaceDependencies: [], + const workspacesContent: WorkspaceContent = [ + new Map( + Object.entries({ + 'workspace-root': { + path: 'w1', + location: 'w1', + name: 'workspace-1', + version: '0.0.1', + workspace: true, + modular: { + type: 'root', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + 'workspace-non-root': { + path: 'workspace-non-root', + location: '/workspace-non-root', + name: 'workspace-non-root', + version: '0.0.1', + workspace: false, + modular: { + type: 'package', + }, + children: [], + parent: null, + dependencies: undefined, + rawPackageJson: {}, + }, + }), + ), + { + 'workspace-root': { + location: '', + workspaceDependencies: [], + mismatchedWorkspaceDependencies: [], + }, + 'workspace-non-root': { + location: 'packages/workspace-non-root', + workspaceDependencies: [], + mismatchedWorkspaceDependencies: [], + }, }, - }; + ]; const listOfPackageManifests = [ '/my/path/workspace-root/package.json', @@ -94,8 +259,8 @@ describe('matchWorkspaces', () => { matchWorkspaces( listOfPackageManifests, '/my/path/workspace-root', - workspaces, + workspacesContent, ), - ).toEqual(workspaces); + ).toEqual(workspacesContent); }); }); diff --git a/packages/modular-scripts/src/utils/getAllWorkspaces.ts b/packages/modular-scripts/src/utils/getAllWorkspaces.ts index 22fa52d20..4b49cf330 100644 --- a/packages/modular-scripts/src/utils/getAllWorkspaces.ts +++ b/packages/modular-scripts/src/utils/getAllWorkspaces.ts @@ -11,7 +11,10 @@ import type { ModularWorkspacePackage, } from '@modular-scripts/modular-types'; -type WorkspaceContent = [Map, WorkspaceMap]; +export type WorkspaceContent = [ + Map, + WorkspaceMap, +]; export interface PackageManagerInfo { getWorkspaceCommand: string; formatWorkspaceCommandOutput: (stdout: string) => WorkspaceMap; diff --git a/packages/modular-scripts/src/utils/getChangedWorkspaces.ts b/packages/modular-scripts/src/utils/getChangedWorkspaces.ts index 280781c2a..760be05a5 100644 --- a/packages/modular-scripts/src/utils/getChangedWorkspaces.ts +++ b/packages/modular-scripts/src/utils/getChangedWorkspaces.ts @@ -3,14 +3,14 @@ import pkgUp from 'pkg-up'; import { getDiffedFiles } from './gitActions'; import { getAllWorkspaces } from './getAllWorkspaces'; import getModularRoot from './getModularRoot'; -import { WorkspaceMap } from '@modular-scripts/modular-types'; +import type { WorkspaceContent } from './getAllWorkspaces'; -// Gets a list of changed files, then maps them to their workspace and returns a subset of WorkspaceMap +// Gets a list of changed files, then maps them to their workspace and returns a subset of WorkspaceContent export async function getChangedWorkspaces( targetBranch: string, -): Promise { +): Promise { const diffedFiles = getDiffedFiles(targetBranch); - const workspaces = await getAllWorkspaces(); + const workspaceContent = await getAllWorkspaces(); const modularRoot = getModularRoot(); // Resolve each of the changed files to their nearest package.json. The resulting list can contain duplicates and null holes @@ -18,31 +18,37 @@ export async function getChangedWorkspaces( diffedFiles.map((changedFile) => pkgUp({ cwd: path.dirname(changedFile) })), ); - return matchWorkspaces(packageManifestPaths, modularRoot, workspaces); + return matchWorkspaces(packageManifestPaths, modularRoot, workspaceContent); } -// Match workspace manifest paths to a subset of WorkspaceMap. This function works completely in memory and is test-friendly +// Match workspace manifest paths to a subset of WorkspaceContent. This function works completely in memory and is test-friendly export function matchWorkspaces( packagePaths: (string | null)[], root: string, - workspaces: WorkspaceMap, -): WorkspaceMap { + workspaceContent: WorkspaceContent, +): WorkspaceContent { + const [packages, workspaces] = workspaceContent; const workspaceEntries = Object.entries(workspaces); - const result: WorkspaceMap = {}; + const result: WorkspaceContent = [new Map([]), {}]; for (const packagePath of packagePaths) { + const [resultPackages, resultWorkspaces] = result; // Ignore holes if (!packagePath) continue; - // Get the package directory from the package.json path and make it relative to the root, for comparison with the original WorkspaceMap + // Get the package directory from the package.json path and make it relative to the root, for comparison with the original WorkspaceContent const packageDir = path.relative(root, path.dirname(packagePath)); - // Match the package directory to its entry WorkspaceMap, using pathEquality + // Match the package directory to its entry WorkspaceContent, using pathEquality const foundEntry = workspaceEntries.find(([_, { location }]) => pathEquality(location, packageDir), ); - // If found, insert the entry into the WorkspaceMap that we are building + // If found, insert the entries into the WorkspaceContent that we are building if (foundEntry) { const [foundWorkspaceName, foundWorkspace] = foundEntry; - result[foundWorkspaceName] = foundWorkspace; + resultWorkspaces[foundWorkspaceName] = foundWorkspace; + const foundPackage = packages.get(foundWorkspaceName); + if (foundPackage) { + resultPackages.set(foundWorkspaceName, foundPackage); + } } } return result;