Skip to content

feat: support Cloud Functions lifecycle hooks#10728

Draft
wandamora wants to merge 9 commits into
mainfrom
morawand-cf3-lifecycle-hooks
Draft

feat: support Cloud Functions lifecycle hooks#10728
wandamora wants to merge 9 commits into
mainfrom
morawand-cf3-lifecycle-hooks

Conversation

@wandamora

@wandamora wandamora commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR introduces support for Cloud Functions (CF3) lifecycle hooks, allowing developers to run actions after deployment events. Specifically, it supports the afterInstall and afterUpdate hooks.

The implementation spans:

  1. Manifest & Discovery Parsing: Parses lifecycleHooks config from the generated functions build manifest/metadata. Support is added to define task (Task Queue functions), callable (Callable functions), and http (HTTP functions or custom URLs) hooks. The execution of hook and callable functions is not yet implemented.
  2. Release Execution Flow: During deployment release, the CLI compares the codebase's current status and target backend configurations to determine if a deploy is a fresh install (afterInstall hook target) or a subsequent update (afterUpdate hook target).
  3. Task Queue Hook Execution & Authentication: Integrates with Cloud Tasks (cloudtasks.ts) to enqueue tasks targeting hook functions. Resolves the service account to attach an oidcToken so that invocations are securely authenticated.
  4. Validation & Prefixing:
    • Validates that target endpoints exist in the backend, match expected triggers (e.g., task hook targeting a task queue function), and are GCF Gen 2 functions.
    • Supports codebase prefixing for target functions in multi-codebase setups.
  5. Logging: Logs a Google Cloud Console log viewer link to easily monitor hook function execution.

Scenarios Tested

  • Verified afterInstall only deploys for new codebases
  • Verified afterUpdate only deploys for any changes in the codebase
  • Verified that error is thrown if either hook is declared more than once
  • Verified task queues are dispatched correctly
  • Verified hooks are successfully removed upon deletion
  • Verified hooks in multiple codebases depend on their respective codebases.
  • Verified log URLs are correctly output on success.

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

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.

Code Review

This pull request introduces support for GCF Gen 2 lifecycle hooks (afterInstall and afterUpdate) in Firebase Functions deployments, including manifest parsing, backend validation, and execution of task queue hooks via Cloud Tasks. The review feedback highlights several critical issues: a type mismatch when calling getProjectNumber, a logic bug in codebase filtering that causes hooks to be skipped for the default codebase, validation failures during partial deployments, a potential runtime TypeError when parsing null lifecycle hooks, and the silent skipping of unsupported callable and http hooks during execution.

throw new FirebaseError(`Target endpoint "${taskHook.function}" does not have a trigger URI.`);
}

const projectNumber = await getProjectNumber({ projectId: targetEndpoint.project });

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.

critical

The getProjectNumber utility function expects a string representing the project ID (as seen in release/index.ts line 96), but here it is being passed an object { projectId: targetEndpoint.project }. This will cause a type mismatch and a runtime crash when trying to resolve the project number. We should pass the project ID string directly.

Suggested change
const projectNumber = await getProjectNumber({ projectId: targetEndpoint.project });
const projectNumber = await getProjectNumber(targetEndpoint.project);

Comment thread src/deploy/functions/release/lifecycle.ts
Comment thread src/deploy/functions/validate.ts Outdated
Comment thread src/deploy/functions/runtimes/discovery/v1alpha1.ts Outdated
Comment on lines +68 to +76
if (hook.callable) {
logger.info(`Skipping hook execution for unsupported actionType: callable`);
return false;
}

if (hook.http) {
logger.info(`Skipping hook execution for unsupported actionType: http`);
return false;
}

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

While callable and http hooks are successfully parsed and validated, they are currently silently skipped during execution with an info log. This can lead to a confusing user experience where configured hooks silently fail to run. If these hook types are not supported yet, we should throw a validation error in validateLifecycleHooks to inform the user upfront, or implement their execution here.

1. Adds validation of each trigger
2. Ensures they are prefixed properly
3. Resolves SA for OIDC token
4. Outputs a Cloud COnsole log
@wandamora wandamora force-pushed the morawand-cf3-lifecycle-hooks branch from f688cf8 to f1e0350 Compare June 26, 2026 21:30
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