Skip to content
8 changes: 7 additions & 1 deletion src/apphosting/secrets/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
gcsm.labels.restore();
gcsm.getIamPolicy.throws("Unexpected getIamPolicy call");
gcsm.setIamPolicy.throws("Unexpected setIamPolicy call");
// Unstubbed, this reaches the Compute API over the network and races mocha's 2s
// timeout. The fake derives the address from its argument so the tests still pin
// that the project number is passed through.
sinon
.stub(gce, "getDefaultServiceAccount")
.callsFake((pn: string) => Promise.resolve(`${pn}-compute@developer.gserviceaccount.com`));
});

afterEach(() => {
Expand All @@ -38,7 +44,7 @@
it("uses explicit account", async () => {
const backend = {
serviceAccount: "sa",
} as any as apphosting.Backend;

Check warning on line 47 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type
expect(await secrets.serviceAccountsForBackend("number", backend)).to.deep.equal({
buildServiceAccount: "sa",
runServiceAccount: "sa",
Expand All @@ -46,10 +52,10 @@
});

it("has a fallback for legacy SAs", async () => {
const backend = {} as any as apphosting.Backend;

Check warning on line 55 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type
expect(await secrets.serviceAccountsForBackend("number", backend)).to.deep.equal({
buildServiceAccount: gcb.getDefaultServiceAccount("number"),
runServiceAccount: await gce.getDefaultServiceAccount("number"),
runServiceAccount: "number-compute@developer.gserviceaccount.com",
});
});
});
Expand Down Expand Up @@ -202,15 +208,15 @@
let err;
try {
await secrets.upsertSecret("project", "secret");
} catch (e: any) {

Check warning on line 211 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type
err = e;

Check warning on line 212 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe assignment of an `any` value
}

expect(err.message).to.equal(

Check warning on line 215 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .message on an `any` value
"Unexpected error loading secret: HTTP Error: 403, This API method requires billing to be enabled.",
);
expect(err.status).to.equal(403);

Check warning on line 218 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .status on an `any` value
expect(err.original).to.equal(original);

Check warning on line 219 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .original on an `any` value
expect(gcsm.createSecret).to.not.have.been.called;
});
});
Expand Down Expand Up @@ -603,8 +609,8 @@
it("creates a new secret and grants access", async () => {
gcsm.getSecret.rejects({ status: 404 });
utils.readSecretValue.resolves("secretValue");
gcsm.addVersion.resolves({

Check warning on line 612 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe argument of type `any` assigned to a parameter of type `Required<SecretVersion> | undefined`
secret: { name: "secret", projectId: "project" } as any,

Check warning on line 613 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type

Check warning on line 613 in src/apphosting/secrets/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe assignment of an `any` value
versionId: "1",
} as any);
prompt.select.resolves("production");
Expand Down
8 changes: 8 additions & 0 deletions src/deploy/functions/checkIam.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as sinon from "sinon";
import * as checkIam from "./checkIam";
import * as storage from "../../gcp/storage";
import * as rm from "../../gcp/resourceManager";
import * as gce from "../../gcp/computeEngine";
import * as backend from "./backend";

const projectId = "my-project";
Expand Down Expand Up @@ -30,6 +31,13 @@ describe("checkIam", () => {
let setIamStub: sinon.SinonStub;

beforeEach(() => {
// Unstubbed, this reaches the Compute API over the network and each test that
// needs the default service account races mocha's 2s timeout. The fake derives
// the address from its argument so the tests still pin that checkIam passes the
// project number through.
sinon
.stub(gce, "getDefaultServiceAccount")
.callsFake((pn: string) => Promise.resolve(`${pn}-compute@developer.gserviceaccount.com`));
storageStub = sinon
.stub(storage, "getServiceAccount")
.throws("unexpected call to storage.getServiceAccount");
Expand Down
13 changes: 12 additions & 1 deletion src/deploy/functions/release/fabricator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import * as gce from "../../../gcp/computeEngine";
import * as iam from "../../../gcp/iam";
import * as resourcemanager from "../../../gcp/resourceManager";

const DEFAULT_COMPUTE_SERVICE_ACCOUNT = "1234567-compute@developer.gserviceaccount.com";

describe("Fabricator", () => {
// Stub all GCP APIs to make sure this test is hermetic
let gcf: sinon.SinonStubbedInstance<typeof gcfNS>;
Expand All @@ -40,6 +42,7 @@ describe("Fabricator", () => {
let tasks: sinon.SinonStubbedInstance<typeof cloudtasksNS>;
let services: sinon.SinonStubbedInstance<typeof servicesNS>;
let identityPlatform: sinon.SinonStubbedInstance<typeof identityPlatformNS>;
let computeEngine: sinon.SinonStubbedInstance<typeof gce>;

beforeEach(() => {
gcf = sinon.stub(gcfNS);
Expand All @@ -53,6 +56,7 @@ describe("Fabricator", () => {
tasks = sinon.stub(cloudtasksNS);
services = sinon.stub(servicesNS);
identityPlatform = sinon.stub(identityPlatformNS);
computeEngine = sinon.stub(gce);

gcf.functionFromEndpoint.restore();
gcfv2.functionFromEndpoint.restore();
Expand Down Expand Up @@ -104,6 +108,13 @@ describe("Fabricator", () => {
identityPlatform.setBlockingFunctionsConfig.rejects(
new Error("unexpected identityPlatform.setBlockingFunctionsConfig"),
);
// Unstubbed, this reaches the Compute API over the network and every test that
// needs the default service account races mocha's 2s timeout. The fake derives
// the address from its argument so the tests still pin that the fabricator passes
// the project number through.
computeEngine.getDefaultServiceAccount.callsFake((pn: string) =>
Promise.resolve(`${pn}-compute@developer.gserviceaccount.com`),
);
});

afterEach(() => {
Expand Down Expand Up @@ -892,7 +903,7 @@ describe("Fabricator", () => {

await fab.createV2Function(ep, new scraper.SourceTokenScraper());
expect(run.setInvokerCreate).to.have.been.calledWith(ep.project, "service", [
await gce.getDefaultServiceAccount(fab.projectNumber),
DEFAULT_COMPUTE_SERVICE_ACCOUNT,
]);
});

Expand Down
15 changes: 15 additions & 0 deletions src/gcp/cloudscheduler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { expect } from "chai";
import * as sinon from "sinon";
import nock from "../test/helpers/nock";

import { FirebaseError } from "../error";
import * as api from "../api";
import * as backend from "../deploy/functions/backend";
import * as cloudscheduler from "./cloudscheduler";
import * as gce from "./computeEngine";
import { cloneDeep } from "../utils";

const VERSION = "v1";
Expand Down Expand Up @@ -157,6 +159,19 @@ describe("cloudscheduler", () => {
});

describe("jobFromEndpoint", () => {
beforeEach(() => {
// Unstubbed, this reaches the Compute API over the network and each v2 endpoint
// test races mocha's 2s timeout. The fake derives the address from its argument
// so the tests still pin that jobFromEndpoint passes the project number through.
sinon
.stub(gce, "getDefaultServiceAccount")
.callsFake((pn: string) => Promise.resolve(`${pn}-compute@developer.gserviceaccount.com`));
});

afterEach(() => {
sinon.verifyAndRestore();
});

const V1_ENDPOINT: backend.Endpoint = {
platform: "gcfv1",
id: "id",
Expand Down
Loading