Skip to content

Commit

Permalink
Add --all option for change
Browse files Browse the repository at this point in the history
  • Loading branch information
ecraig12345 committed Jul 11, 2023
1 parent 4988272 commit 7d73fda
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 21 deletions.
7 changes: 7 additions & 0 deletions change/beachball-9bdf704a-61ed-4b77-8dfa-26bc583976fa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add --all option for `change` command",
"packageName": "beachball",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
9 changes: 9 additions & 0 deletions src/__e2e__/getChangedPackages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,13 @@ describe('getChangedPackages', () => {
expect(changedPackagesB).toStrictEqual([]);
expect(changedPackagesRoot).toStrictEqual(['@workspace-a/foo']);
});

it('returns all packages with --all option', () => {
repositoryFactory = new RepositoryFactory('monorepo');
const repo = repositoryFactory.cloneRepository();
const options = { all: true, fetch: false, path: repo.rootPath, branch: defaultBranchName } as BeachballOptions;
const packageInfos = getPackageInfos(repo.rootPath);

expect(getChangedPackages(options, packageInfos).sort()).toStrictEqual(['a', 'b', 'bar', 'baz', 'foo']);
});
});
56 changes: 40 additions & 16 deletions src/changefile/getChangedPackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,49 @@ function getMatchingPackageInfo(
return undefined;
}

/** Determines whether the package is publishable based on private flags and scopedPackages */
function isPackagePublishable(
packageInfo: PackageInfo | undefined,
scopedPackages: string[]
): { result: boolean; reason: string } {
const reason = !packageInfo
? 'no corresponding package found'
: packageInfo.private
? `${packageInfo.name} is private`
: packageInfo.combinedOptions.shouldPublish === false
? `${packageInfo.name} has beachball.shouldPublish=false`
: !scopedPackages.includes(packageInfo.name)
? `${packageInfo.name} is out of scope`
: ''; // not ignored

return { result: !reason, reason };
}

/**
* Gets all the changed package names, regardless of the change files
* Gets all the changed package names, regardless of the change files.
* If `options.all` is set, returns all the packages in scope, regardless of whether they've changed.
*/
function getAllChangedPackages(options: BeachballOptions, packageInfos: PackageInfos): string[] {
const { branch, path: cwd, verbose } = options;
const { branch, path: cwd, verbose, all } = options;

const verboseLog = (msg: string) => verbose && console.log(msg);
const logIgnored = (file: string, reason: string) => verboseLog(` - ~~${file}~~ (${reason})`);
const logIncluded = (file: string) => verboseLog(` - ${file}`);

const scopedPackages = getScopedPackages(options, packageInfos);

// If --all is set, return all the packages in scope rather than looking at which files changed
if (all) {
verboseLog('--all option was provided, so including all packages that are in scope (regardless of changes)');
return Object.values(packageInfos)
.filter(pkg => {
const { result, reason } = isPackagePublishable(pkg, scopedPackages);
verboseLog(result ? ` - ${pkg.name}` : ` - ~~${pkg.name}~~ (${reason.replace(`${pkg.name} `, '')})`);
return result;
})
.map(pkg => pkg.name);
}

const changes = [...(getChanges(branch, cwd) || []), ...(getStagedChanges(cwd) || [])];
verboseLog(`Found ${count(changes.length, 'changed file')} in branch "${branch}" (before filtering)`);

Expand All @@ -66,26 +99,17 @@ function getAllChangedPackages(options: BeachballOptions, packageInfos: PackageI
// and whether that package is in scope and not private
const includedPackages = new Set<string>();
let fileCount = 0;
const scopedPackages = getScopedPackages(options, packageInfos);
const packageInfosByPath: { [packageAbsNormalizedPath: string]: PackageInfo } = {};
for (const info of Object.values(packageInfos)) {
packageInfosByPath[path.normalize(path.dirname(info.packageJsonPath))] = info;
}
for (const moddedFile of nonIgnoredChanges) {
const packageInfo = getMatchingPackageInfo(moddedFile, cwd, packageInfosByPath);

const omitReason = !packageInfo
? 'no corresponding package found'
: packageInfo.private
? `${packageInfo.name} is private`
: packageInfo.combinedOptions.shouldPublish === false
? `${packageInfo.name} has beachball.shouldPublish=false`
: !scopedPackages.includes(packageInfo.name)
? `${packageInfo.name} is out of scope`
: ''; // not ignored

if (omitReason) {
logIgnored(moddedFile, omitReason);
const { result, reason } = isPackagePublishable(packageInfo, scopedPackages);

if (!result) {
logIgnored(moddedFile, reason);
} else {
includedPackages.add(packageInfo!.name);
fileCount++;
Expand All @@ -101,7 +125,7 @@ function getAllChangedPackages(options: BeachballOptions, packageInfos: PackageI
}

/**
* Gets all the changed packages, accounting for change files
* Gets all the changed packages which do not already have a change file
*/
export function getChangedPackages(options: BeachballOptions, packageInfos: PackageInfos): string[] {
const { path: cwd, branch } = options;
Expand Down
3 changes: 1 addition & 2 deletions src/commands/change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { getChangedPackages } from '../changefile/getChangedPackages';
import { getPackageGroups } from '../monorepo/getPackageGroups';

export async function change(options: BeachballOptions): Promise<void> {
const { branch, path: cwd } = options;
const { package: specificPackage } = options;
const { branch, path: cwd, package: specificPackage } = options;

const packageInfos = getPackageInfos(cwd);
const packageGroups = getPackageGroups(packageInfos, cwd, options.groups);
Expand Down
9 changes: 6 additions & 3 deletions src/packageManager/listPackageVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,19 @@ export async function listPackageVersionsByTag(
packageInfos: PackageInfo[],
tag: string | undefined,
options: NpmOptions
): Promise<{ [pkg: string]: string | undefined }> {
): Promise<{ [pkg: string]: string }> {
const limit = pLimit(NPM_CONCURRENCY);
const versions: { [pkg: string]: string | undefined } = {};
const versions: { [pkg: string]: string } = {};

await Promise.all(
packageInfos.map(pkg =>
limit(async () => {
const info = await getNpmPackageInfo(pkg.name, options);
const npmTag = tag || pkg.combinedOptions.tag || pkg.combinedOptions.defaultNpmTag;
versions[pkg.name] = (npmTag && info['dist-tags']?.[npmTag]) || undefined;
const version = npmTag && info['dist-tags']?.[npmTag];
if (version) {
versions[pkg.name] = version;
}
})
)
);
Expand Down

0 comments on commit 7d73fda

Please sign in to comment.