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

Adding support for <product>_EMULATOR_BINARY_PATH for local emualtor dev #6981

Open
wants to merge 3 commits 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/emulator/download.ts
Expand Up @@ -12,8 +12,16 @@

tmp.setGracefulCleanup();

export async function downloadEmulator(name: DownloadableEmulators): Promise<void> {

Check warning on line 15 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing JSDoc comment
const emulator = downloadableEmulators.getDownloadDetails(name);
if (emulator.localOnly) {
EmulatorLogger.forEmulator(name).logLabeled(
"WARN",
name,
`Env variable override detected, skipping download. Using ${emulator} emulator at ${emulator.binaryPath}`,

Check warning on line 21 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Invalid type "EmulatorDownloadDetails" of template literal expression

Check warning on line 21 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Invalid type "string | undefined" of template literal expression
);
return;
}
EmulatorLogger.forEmulator(name).logLabeled(
"BULLET",
name,
Expand Down Expand Up @@ -43,7 +51,7 @@
removeOldFiles(name, emulator);
}

export async function downloadExtensionVersion(

Check warning on line 54 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing JSDoc comment
extensionVersionRef: string,
sourceDownloadUri: string,
targetDir: string,
Expand Down Expand Up @@ -86,7 +94,7 @@
for (const file of files) {
const fullFilePath = path.join(emulator.opts.cacheDir, file);

if (file.indexOf(emulator.opts.namePrefix) < 0) {

Check warning on line 97 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Use 'includes()' method instead
// This file is not related to this emulator, could be a JAR
// from a different emulator or just a random file.
continue;
Expand Down Expand Up @@ -130,7 +138,7 @@
return new Promise((resolve, reject) => {
const hash = crypto.createHash("md5");
const stream = fs.createReadStream(filepath);
stream.on("data", (data: any) => hash.update(data));

Check warning on line 141 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type

Check warning on line 141 in src/emulator/download.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe argument of type `any` assigned to a parameter of type `BinaryLike`
stream.on("end", () => {
const checksum = hash.digest("hex");
return checksum === expectedChecksum
Expand Down
18 changes: 16 additions & 2 deletions src/emulator/downloadableEmulators.ts
Expand Up @@ -265,7 +265,7 @@
shell: false,
},
pubsub: {
binary: getExecPath(Emulators.PUBSUB)!,

Check warning on line 268 in src/emulator/downloadableEmulators.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Forbidden non-null assertion
args: [],
optionalArgs: ["port", "host"],
joinArgs: true,
Expand Down Expand Up @@ -293,7 +293,7 @@
}

/**
* @param name

Check warning on line 296 in src/emulator/downloadableEmulators.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing JSDoc @param "name" description
*/
export function getLogFileName(name: string): string {
return `${name}-debug.log`;
Expand All @@ -306,7 +306,7 @@
*/
export function _getCommand(
emulator: DownloadableEmulators,
args: { [s: string]: any },

Check warning on line 309 in src/emulator/downloadableEmulators.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
): DownloadableEmulatorCommand {
const baseCmd = Commands[emulator];

Expand Down Expand Up @@ -489,7 +489,21 @@
* @param emulator
*/
export function getDownloadDetails(emulator: DownloadableEmulators): EmulatorDownloadDetails {
return DownloadDetails[emulator];
const details = DownloadDetails[emulator];
const pathOverride = process.env[`${emulator.toUpperCase()}_EMULATOR_BINARY_PATH`];
if (pathOverride) {
const logger = EmulatorLogger.forEmulator(emulator);
logger.logLabeled(
"WARN",
emulator,
`Env variable override detected. Using ${emulator} emulator at ${pathOverride}`,
);
details.downloadPath = pathOverride;
details.binaryPath = pathOverride;
details.localOnly = true;
fs.chmodSync(pathOverride, 0o755);
}
return details;
}

/**
Expand Down Expand Up @@ -565,7 +579,7 @@
},
extraEnv: Partial<NodeJS.ProcessEnv> = {},
): Promise<void> {
const downloadDetails = DownloadDetails[targetName];
const downloadDetails = getDownloadDetails(targetName);
const emulator = get(targetName);
const hasEmulator = fs.existsSync(getExecPath(targetName));
const logger = EmulatorLogger.forEmulator(targetName);
Expand Down
4 changes: 2 additions & 2 deletions src/emulator/storage/rules/runtime.ts
Expand Up @@ -27,7 +27,7 @@ import { downloadEmulator } from "../../download";
import * as fs from "fs-extra";
import {
_getCommand,
DownloadDetails,
getDownloadDetails,
handleEmulatorProcessError,
} from "../../downloadableEmulators";
import { EmulatorRegistry } from "../../registry";
Expand Down Expand Up @@ -124,7 +124,7 @@ export class StorageRulesRuntime {
if (this.alive) {
return;
}
const downloadDetails = DownloadDetails[Emulators.STORAGE];
const downloadDetails = getDownloadDetails(Emulators.STORAGE);
const hasEmulator = fs.existsSync(downloadDetails.downloadPath);

if (!hasEmulator) {
Expand Down
3 changes: 3 additions & 0 deletions src/emulator/types.ts
Expand Up @@ -190,6 +190,9 @@ export interface EmulatorDownloadDetails {
// If specified, a path where the runnable binary can be found after downloading and
// unzipping. Otherwise downloadPath will be used.
binaryPath?: string;

// If true, never try to download this emualtor. Set when developing with local versions of an emulator.
localOnly?: boolean;
}

export interface DownloadableEmulatorDetails {
Expand Down
41 changes: 41 additions & 0 deletions src/test/emulators/downloadableEmulators.spec.ts
@@ -1,5 +1,7 @@
import { expect } from "chai";
import * as path from "path";
import * as sinon from "sinon";
import * as fs from "fs-extra";

import * as downloadableEmulators from "../../emulator/downloadableEmulators";
import { Emulators } from "../../emulator/types";
Expand All @@ -12,9 +14,48 @@ function checkDownloadPath(name: DownloadableEmulator): void {
}

describe("downloadDetails", () => {
const tempEnvVars: Record<DownloadableEmulator, string> = {
firestore: "",
database: "",
pubsub: "",
};
let chmodStub: sinon.SinonStub;
beforeEach(() => {
chmodStub = sinon.stub(fs, "chmodSync").returns();
tempEnvVars["firestore"] = process.env["FIRESTORE_EMULATOR_BINARY_PATH"] ?? "";
tempEnvVars["database"] = process.env["DATABASE_EMULATOR_BINARY_PATH"] ?? "";
tempEnvVars["pubsub"] = process.env["PUBSUB_EMULATOR_BINARY_PATH"] ?? "";
delete process.env["FIRESTORE_EMULATOR_BINARY_PATH"];
delete process.env["DATABASE_EMULATOR_BINARY_PATH"];
delete process.env["PUBSUB_EMULATOR_BINARY_PATH"];
});

afterEach(() => {
chmodStub.restore();
process.env["FIRESTORE_EMULATOR_BINARY_PATH"] = tempEnvVars["firestore"];
process.env["DATABASE_EMULATOR_BINARY_PATH"] = tempEnvVars["database"];
process.env["PUBSUB_EMULATOR_BINARY_PATH"] = tempEnvVars["pubsub"];
});
it("should match the basename of remoteUrl", () => {
checkDownloadPath(Emulators.FIRESTORE);
checkDownloadPath(Emulators.DATABASE);
checkDownloadPath(Emulators.PUBSUB);
});

it("should apply environment varable overrides", () => {
process.env["FIRESTORE_EMULATOR_BINARY_PATH"] = "my/fake/firestore";
process.env["DATABASE_EMULATOR_BINARY_PATH"] = "my/fake/database";
process.env["PUBSUB_EMULATOR_BINARY_PATH"] = "my/fake/pubsub";

expect(downloadableEmulators.getDownloadDetails(Emulators.FIRESTORE).binaryPath).to.equal(
"my/fake/firestore",
);
expect(downloadableEmulators.getDownloadDetails(Emulators.DATABASE).binaryPath).to.equal(
"my/fake/database",
);
expect(downloadableEmulators.getDownloadDetails(Emulators.PUBSUB).binaryPath).to.equal(
"my/fake/pubsub",
);
expect(chmodStub.callCount).to.equal(3);
});
});