1import chalk from 'chalk'; 2 3import { formatCommitHash } from '../Formatter'; 4import Git from '../Git'; 5import logger from '../Logger'; 6import { getListOfPackagesAsync } from '../Packages'; 7import { ActionOptions } from './types'; 8 9const { yellow } = chalk; 10 11async function safeGetMergeBaseAsync(ref: string): Promise<string | null> { 12 try { 13 return await Git.mergeBaseAsync(ref); 14 } catch (e) { 15 logger.error(` Cannot get merge base for reference: ${yellow(ref)}\n`, e.stack); 16 return null; 17 } 18} 19 20/** 21 * Resolves which packages should go through checks based on given options. 22 */ 23export default async function getPackagesToCheckAsync(options: ActionOptions) { 24 const { all, packageNames } = options; 25 26 const allPackages = (await getListOfPackagesAsync()).filter((pkg) => { 27 // If the package doesn't have build or test script, just skip it. 28 return pkg.scripts.build || pkg.scripts.test; 29 }); 30 31 if (all) { 32 return allPackages; 33 } 34 if (packageNames.length > 0) { 35 return allPackages.filter((pkg) => { 36 return packageNames.includes(pkg.packageName); 37 }); 38 } 39 40 const sinceRef = options.since ?? 'main'; 41 const mergeBase = await safeGetMergeBaseAsync(sinceRef); 42 43 if (!mergeBase) { 44 logger.warn( 45 ` Couldn't find merge base with ${yellow(sinceRef)}, falling back to all packages\n` 46 ); 47 return allPackages; 48 } 49 50 logger.info(` Using incremental checks since ${formatCommitHash(mergeBase)} commit\n`); 51 const changedFiles = await Git.logFilesAsync({ fromCommit: mergeBase }); 52 53 return allPackages.filter((pkg) => { 54 const pkgPath = pkg.path.replace(/([^\/])$/, '$1/'); 55 return changedFiles.some(({ path }) => path.startsWith(pkgPath)); 56 }); 57} 58