diff --git a/.changeset/famous-tips-lie.md b/.changeset/famous-tips-lie.md new file mode 100644 index 000000000..e6f9069b8 --- /dev/null +++ b/.changeset/famous-tips-lie.md @@ -0,0 +1,8 @@ +--- +'@rnef/platform-apple-helpers': patch +'@rnef/platform-android': patch +'@rnef/config': patch +'@rnef/tools': patch +--- + +feat: refactor and expose remote cache provider diff --git a/packages/config/src/lib/schema.ts b/packages/config/src/lib/schema.ts index d0cd9201f..2869ee938 100644 --- a/packages/config/src/lib/schema.ts +++ b/packages/config/src/lib/schema.ts @@ -40,14 +40,18 @@ const ConfigTypeSchema = Joi.object({ plugins: Joi.array().items(Joi.function()).optional(), platforms: Joi.object().pattern(Joi.string(), Joi.function()).optional(), commands: Joi.array().items(CommandTypeSchema).optional(), - remoteCacheProvider: Joi.string().valid('github-actions', null).optional(), + remoteCacheProvider: Joi.string() + .valid('github-actions', null, Joi.function()) + .optional(), fingerprint: Joi.object({ extraSources: Joi.array().items(Joi.string()).default([]), ignorePaths: Joi.array().items(Joi.string()).default([]), - }).default({ - extraSources: [], - ignorePaths: [], - }).optional(), + }) + .default({ + extraSources: [], + ignorePaths: [], + }) + .optional(), }).unknown(false); export { ConfigTypeSchema }; diff --git a/packages/platform-android/src/lib/commands/runAndroid/fetchCachedBuild.ts b/packages/platform-android/src/lib/commands/runAndroid/fetchCachedBuild.ts deleted file mode 100644 index f515330f9..000000000 --- a/packages/platform-android/src/lib/commands/runAndroid/fetchCachedBuild.ts +++ /dev/null @@ -1,127 +0,0 @@ -import path from 'node:path'; -import type { LocalBuild, SupportedRemoteCacheProviders } from '@rnef/tools'; -import { - color, - createRemoteBuildCache, - findFilesWithPattern, - formatArtifactName, - logger, - nativeFingerprint, - queryLocalBuildCache, - spinner, -} from '@rnef/tools'; - -type FetchCachedBuildOptions = { - variant: string; - remoteCacheProvider: SupportedRemoteCacheProviders | undefined; - root: string; - fingerprintOptions: { - extraSources: string[]; - ignorePaths: string[]; - }; -}; - -export async function fetchCachedBuild({ - variant, - remoteCacheProvider, - root, - fingerprintOptions, -}: FetchCachedBuildOptions): Promise { - if (remoteCacheProvider === null) { - return null; - } - if (remoteCacheProvider === undefined) { - logger.warn(`No remote cache provider set. You won't be able to access reusable builds from e.g. GitHub Actions. -To configure it, set the "remoteCacheProvider" key in ${color.cyan( - 'rnef.config.mjs' - )} file: -{ - remoteCacheProvider: 'github-actions' -} -To disable this warning, set "remoteCacheProvider" to null. -Proceeding with local build.`); - return null; - } - const loader = spinner(); - loader.start('Looking for a local cached build'); - - const artifactName = await calculateArtifactName( - variant, - root, - fingerprintOptions - ); - - const localBuild = queryLocalBuildCache(artifactName, { findBinary }); - if (localBuild != null) { - loader.stop(`Found local cached build: ${color.cyan(localBuild.name)}`); - return localBuild; - } - - const remoteBuildCache = await createRemoteBuildCache(remoteCacheProvider); - if (!remoteBuildCache) { - loader.stop(`No supported remote provider set, skipping.`); - return null; - } - - loader.stop(`No local build cached. Checking ${remoteBuildCache.name}.`); - const repoDetails = await remoteBuildCache.detectRepoDetails(); - if (!repoDetails) { - return null; - } - - loader.start(`Looking for a cached build on ${remoteBuildCache.name}`); - const remoteBuild = await remoteBuildCache.query(artifactName); - if (!remoteBuild) { - loader.stop(`No cached build found for "${artifactName}".`); - return null; - } - - loader.message(`Downloading cached build from ${remoteBuildCache.name}`); - const fetchedBuild = await remoteBuildCache.download(remoteBuild, loader); - const binaryPath = findBinary(fetchedBuild.path); - if (!binaryPath) { - loader.stop(`No binary found in "${artifactName}".`); - return null; - } - - loader.stop( - `Downloaded cached build: ${color.cyan(path.relative(root, binaryPath))}.` - ); - - return { - name: fetchedBuild.name, - artifactPath: fetchedBuild.path, - binaryPath, - }; -} - -async function calculateArtifactName( - variant: string, - root: string, - fingerprintOptions: { extraSources: string[]; ignorePaths: string[] } -) { - const fingerprint = await nativeFingerprint(root, { - platform: 'android', - ...fingerprintOptions, - }); - - return formatArtifactName({ - platform: 'android', - build: variant, - hash: fingerprint.hash, - }); -} - -function findBinary(path: string): string | null { - const apks = findFilesWithPattern(path, /\.apk$/); - if (apks.length > 0) { - return apks[0]; - } - - const aabs = findFilesWithPattern(path, /\.aab$/); - if (aabs.length > 0) { - return aabs[0]; - } - - return null; -} diff --git a/packages/platform-android/src/lib/commands/runAndroid/runAndroid.ts b/packages/platform-android/src/lib/commands/runAndroid/runAndroid.ts index 888f1df42..110b29d14 100644 --- a/packages/platform-android/src/lib/commands/runAndroid/runAndroid.ts +++ b/packages/platform-android/src/lib/commands/runAndroid/runAndroid.ts @@ -6,6 +6,8 @@ import type { } from '@react-native-community/cli-types'; import type { SupportedRemoteCacheProviders } from '@rnef/tools'; import { + fetchCachedBuild, + formatArtifactName, intro, isInteractive, logger, @@ -18,7 +20,6 @@ import { options } from '../buildAndroid/buildAndroid.js'; import { runGradle } from '../runGradle.js'; import { toPascalCase } from '../toPascalCase.js'; import { getDevices } from './adb.js'; -import { fetchCachedBuild } from './fetchCachedBuild.js'; import type { DeviceData } from './listAndroidDevices.js'; import { listAndroidDevices } from './listAndroidDevices.js'; import { tryInstallAppOnDevice } from './tryInstallAppOnDevice.js'; @@ -59,12 +60,16 @@ export async function runAndroid( const tasks = args.tasks ?? [`${mainTaskType}${toPascalCase(args.variant)}`]; if (!args.binaryPath && args.remoteCache) { - const cachedBuild = await fetchCachedBuild({ - variant: args.variant, - remoteCacheProvider, + const artifactName = await formatArtifactName({ + platform: 'android', + traits: [args.variant], root: projectRoot, fingerprintOptions, }); + const cachedBuild = await fetchCachedBuild({ + artifactName, + remoteCacheProvider, + }); if (cachedBuild) { // @todo replace with a more generic way to pass binary path args.binaryPath = cachedBuild.binaryPath; diff --git a/packages/platform-apple-helpers/package.json b/packages/platform-apple-helpers/package.json index caef46fd1..2930e767e 100644 --- a/packages/platform-apple-helpers/package.json +++ b/packages/platform-apple-helpers/package.json @@ -21,7 +21,6 @@ "adm-zip": "^0.5.16", "fast-glob": "^3.3.2", "fast-xml-parser": "^4.5.0", - "tar": "^7.4.3", "tslib": "^2.3.0" }, "devDependencies": { diff --git a/packages/platform-apple-helpers/src/lib/commands/run/createRun.ts b/packages/platform-apple-helpers/src/lib/commands/run/createRun.ts index 8cdb4111f..6c16e3432 100644 --- a/packages/platform-apple-helpers/src/lib/commands/run/createRun.ts +++ b/packages/platform-apple-helpers/src/lib/commands/run/createRun.ts @@ -3,6 +3,8 @@ import path from 'node:path'; import type { SupportedRemoteCacheProviders } from '@rnef/tools'; import { color, + fetchCachedBuild, + formatArtifactName, isInteractive, logger, promptSelect, @@ -21,7 +23,6 @@ import { getSimulatorPlatformSDK, } from '../../utils/getPlatformInfo.js'; import { listDevicesAndSimulators } from '../../utils/listDevices.js'; -import { fetchCachedBuild } from './fetchCachedBuild.js'; import { matchingDevice } from './matchingDevice.js'; import { cacheRecentDevice, sortByRecentDevices } from './recentDevices.js'; import { runOnDevice } from './runOnDevice.js'; @@ -39,13 +40,16 @@ export const createRun = async ( fingerprintOptions: { extraSources: string[]; ignorePaths: string[] } ) => { if (!args.binaryPath && args.remoteCache) { - const cachedBuild = await fetchCachedBuild({ - configuration: args.configuration ?? 'Debug', - distribution: args.destination ?? 'simulator', - remoteCacheProvider, + const artifactName = await formatArtifactName({ + platform: 'ios', + traits: [args.destination ?? 'simulator', args.configuration ?? 'Debug'], root: projectRoot, fingerprintOptions, }); + const cachedBuild = await fetchCachedBuild({ + artifactName, + remoteCacheProvider, + }); if (cachedBuild) { // @todo replace with a more generic way to pass binary path args.binaryPath = cachedBuild.binaryPath; diff --git a/packages/platform-apple-helpers/src/lib/commands/run/fetchCachedBuild.ts b/packages/platform-apple-helpers/src/lib/commands/run/fetchCachedBuild.ts deleted file mode 100644 index 30ca35c05..000000000 --- a/packages/platform-apple-helpers/src/lib/commands/run/fetchCachedBuild.ts +++ /dev/null @@ -1,180 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import type { SupportedRemoteCacheProviders } from '@rnef/tools'; -import { - color, - createRemoteBuildCache, - findDirectoriesWithPattern, - findFilesWithPattern, - formatArtifactName, - type LocalBuild, - logger, - nativeFingerprint, - queryLocalBuildCache, - spinner, -} from '@rnef/tools'; -import * as tar from 'tar'; - -export type Distribution = 'simulator' | 'device'; - -type FetchCachedBuildOptions = { - distribution: Distribution; - configuration: string; - remoteCacheProvider: SupportedRemoteCacheProviders | undefined | null; - root: string; - fingerprintOptions: { - extraSources: string[]; - ignorePaths: string[]; - }; -}; - -export async function fetchCachedBuild({ - distribution, - configuration, - remoteCacheProvider, - root, - fingerprintOptions, -}: FetchCachedBuildOptions): Promise { - if (remoteCacheProvider === null) { - return null; - } - if (remoteCacheProvider === undefined) { - logger.warn(`No remote cache provider set. You won't be able to access reusable builds from e.g. GitHub Actions. -To configure it, set the "remoteCacheProvider" key in ${color.cyan( - 'rnef.config.mjs' - )} file: -{ - remoteCacheProvider: 'github-actions' -} -To disable this warning, set "remoteCacheProvider" to null. -Proceeding with local build.`); - return null; - } - const loader = spinner(); - loader.start('Looking for a local cached build'); - - const artifactName = await calculateArtifactName({ - distribution, - configuration, - root, - fingerprintOptions, - }); - - const localBuild = queryLocalBuildCache(artifactName, { - findBinary: (path) => findBinary(distribution, path), - }); - if (localBuild != null) { - loader.stop(`Found local cached build: ${color.cyan(localBuild.name)}`); - return localBuild; - } - - const remoteBuildCache = await createRemoteBuildCache(remoteCacheProvider); - if (!remoteBuildCache) { - loader.stop(`No remote cache provider found, skipping.`); - return null; - } - - loader.stop(`No local build cached. Checking ${remoteBuildCache.name}.`); - const repoDetails = await remoteBuildCache.detectRepoDetails(); - if (!repoDetails) { - return null; - } - - loader.start(`Looking for a cached build on ${remoteBuildCache.name}`); - const remoteBuild = await remoteBuildCache.query(artifactName); - if (!remoteBuild) { - loader.stop(`No cached build found for "${artifactName}".`); - return null; - } - - loader.message(`Downloading cached build from ${remoteBuildCache.name}`); - const fetchedBuild = await remoteBuildCache.download(remoteBuild, loader); - await extractArtifactTarballIfNeeded(fetchedBuild.path); - const binaryPath = findBinary(distribution, fetchedBuild.path); - if (!binaryPath) { - loader.stop(`No binary found in "${artifactName}".`); - return null; - } - - loader.stop( - `Downloaded cached build: ${color.cyan(path.relative(root, binaryPath))}.` - ); - - return { - name: fetchedBuild.name, - artifactPath: fetchedBuild.path, - binaryPath, - }; -} - -async function calculateArtifactName({ - distribution, - configuration, - root, - fingerprintOptions, -}: Omit) { - const fingerprint = await nativeFingerprint(root, { - platform: 'ios', - ...fingerprintOptions, - }); - - return formatArtifactName({ - platform: 'ios', - distribution, - build: configuration, - hash: fingerprint.hash, - }); -} - -function findBinary(distribution: Distribution, path: string): string | null { - return distribution === 'device' - ? findDeviceBinary(path) - : findSimulatorBinary(path); -} - -function findSimulatorBinary(path: string): string | null { - const apps = findDirectoriesWithPattern(path, /\.app$/); - if (apps.length === 0) { - return null; - } - - logger.debug( - `Found simulator binaries (*.app): ${apps.join( - ', ' - )}. Picking the first one: ${apps[0]}.` - ); - return apps[0]; -} - -function findDeviceBinary(path: string): string | null { - const ipas = findFilesWithPattern(path, /\.ipa$/); - if (ipas.length === 0) { - return null; - } - - logger.debug( - `Found device binaries (*.ipa): ${ipas.join( - ', ' - )}. Picking the first one: ${ipas[0]}.` - ); - return ipas[0]; -} - -async function extractArtifactTarballIfNeeded(artifactPath: string) { - const tarPath = path.join(artifactPath, 'app.tar.gz'); - - // If the tarball is not found, it means the artifact is already unpacked. - if (!fs.existsSync(tarPath)) { - return; - } - - // iOS simulator build artifact (*.app directory) is packed in .tar.gz file to - // preserve execute file permission. - // See: https://github.com/actions/upload-artifact?tab=readme-ov-file#permission-loss - await tar.extract({ - file: tarPath, - cwd: artifactPath, - gzip: true, - }); - fs.unlinkSync(tarPath); -} diff --git a/packages/tools/package.json b/packages/tools/package.json index 0e1deeb4a..08b017929 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -24,6 +24,7 @@ "nano-spawn": "^0.2.0", "picocolors": "^1.1.1", "string-argv": "^0.3.2", + "tar": "^7.4.3", "ts-regex-builder": "^1.8.2", "tslib": "^2.3.0" }, diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 231be48a1..6223c9598 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -19,3 +19,4 @@ export { isInteractive } from './lib/isInteractive.js'; export { spawn, SubprocessError } from './lib/spawn.js'; export { color } from './lib/color.js'; export { runHermes } from './lib/hermes.js'; +export { fetchCachedBuild } from './lib/build-cache/fetchCachedBuild.js'; diff --git a/packages/tools/src/lib/build-cache/common.ts b/packages/tools/src/lib/build-cache/common.ts index ba9fa4683..4f5baeb65 100644 --- a/packages/tools/src/lib/build-cache/common.ts +++ b/packages/tools/src/lib/build-cache/common.ts @@ -1,4 +1,6 @@ +import fs from 'node:fs'; import path from 'node:path'; +import { nativeFingerprint } from '../fingerprint/index.js'; import { getCacheRootPath } from '../project.js'; import type { spinner } from '../prompts.js'; @@ -16,29 +18,21 @@ export type LocalArtifact = { path: string; }; -type RepoDetails = { - url: string; - owner: string; - repository: string; -}; - -export type RemoteBuildCache = { +export interface RemoteBuildCache { name: string; - repoDetails: RepoDetails | null; - detectRepoDetails(): Promise; - query(artifactName: string): Promise; - download( - artifact: RemoteArtifact, - loader: ReturnType - ): Promise; -}; - -type FormatArtifactNameParams = { - platform: string; - distribution?: string; - build: string; - hash: string; -}; + query({ + artifactName, + }: { + artifactName: string; + }): Promise; + download({ + artifact, + loader, + }: { + artifact: RemoteArtifact; + loader: ReturnType; + }): Promise; +} /** * Used formats: @@ -46,17 +40,39 @@ type FormatArtifactNameParams = { * - rnef-ios-simulator-debug-1234567890 * - rnef-ios-device-debug-1234567890 */ -export function formatArtifactName({ +export async function formatArtifactName({ platform, - distribution, - build, - hash, -}: FormatArtifactNameParams): string { - return `rnef-${platform}${ - distribution ? `-${distribution}` : '' - }-${build}-${hash}`; + traits, + root, + fingerprintOptions, +}: { + platform: 'ios' | 'android'; + traits: string[]; + root: string; + fingerprintOptions: { extraSources: string[]; ignorePaths: string[] }; +}): Promise { + const { hash } = await nativeFingerprint(root, { + platform, + ...fingerprintOptions, + }); + return `rnef-${platform}-${traits.join('-')}-${hash}`; } export function getLocalArtifactPath(artifactName: string) { return path.join(getCacheRootPath(), BUILD_CACHE_DIR, artifactName); } + +export function getLocalBinaryPath(artifactPath: string) { + let binaryPath: string | null = null; + const files = fs.readdirSync(artifactPath); + + // assume there is only one binary in the artifact + for (const file of files) { + if (file) { + binaryPath = path.join(artifactPath, file); + } + break; + } + + return binaryPath; +} diff --git a/packages/tools/src/lib/build-cache/fetchCachedBuild.ts b/packages/tools/src/lib/build-cache/fetchCachedBuild.ts new file mode 100644 index 000000000..8e1da0c33 --- /dev/null +++ b/packages/tools/src/lib/build-cache/fetchCachedBuild.ts @@ -0,0 +1,92 @@ +import path from 'node:path'; +import { color } from '../color.js'; +import logger from '../logger.js'; +import { getProjectRoot } from '../project.js'; +import { spinner } from '../prompts.js'; +import { + getLocalBinaryPath, + type RemoteBuildCache, + type SupportedRemoteCacheProviders, +} from './common.js'; +import type { LocalBuild } from './localBuildCache.js'; +import { queryLocalBuildCache } from './localBuildCache.js'; +import { createRemoteBuildCache } from './remoteBuildCache.js'; + +export type Distribution = 'simulator' | 'device'; + +type FetchCachedBuildOptions = { + artifactName: string; + remoteCacheProvider: + | SupportedRemoteCacheProviders + | undefined + | null + | { new (): RemoteBuildCache }; +}; + +export async function fetchCachedBuild({ + artifactName, + remoteCacheProvider, +}: FetchCachedBuildOptions): Promise { + if (remoteCacheProvider === null) { + return null; + } + if (remoteCacheProvider === undefined) { + logger.warn(`No remote cache provider set. You won't be able to access reusable builds from e.g. GitHub Actions. +To configure it, set the "remoteCacheProvider" key in ${color.cyan( + 'rnef.config.mjs' + )} file: +{ + remoteCacheProvider: 'github-actions' +} +To disable this warning, set "remoteCacheProvider" to null. +Proceeding with local build.`); + return null; + } + const loader = spinner(); + loader.start('Looking for a local cached build'); + + const root = getProjectRoot(); + + const localBuild = queryLocalBuildCache(artifactName); + if (localBuild != null) { + loader.stop(`Found local cached build: ${color.cyan(localBuild.name)}`); + return localBuild; + } + + const remoteBuildCache = await createRemoteBuildCache(remoteCacheProvider); + if (!remoteBuildCache) { + loader.stop(`No remote cache provider found, skipping.`); + return null; + } + + loader.stop(`No local build cached. Checking ${remoteBuildCache.name}.`); + + const remoteBuild = await remoteBuildCache.query({ artifactName }); + if (!remoteBuild) { + loader.start(''); + loader.stop(`No cached build found for "${artifactName}".`); + return null; + } + + loader.start(`Downloading cached build from ${remoteBuildCache.name}`); + const fetchedBuild = await remoteBuildCache.download({ + artifact: remoteBuild, + loader, + }); + + const binaryPath = getLocalBinaryPath(fetchedBuild.path); + if (!binaryPath) { + loader.stop(`No binary found for "${artifactName}".`); + return null; + } + + loader.stop( + `Downloaded cached build: ${color.cyan(path.relative(root, binaryPath))}.` + ); + + return { + name: fetchedBuild.name, + artifactPath: fetchedBuild.path, + binaryPath, + }; +} diff --git a/packages/tools/src/lib/build-cache/github/GitHubBuildCache.ts b/packages/tools/src/lib/build-cache/github/GitHubBuildCache.ts index a65202fd1..26806249d 100644 --- a/packages/tools/src/lib/build-cache/github/GitHubBuildCache.ts +++ b/packages/tools/src/lib/build-cache/github/GitHubBuildCache.ts @@ -1,3 +1,6 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import * as tar from 'tar'; import { color } from '../../color.js'; import { getGitRemote } from '../../git.js'; import logger from '../../logger.js'; @@ -42,15 +45,24 @@ Include "repo", "workflow", and "read:org" permissions.` return this.repoDetails; } - async query(artifactName: string): Promise { + async query({ + artifactName, + }: { + artifactName: string; + }): Promise { + const repoDetails = await this.detectRepoDetails(); if (!getGitHubToken()) { logger.warn(`No GitHub Personal Access Token found.`); return null; } + if (!repoDetails) { + return null; + } + const artifacts = await fetchGitHubArtifactsByName( artifactName, - this.repoDetails + repoDetails ); if (artifacts.length === 0) { return null; @@ -62,10 +74,13 @@ Include "repo", "workflow", and "read:org" permissions.` }; } - async download( - artifact: RemoteArtifact, - loader: ReturnType - ): Promise { + async download({ + artifact, + loader, + }: { + artifact: RemoteArtifact; + loader: ReturnType; + }): Promise { const artifactPath = getLocalArtifactPath(artifact.name); await downloadGitHubArtifact( artifact.downloadUrl, @@ -73,10 +88,29 @@ Include "repo", "workflow", and "read:org" permissions.` this.name, loader ); - + await extractArtifactTarballIfNeeded(artifactPath); return { name: artifact.name, path: artifactPath, }; } } + +async function extractArtifactTarballIfNeeded(artifactPath: string) { + const tarPath = path.join(artifactPath, 'app.tar.gz'); + + // If the tarball is not found, it means the artifact is already unpacked. + if (!fs.existsSync(tarPath)) { + return; + } + + // iOS simulator build artifact (*.app directory) is packed in .tar.gz file to + // preserve execute file permission. + // See: https://github.com/actions/upload-artifact?tab=readme-ov-file#permission-loss + await tar.extract({ + file: tarPath, + cwd: artifactPath, + gzip: true, + }); + fs.unlinkSync(tarPath); +} diff --git a/packages/tools/src/lib/build-cache/localBuildCache.ts b/packages/tools/src/lib/build-cache/localBuildCache.ts index 9101e8a75..d6ed7fd76 100644 --- a/packages/tools/src/lib/build-cache/localBuildCache.ts +++ b/packages/tools/src/lib/build-cache/localBuildCache.ts @@ -1,9 +1,5 @@ import * as fs from 'node:fs'; -import { getLocalArtifactPath } from './common.js'; - -export type LocalBuildCacheConfig = { - findBinary: (path: string) => string | null; -}; +import { getLocalArtifactPath, getLocalBinaryPath } from './common.js'; export type LocalBuild = { name: string; @@ -11,20 +7,15 @@ export type LocalBuild = { binaryPath: string; }; -export function queryLocalBuildCache( - artifactName: string, - { findBinary }: LocalBuildCacheConfig -): LocalBuild | null { +export function queryLocalBuildCache(artifactName: string): LocalBuild | null { const artifactPath = getLocalArtifactPath(artifactName); if (!fs.statSync(artifactPath, { throwIfNoEntry: false })?.isDirectory()) { return null; } - - const binaryPath = findBinary(artifactPath); + const binaryPath = getLocalBinaryPath(artifactPath); if (binaryPath == null || !fs.existsSync(binaryPath)) { return null; } - return { name: artifactName, artifactPath, diff --git a/packages/tools/src/lib/build-cache/remoteBuildCache.ts b/packages/tools/src/lib/build-cache/remoteBuildCache.ts index 6d45af68d..a1abe7b7d 100644 --- a/packages/tools/src/lib/build-cache/remoteBuildCache.ts +++ b/packages/tools/src/lib/build-cache/remoteBuildCache.ts @@ -1,12 +1,16 @@ import type { RemoteBuildCache } from './common.js'; export async function createRemoteBuildCache( - remoteCacheProvider: 'github-actions' | null + remoteCacheProvider: 'github-actions' | null | { new (): RemoteBuildCache } ): Promise { if (remoteCacheProvider === 'github-actions') { const { GitHubBuildCache } = await import('./github/GitHubBuildCache.js'); return new GitHubBuildCache(); } + if (remoteCacheProvider && typeof remoteCacheProvider !== 'string') { + return new remoteCacheProvider(); + } + return null; } diff --git a/packages/tools/src/lib/path.ts b/packages/tools/src/lib/path.ts index d326b4151..e870ec9e8 100644 --- a/packages/tools/src/lib/path.ts +++ b/packages/tools/src/lib/path.ts @@ -25,21 +25,6 @@ export function resolveFilenameUp(path: string, filename: string) { return resolveFilenameUp(parentDir, filename); } -export function findFilesWithPattern(path: string, pattern: RegExp) { - const files = fs.readdirSync(path); - const result: string[] = []; - for (const file of files) { - const filePath = nodePath.join(path, file); - const stat = fs.statSync(filePath); - if (stat.isFile() && file.match(pattern)) { - result.push(filePath); - } else if (stat.isDirectory()) { - result.push(...findFilesWithPattern(filePath, pattern)); - } - } - return result; -} - export function findDirectoriesWithPattern(path: string, pattern: RegExp) { const files = fs.readdirSync(path); const result: string[] = []; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88b236113..c16c93409 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -229,9 +229,6 @@ importers: fast-xml-parser: specifier: ^4.5.0 version: 4.5.1 - tar: - specifier: ^7.4.3 - version: 7.4.3 tslib: specifier: ^2.3.0 version: 2.8.1 @@ -403,6 +400,9 @@ importers: string-argv: specifier: ^0.3.2 version: 0.3.2 + tar: + specifier: ^7.4.3 + version: 7.4.3 ts-regex-builder: specifier: ^1.8.2 version: 1.8.2