Skip to content

fix(eventarc): set eventTrigger.region from channel to prevent unnecessary delete+recreate on deploy#1855

Open
deepfotello wants to merge 1 commit intofirebase:masterfrom
deepfotello:fix/eventarc-trigger-region
Open

fix(eventarc): set eventTrigger.region from channel to prevent unnecessary delete+recreate on deploy#1855
deepfotello wants to merge 1 commit intofirebase:masterfrom
deepfotello:fix/eventarc-trigger-region

Conversation

@deepfotello
Copy link
Copy Markdown

Problem

Functions defined with onCustomEventPublished are deleted and recreated on every deployment instead of being updated in-place. This causes:

  • Eventarc triggers to temporarily disappear during deployment, creating a window where events are silently dropped
  • Loss of Cloud Run revision history for affected functions
  • Unnecessary downtime for event-driven functions in production

Root Cause

When firebase-tools compares the desired state ("want") against the deployed state ("have") during deployment planning, it calls changedTriggerRegion() in src/deploy/functions/release/planner.ts:

return want.eventTrigger.region !== have.eventTrigger.region;

"have" side: endpointFromFunction() in firebase-tools (cloudfunctionsv2.ts#L698-L703) correctly reads triggerRegion from the GCP API response and maps it to endpoint.eventTrigger.region (e.g., "us-central1").

"want" side: The ManifestEndpoint emitted by onCustomEventPublished in firebase-functions never sets eventTrigger.region, so it remains undefined.

This means undefined !== "us-central1" evaluates to true on every deployment, forcing deleteAndRecreate = true — even when nothing has changed.

Fix

Derive the trigger region from the channel string (which already contains the region) and set it on eventTrigger.region in the manifest endpoint. The channel follows the format locations/{region}/channels/{channel-id}, so the region is already available.

This ensures firebase-tools sees matching regions on both sides and performs an in-place PATCH update instead of DELETE + POST.

Reproduction

  1. Create any function using onCustomEventPublished:
    export const myFunc = onCustomEventPublished(
        'com.example.event',
        async (event) => { /* handler */ }
    );
  2. Deploy with firebase deploy --only functions
  3. Deploy again with no code changes
  4. Observe in --debug logs: the function is DELETEd then POSTed (created), not PATCHed (updated)

Verification

After this fix, --debug deploy logs show:

PATCH https://cloudfunctions.googleapis.com/v2/.../functions/myFunc

Instead of:

DELETE https://cloudfunctions.googleapis.com/v2/.../functions/myFunc
POST https://cloudfunctions.googleapis.com/v2/.../functions/myFunc

Impact

This affects all users of onCustomEventPublished, including those using the Invertase Stripe extension's custom events. The fix is backward-compatible — it only adds a field that was already expected by firebase-tools but never provided.

@google-cla
Copy link
Copy Markdown

google-cla bot commented Apr 2, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the onCustomEventPublished function in src/v2/providers/eventarc.ts to extract the region from the channel string and include it in the event trigger configuration. Feedback indicates that the regex used for region extraction is brittle and may lead to incorrect assignments if the channel format deviates from the expected pattern, suggesting a more robust parsing approach.

Comment on lines +204 to +205
const channelRegionMatch = channel.match(/locations\/([^/]+)\/channels\//);
const triggerRegion = channelRegionMatch ? channelRegionMatch[1] : "us-central1";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regex used to extract the region from the channel string is brittle. If the channel format changes or if the input does not match the expected pattern, it defaults to 'us-central1' silently. It would be safer to validate the channel format or use a more robust parsing method to avoid incorrect region assignment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants