feature/add auth event arc experiment#10635
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for experimental Eventarc-based Auth triggers (v2 onUserCreated and onUserDeleted events) under a new autheventarc experiment flag. It adds the experiment configuration, maps the events to noOpService, validates that the experiment is enabled during deployment, and includes corresponding unit tests. The feedback suggests optimizing the event type validation by using a module-level Set to avoid inline type assertions and improve lookup performance. Additionally, it is recommended to use the public experiments.setEnabled API in unit tests instead of stubbing experiments.assertEnabled with Sinon to make the tests more robust.
| import * as experiments from "../../experiments"; | ||
| import { AUTH_EVENTS } from "../../functions/events/v2"; |
There was a problem hiding this comment.
| if (backend.isEventTriggered(ep)) { | ||
| if ((AUTH_EVENTS as readonly string[]).includes(ep.eventTrigger.eventType)) { | ||
| experiments.assertEnabled("autheventarc", "deploy Auth Eventarc triggers"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Use the module-level AUTH_EVENTS_SET to check if the event type is an Auth Eventarc trigger. This avoids the inline type assertion as readonly string[] and provides
| if (backend.isEventTriggered(ep)) { | |
| if ((AUTH_EVENTS as readonly string[]).includes(ep.eventTrigger.eventType)) { | |
| experiments.assertEnabled("autheventarc", "deploy Auth Eventarc triggers"); | |
| } | |
| } | |
| if (backend.isEventTriggered(ep)) { | |
| if (AUTH_EVENTS_SET.has(ep.eventTrigger.eventType)) { | |
| experiments.assertEnabled("autheventarc", "deploy Auth Eventarc triggers"); | |
| } | |
| } |
| it("disallows v2 Auth Eventarc triggers if autheventarc experiment is not enabled", () => { | ||
| const sandbox = sinon.createSandbox(); | ||
| const assertEnabledStub = sandbox.stub(experiments, "assertEnabled"); | ||
| assertEnabledStub | ||
| .withArgs("autheventarc", sinon.match.any) | ||
| .throws(new FirebaseError("the experiment autheventarc is not enabled")); | ||
|
|
||
| const ep: backend.Endpoint = { | ||
| ...ENDPOINT_BASE, | ||
| platform: "gcfv2", | ||
| eventTrigger: { | ||
| eventType: "google.firebase.auth.user.v2.created", | ||
| eventFilters: {}, | ||
| retry: false, | ||
| }, | ||
| }; | ||
|
|
||
| try { | ||
| expect(() => validate.endpointsAreValid(backend.of(ep))).to.throw( | ||
| /the experiment autheventarc is not enabled/ | ||
| ); | ||
| } finally { | ||
| sandbox.restore(); | ||
| } | ||
| }); | ||
|
|
||
| it("allows v2 Auth Eventarc triggers if autheventarc experiment is enabled", () => { | ||
| const sandbox = sinon.createSandbox(); | ||
| const assertEnabledStub = sandbox.stub(experiments, "assertEnabled"); | ||
| assertEnabledStub.withArgs("autheventarc", sinon.match.any).returns(); | ||
|
|
||
| const ep: backend.Endpoint = { | ||
| ...ENDPOINT_BASE, | ||
| platform: "gcfv2", | ||
| eventTrigger: { | ||
| eventType: "google.firebase.auth.user.v2.created", | ||
| eventFilters: {}, | ||
| retry: false, | ||
| }, | ||
| }; | ||
|
|
||
| try { | ||
| expect(() => validate.endpointsAreValid(backend.of(ep))).to.not.throw(); | ||
| } finally { | ||
| sandbox.restore(); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Instead of stubbing experiments.assertEnabled with Sinon, we can use the public experiments.setEnabled API to toggle the experiment state. This tests the actual integration with the experiments module, verifies the real error messages, and avoids stubbing module exports which can be brittle and problematic in some environments.
it("disallows v2 Auth Eventarc triggers if autheventarc experiment is not enabled", () => {
experiments.setEnabled("autheventarc", false);
const ep: backend.Endpoint = {
...ENDPOINT_BASE,
platform: "gcfv2",
eventTrigger: {
eventType: "google.firebase.auth.user.v2.created",
eventFilters: {},
retry: false,
},
};
try {
expect(() => validate.endpointsAreValid(backend.of(ep))).to.throw(
/Cannot deploy Auth Eventarc triggers because the experiment.*autheventarc.*is not enabled/
);
} finally {
experiments.setEnabled("autheventarc", null);
}
});
it("allows v2 Auth Eventarc triggers if autheventarc experiment is enabled", () => {
experiments.setEnabled("autheventarc", true);
const ep: backend.Endpoint = {
...ENDPOINT_BASE,
platform: "gcfv2",
eventTrigger: {
eventType: "google.firebase.auth.user.v2.created",
eventFilters: {},
retry: false,
},
};
try {
expect(() => validate.endpointsAreValid(backend.of(ep))).to.not.throw();
} finally {
experiments.setEnabled("autheventarc", null);
}
});
inlined
left a comment
There was a problem hiding this comment.
I wouldn't create an experiment for this (especially a public one). Experiments help us avoid clutter (e.g. the internal test utilities), guard against changes, or inform a customer that they're trying beta code.
Historically for adding new event types we've just not added documentation to the API and not added it to index.ts. If you want to add additional rigor to our process that's fine by me, but we shouldn't make the experiment public because it draws attention when we wren't asking for beta testers ATM.
And Gemini is right; setEnabled is there for testing so you can prefer it over mocks.
This PR registers and gates the new experimental autheventarc feature flag within the Firebase CLI to control the deployment of v2 Auth Eventarc triggers (onUserCreated and onUserDeleted). It officially defines these event types in the CLI's v2 events registry and maps them to the default service map to ensure type safety. During deployment validation, the CLI checks for these trigger types and asserts that the autheventarc experiment is enabled, blocking deployments with a friendly error if it is not. This ensures the experimental triggers can be safely integrated into the SDK while preventing accidental deployments until the backend is fully launched. All changes have been verified with type checks and corresponding unit tests.