Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
filip131311 committed Jan 17, 2025
1 parent a081b34 commit 9317a59
Show file tree
Hide file tree
Showing 26 changed files with 690 additions and 354 deletions.
25 changes: 15 additions & 10 deletions packages/vscode-extension/src/builders/BuildCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from "path";
import fs from "fs";
import { createFingerprintAsync } from "@expo/fingerprint";
import { Logger } from "../Logger";
import { extensionContext, getAppRootFolder } from "../utilities/extensionContext";
import { AppRootFolder, extensionContext } from "../utilities/extensionContext";
import { DevicePlatform } from "../common/DeviceManager";
import { IOSBuildResult } from "./buildIOS";
import { AndroidBuildResult } from "./buildAndroid";
Expand Down Expand Up @@ -37,12 +37,15 @@ function makeCacheKey(platform: DevicePlatform, appRoot: string) {
}

export class BuildCache {
private readonly cacheKey: string;

constructor(private readonly platform: DevicePlatform, private readonly appRoot: string) {
this.cacheKey = makeCacheKey(platform, appRoot);
private get cacheKey() {
return makeCacheKey(this.platform, this.appRootFolder.getAppRoot());
}

constructor(
private readonly platform: DevicePlatform,
private readonly appRootFolder: AppRootFolder
) {}

/**
* Passed fingerprint should be calculated at the time build is started.
*/
Expand Down Expand Up @@ -112,7 +115,7 @@ export class BuildCache {
return customFingerprint;
}

const fingerprint = await createFingerprintAsync(getAppRootFolder(), {
const fingerprint = await createFingerprintAsync(this.appRootFolder.getAppRoot(), {
ignorePaths: IGNORE_PATHS,
});
Logger.debug("App folder fingerprint", fingerprint.hash);
Expand All @@ -134,7 +137,11 @@ export class BuildCache {
}

Logger.debug(`Using custom fingerprint script '${fingerprintCommand}'`);
const fingerprint = await runfingerprintCommand(fingerprintCommand, env);
const fingerprint = await runfingerprintCommand(
fingerprintCommand,
env,
this.appRootFolder.getAppRoot()
);

if (!fingerprint) {
throw new Error("Failed to generate application fingerprint using custom script.");
Expand All @@ -153,10 +160,8 @@ async function getAppHash(appPath: string) {
return (await calculateMD5(appPath)).digest("hex");
}

export async function migrateOldBuildCachesToNewStorage() {
export async function migrateOldBuildCachesToNewStorage(appRoot: string) {
try {
const appRoot = getAppRootFolder();

for (const platform of [DevicePlatform.Android, DevicePlatform.IOS]) {
const oldKey =
platform === DevicePlatform.Android ? ANDROID_BUILD_CACHE_KEY : IOS_BUILD_CACHE_KEY;
Expand Down
8 changes: 4 additions & 4 deletions packages/vscode-extension/src/builders/BuildManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { BuildCache } from "./BuildCache";
import { AndroidBuildResult, buildAndroid } from "./buildAndroid";
import { IOSBuildResult, buildIos } from "./buildIOS";
import { DeviceInfo, DevicePlatform } from "../common/DeviceManager";
import { getAppRootFolder } from "../utilities/extensionContext";
import { DependencyManager } from "../dependency/DependencyManager";
import { CancelToken } from "./cancelToken";
import { getTelemetryReporter } from "../utilities/telemetry";
Expand All @@ -16,6 +15,7 @@ export interface DisposableBuild<R> extends Disposable {
}

type BuildOptions = {
appRoot: string;
clean: boolean;
progressListener: (newProgress: number) => void;
onSuccess: () => void;
Expand Down Expand Up @@ -47,7 +47,7 @@ export class BuildManager {
}

public startBuild(deviceInfo: DeviceInfo, options: BuildOptions): DisposableBuild<BuildResult> {
const { clean: forceCleanBuild, progressListener, onSuccess } = options;
const { clean: forceCleanBuild, progressListener, onSuccess, appRoot } = options;
const { platform } = deviceInfo;

getTelemetryReporter().sendTelemetryEvent("build:requested", {
Expand Down Expand Up @@ -95,7 +95,7 @@ export class BuildManager {
});
this.buildOutputChannel.clear();
buildResult = await buildAndroid(
getAppRootFolder(),
appRoot,
forceCleanBuild,
cancelToken,
this.buildOutputChannel,
Expand Down Expand Up @@ -128,7 +128,7 @@ export class BuildManager {
}
};
buildResult = await buildIos(
getAppRootFolder(),
appRoot,
forceCleanBuild,
cancelToken,
this.buildOutputChannel,
Expand Down
17 changes: 9 additions & 8 deletions packages/vscode-extension/src/builders/buildAndroid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function makeBuildTaskName(productFlavor: string, buildType: string) {
}

export async function buildAndroid(
appRootFolder: string,
appRoot: string,
forceCleanBuild: boolean,
cancelToken: CancelToken,
outputChannel: OutputChannel,
Expand All @@ -97,7 +97,8 @@ export async function buildAndroid(
cancelToken,
customBuild.android.buildCommand,
env,
DevicePlatform.Android
DevicePlatform.Android,
appRoot
);
if (!apkPath) {
throw new Error("Failed to build Android app using custom script.");
Expand All @@ -114,7 +115,7 @@ export async function buildAndroid(
getTelemetryReporter().sendTelemetryEvent("build:eas-build-requested", {
platform: DevicePlatform.Android,
});
const apkPath = await fetchEasBuild(cancelToken, eas.android, DevicePlatform.Android);
const apkPath = await fetchEasBuild(cancelToken, eas.android, DevicePlatform.Android, appRoot);
if (!apkPath) {
throw new Error("Failed to build Android app using EAS build.");
}
Expand All @@ -126,11 +127,11 @@ export async function buildAndroid(
};
}

if (await isExpoGoProject()) {
if (await isExpoGoProject(appRoot)) {
getTelemetryReporter().sendTelemetryEvent("build:expo-go-requested", {
platform: DevicePlatform.Android,
});
const apkPath = await downloadExpoGo(DevicePlatform.Android, cancelToken);
const apkPath = await downloadExpoGo(DevicePlatform.Android, cancelToken, appRoot);
return { apkPath, packageName: EXPO_GO_PACKAGE_NAME, platform: DevicePlatform.Android };
}

Expand All @@ -140,7 +141,7 @@ export async function buildAndroid(
);
}

const androidSourceDir = getAndroidSourceDir(appRootFolder);
const androidSourceDir = getAndroidSourceDir(appRoot);
const productFlavor = android?.productFlavor || "";
const buildType = android?.buildType || "debug";
const gradleArgs = [
Expand All @@ -158,7 +159,7 @@ export async function buildAndroid(
),
];
// configureReactNativeOverrides init script is only necessary for RN versions older then 0.74.0 see comments in configureReactNativeOverrides.gradle for more details
if (semver.lt(getReactNativeVersion(), "0.74.0")) {
if (semver.lt(getReactNativeVersion(appRoot), "0.74.0")) {
gradleArgs.push(
"--init-script", // configureReactNativeOverrides init script is used to patch React Android project, see comments in configureReactNativeOverrides.gradle for more details
path.join(
Expand Down Expand Up @@ -186,6 +187,6 @@ export async function buildAndroid(

await buildProcess;
Logger.debug("Android build successful");
const apkInfo = await getAndroidBuildPaths(appRootFolder, cancelToken, productFlavor, buildType);
const apkInfo = await getAndroidBuildPaths(appRoot, cancelToken, productFlavor, buildType);
return { ...apkInfo, platform: DevicePlatform.Android };
}
15 changes: 8 additions & 7 deletions packages/vscode-extension/src/builders/buildIOS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function buildProject(
}

export async function buildIos(
appRootFolder: string,
appRoot: string,
forceCleanBuild: boolean,
cancelToken: CancelToken,
outputChannel: OutputChannel,
Expand All @@ -97,7 +97,8 @@ export async function buildIos(
cancelToken,
customBuild.ios.buildCommand,
env,
DevicePlatform.IOS
DevicePlatform.IOS,
appRoot
);
if (!appPath) {
throw new Error("Failed to build iOS app using custom script.");
Expand All @@ -114,7 +115,7 @@ export async function buildIos(
getTelemetryReporter().sendTelemetryEvent("build:eas-build-requested", {
platform: DevicePlatform.IOS,
});
const appPath = await fetchEasBuild(cancelToken, eas.ios, DevicePlatform.IOS);
const appPath = await fetchEasBuild(cancelToken, eas.ios, DevicePlatform.IOS, appRoot);
if (!appPath) {
throw new Error("Failed to build iOS app using EAS build.");
}
Expand All @@ -126,11 +127,11 @@ export async function buildIos(
};
}

if (await isExpoGoProject()) {
if (await isExpoGoProject(appRoot)) {
getTelemetryReporter().sendTelemetryEvent("build:expo-go-requested", {
platform: DevicePlatform.IOS,
});
const appPath = await downloadExpoGo(DevicePlatform.IOS, cancelToken);
const appPath = await downloadExpoGo(DevicePlatform.IOS, cancelToken, appRoot);
return { appPath, bundleID: EXPO_GO_BUNDLE_ID, platform: DevicePlatform.IOS };
}

Expand All @@ -140,11 +141,11 @@ export async function buildIos(
);
}

const sourceDir = getIosSourceDir(appRootFolder);
const sourceDir = getIosSourceDir(appRoot);

await installPodsIfNeeded();

const xcodeProject = await findXcodeProject(appRootFolder);
const xcodeProject = await findXcodeProject(appRoot);

if (!xcodeProject) {
throw new Error(`Could not find Xcode project files in "${sourceDir}" folder`);
Expand Down
19 changes: 12 additions & 7 deletions packages/vscode-extension/src/builders/customBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { mkdtemp } from "fs/promises";
import { Logger } from "../Logger";
import { command, lineReader } from "../utilities/subprocess";
import { CancelToken } from "./cancelToken";
import { getAppRootFolder } from "../utilities/extensionContext";
import { extractTarApp, isApkFile, isAppFile } from "./utils";
import { DevicePlatform } from "../common/DeviceManager";

Expand All @@ -18,9 +17,10 @@ export async function runExternalBuild(
cancelToken: CancelToken,
buildCommand: string,
env: Env,
platform: DevicePlatform
platform: DevicePlatform,
appRoot: string
) {
const output = await runExternalScript(buildCommand, env, cancelToken);
const output = await runExternalScript(buildCommand, env, appRoot, cancelToken);

if (!output) {
return undefined;
Expand Down Expand Up @@ -64,16 +64,21 @@ export async function runExternalBuild(
return binaryPath;
}

export async function runfingerprintCommand(externalCommand: string, env: Env) {
const output = await runExternalScript(externalCommand, env);
export async function runfingerprintCommand(externalCommand: string, env: Env, appRoot: string) {
const output = await runExternalScript(externalCommand, env, appRoot);
if (!output) {
return undefined;
}
return output.lastLine;
}

async function runExternalScript(externalCommand: string, env: Env, cancelToken?: CancelToken) {
let process = command(externalCommand, { cwd: getAppRootFolder(), env });
async function runExternalScript(
externalCommand: string,
env: Env,
appRoot: string,
cancelToken?: CancelToken
) {
let process = command(externalCommand, { cwd: appRoot, env });
process = cancelToken ? cancelToken.adapt(process) : process;
Logger.info(`Running external script: ${externalCommand}`);

Expand Down
11 changes: 6 additions & 5 deletions packages/vscode-extension/src/builders/eas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import { extractTarApp } from "./utils";
export async function fetchEasBuild(
cancelToken: CancelToken,
config: EasConfig,
platform: DevicePlatform
platform: DevicePlatform,
appRoot: string
): Promise<string | undefined> {
const build = await fetchBuild(config, platform);
const build = await fetchBuild(config, platform, appRoot);
if (!build) {
return undefined;
}
Expand All @@ -30,9 +31,9 @@ export async function fetchEasBuild(
return easBinaryPath;
}

async function fetchBuild(config: EasConfig, platform: DevicePlatform) {
async function fetchBuild(config: EasConfig, platform: DevicePlatform, appRoot: string) {
if (config.buildUUID) {
const build = await viewEasBuild(config.buildUUID, platform);
const build = await viewEasBuild(config.buildUUID, platform, appRoot);
if (!build) {
Logger.error(
`Failed to find EAS build artifact with ID ${config.buildUUID} for platform ${platform}.`
Expand All @@ -48,7 +49,7 @@ async function fetchBuild(config: EasConfig, platform: DevicePlatform) {
return build;
}

const builds = await listEasBuilds(platform, config.profile);
const builds = await listEasBuilds(platform, config.profile, appRoot);
if (!builds || builds.length === 0) {
Logger.error(
`Failed to find any EAS build artifacts for ${platform} with ${config.profile} profile. If you're building iOS app, make sure you set '"ios.simulator": true' option in eas.json.`
Expand Down
9 changes: 4 additions & 5 deletions packages/vscode-extension/src/builders/easCommand.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { DevicePlatform } from "../common/DeviceManager";
import { getAppRootFolder } from "../utilities/extensionContext";
import { exec } from "../utilities/subprocess";

type UnixTimestamp = number;
Expand Down Expand Up @@ -53,7 +52,7 @@ type EASBuildJson = {
isForIosSimulator: false;
};

export async function listEasBuilds(platform: DevicePlatform, profile: string) {
export async function listEasBuilds(platform: DevicePlatform, profile: string, appRoot: string) {
const platformMapping = { [DevicePlatform.Android]: "android", [DevicePlatform.IOS]: "ios" };

const { stdout } = await exec(
Expand All @@ -67,14 +66,14 @@ export async function listEasBuilds(platform: DevicePlatform, profile: string) {
"--profile",
profile,
],
{ cwd: getAppRootFolder() }
{ cwd: appRoot }
);
return parseEasBuildOutput(stdout, platform);
}

export async function viewEasBuild(buildUUID: UUID, platform: DevicePlatform) {
export async function viewEasBuild(buildUUID: UUID, platform: DevicePlatform, appRoot: string) {
const { stdout } = await exec("eas", ["build:view", buildUUID, "--json"], {
cwd: getAppRootFolder(),
cwd: appRoot,
});
return parseEasBuildOutput(stdout, platform)?.at(0);
}
Expand Down
15 changes: 9 additions & 6 deletions packages/vscode-extension/src/builders/expoGo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from "path";
import http from "http";
import fs from "fs";
import { extensionContext, getAppRootFolder } from "../utilities/extensionContext";
import { extensionContext } from "../utilities/extensionContext";
import { exec } from "../utilities/subprocess";
import { DevicePlatform } from "../common/DeviceManager";
import { CancelToken } from "./cancelToken";
Expand All @@ -15,7 +15,7 @@ function fileExists(filePath: string, ...additionalPaths: string[]) {
return fs.existsSync(path.join(filePath, ...additionalPaths));
}

export async function isExpoGoProject(): Promise<boolean> {
export async function isExpoGoProject(appRoot: string): Promise<boolean> {
// There is no straightforward way to tell apart different react native project
// setups. i.e. expo-go, expo-dev-client, bare react native, etc.
// Here, we are using a heuristic to determine if the project is expo-go based
Expand All @@ -24,7 +24,6 @@ export async function isExpoGoProject(): Promise<boolean> {
// 2) The project doesn't have an android or ios folder
// 3) The expo_go_project_tester.js script runs successfully – the script uses expo-cli
// internals to resolve project config and tells expo-go and dev-client apart.
const appRoot = getAppRootFolder();

if (!fileExists(appRoot, "app.json") && !fileExists(appRoot, "app.config.js")) {
// app.json or app.config.js is required for expo-go projects
Expand All @@ -43,7 +42,7 @@ export async function isExpoGoProject(): Promise<boolean> {
);
try {
const result = await exec("node", [expoGoProjectTesterScript], {
cwd: getAppRootFolder(),
cwd: appRoot,
allowNonZeroExit: true,
});
return result.exitCode === 0;
Expand Down Expand Up @@ -89,11 +88,15 @@ export function fetchExpoLaunchDeeplink(
});
}

export async function downloadExpoGo(platform: DevicePlatform, cancelToken: CancelToken) {
export async function downloadExpoGo(
platform: DevicePlatform,
cancelToken: CancelToken,
appRoot: string
) {
const downloadScript = path.join(extensionContext.extensionPath, "lib", "expo_go_download.js");
const { stdout } = await cancelToken.adapt(
exec("node", [downloadScript, platform], {
cwd: getAppRootFolder(),
cwd: appRoot,
})
);

Expand Down
Loading

0 comments on commit 9317a59

Please sign in to comment.