Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add caching for list of changed packages #569

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions change/beachball-1cc40d1b-98c5-48b9-8387-c6a7f1dbf6a1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Add caching of changed packages",
"packageName": "beachball",
"email": "[email protected]",
"dependentChangeType": "patch"
}
3 changes: 2 additions & 1 deletion src/__e2e__/multiMonorepo.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs-extra';
import path from 'path';
import { RepositoryFactory } from '../fixtures/repository';
import { getChangedPackages } from '../changefile/getChangedPackages';
import { getChangedPackages, resetChangedPackagesCache } from '../changefile/getChangedPackages';
import { writeChangeFiles } from '../changefile/writeChangeFiles';
import { git } from 'workspace-tools';
import { bump } from '../commands/bump';
Expand All @@ -14,6 +14,7 @@ describe('changed files', () => {
let repositoryFactory: RepositoryFactory | undefined;

afterEach(() => {
resetChangedPackagesCache();
if (repositoryFactory) {
repositoryFactory.cleanUp();
repositoryFactory = undefined;
Expand Down
62 changes: 39 additions & 23 deletions src/changefile/getChangedPackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import { getScopedPackages } from '../monorepo/getScopedPackages';
import { BeachballOptions } from '../types/BeachballOptions';
import { PackageInfos } from '../types/PackageInfo';

let cachedPackages: { [key: string]: ReadonlyArray<string> } = {};

function getCacheKey(options: BeachballOptions) {
return [options.path, options.branch, options.fetch].join('-');
}

/** Reset the cache for `getChangedPackages` */
export function resetChangedPackagesCache() {
cachedPackages = {};
}

/**
* Gets all the changed packages, regardless of the change files
*/
Expand All @@ -17,30 +28,28 @@ function getAllChangedPackages(options: BeachballOptions, packageInfos: PackageI
const scopedPackages = getScopedPackages(options, packageInfos);
const ignoredFiles = ['CHANGELOG.md', 'CHANGELOG.json'];
const packageRoots: { [pathName: string]: string } = {};
if (changes) {
// Discover package roots from modded files (ignores the CHANGELOG file because that's generated by beachball)
changes
.filter(name => !ignoredFiles.includes(path.basename(name)))
.forEach(moddedFile => {
const root = findPackageRoot(path.join(cwd, path.dirname(moddedFile)));

if (root && !packageRoots[root]) {
try {
const packageJson = fs.readJSONSync(path.join(root, 'package.json'));

if (!packageJson.private && (!packageJson.beachball || packageJson.beachball.shouldPublish !== false)) {
const packageName = packageJson.name;

if (scopedPackages.includes(packageName)) {
packageRoots[root] = packageName;
}
// Discover package roots from modded files (ignores the CHANGELOG file because that's generated by beachball)
changes
.filter(name => !ignoredFiles.includes(path.basename(name)))
.forEach(moddedFile => {
const root = findPackageRoot(path.join(cwd, path.dirname(moddedFile)));

if (root && !packageRoots[root]) {
try {
const packageJson = fs.readJSONSync(path.join(root, 'package.json'));

if (!packageJson.private && (!packageJson.beachball || packageJson.beachball.shouldPublish !== false)) {
const packageName = packageJson.name;

if (scopedPackages.includes(packageName)) {
packageRoots[root] = packageName;
}
} catch (e) {
// Ignore JSON errors
}
} catch (e) {
// Ignore JSON errors
}
});
}
}
});

return Object.values(packageRoots);
}
Expand All @@ -50,6 +59,11 @@ function getAllChangedPackages(options: BeachballOptions, packageInfos: PackageI
*/
export function getChangedPackages(options: BeachballOptions, packageInfos: PackageInfos) {
const { fetch, path: cwd, branch } = options;
const cacheKey = getCacheKey(options);

if (cachedPackages[cacheKey]) {
return cachedPackages[cacheKey];
}

const changePath = getChangePath(cwd);

Expand All @@ -59,14 +73,15 @@ export function getChangedPackages(options: BeachballOptions, packageInfos: Pack
fetchRemoteBranch(remote, remoteBranch, cwd);
}

const changedPackages = getAllChangedPackages(options, packageInfos);
let changedPackages = getAllChangedPackages(options, packageInfos);

const changeFilesResult = git(
['diff', '--name-only', '--relative', '--no-renames', '--diff-filter=A', `${branch}...`],
{ cwd }
);

if (!changePath || !fs.existsSync(changePath) || !changeFilesResult.success) {
cachedPackages[cacheKey] = changedPackages;
return changedPackages;
}

Expand Down Expand Up @@ -94,5 +109,6 @@ export function getChangedPackages(options: BeachballOptions, packageInfos: Pack
);
}

return changedPackages.filter(pkgName => !changeFilePackageSet.has(pkgName));
changedPackages = cachedPackages[cacheKey] = changedPackages.filter(pkgName => !changeFilePackageSet.has(pkgName));
return changedPackages;
}