Repository navigation
Conversation
…tension treated as terminal The extension reported a missing linked transfer config and a rejected partitioning-field removal as a completed install and returned, so Cloud Tasks never retried them. The kit throws on both, which retries five times and then dead-letters. Log them and return instead. Kits have no status channel, so the messages go to Cloud Logging at error level and carry the remediation.
…nts from the real module in tests Both sides of the handler's prefix match came from copies in the test file, so the suite stayed green when the thrown message no longer started with the prefix. Take both constants from the module under test. Also scope the comment on the swallow to what the guard does, since #2985 shows the API does accept clearing the field.
…model TEMPERATURE, TOP_P, TOP_K and CANDIDATE_COUNT were accepted as config in the extension but never forwarded on the generation request. The kit forwards all four, and decides whether to write the candidates field from the count actually sent rather than from the deploy-time value. Record it as a deliberate divergence in the kit's differences section.
…tZodError (#3040) The kit's formatZodError dropped the invalid_string branch the legacy extension has, so string-validation failures (e.g. a failed .email() check) fell through to zod's raw default message instead of the extension's "Field 'x' must be a valid email address" / "Field 'x' is invalid" shape. This restores the branch; the kit pins zod ^3.25.76 (same major as the extension's ^3.24.4), so the issue code and its validation field carry over unchanged. formatZodError is now exported so the new vitest tests can drive it with real zod errors; note the kit's current schemas do not yet use string validators, so this path is only reachable if a schema adds one, matching the extension's defensive intent. Full kit suite, tsc, and prettier pass; no live/e2e run. Part of #3036.
…om embeddings endpoint (#3042) The legacy extension (firestore-vector-search v0.1.3) checked the custom embeddings endpoint's content-type header and rejected non-JSON responses with a clear error; the kit dropped that check, so a non-JSON response (for example an HTML error page) surfaced as a raw `Unexpected token` parse error. This restores the check in `CustomEndpointClient.getEmbeddings`, throwing "Error getting embeddings from custom endpoint: response is not JSON" before parsing, matching the legacy wording. Following review, it also restores two more legacy behaviors in the same method: the schema parse is wrapped so valid JSON of the wrong shape throws "Error getting embeddings from custom endpoint: response does not match expected schema" instead of a raw ZodError, and the length-mismatch message reverts to legacy's exact "response does not contain embeddings" wording. Adds four vitest cases (JSON success with charset parameter, non-JSON content-type, wrong-shape JSON, missing embeddings) - each failing case was written and verified red before its fix. Full kit suite passes (53 tests) and `tsc -b` is clean; note `npx prettier --check src` already fails on origin/kits because prettier 2.7.1 cannot parse `satisfies` in `src/config.ts` (pre-existing, untouched). Part of #3036.
…STALENESS doc example (#3045) Restores two parity items from the #2974 ledger. The bigquery-firestore-export kit gets back the extension's `logs.writeRunResultsToFirestore(runId)` helper, called after the BigQuery results are read and before the row writes, with a test pinning the call and its ordering on both sides (mutation-checked: hoisting the call above the read fails); the kit's full suite, tsc, and prettier pass. The other two dropped helpers, `logs.start()` and `logs.invalidResourceName()`, are deliberately skipped: neither has a call site in the upstream extension (both are defined and never called), and the kit already has its own `start()`/`init(config)` logging, so restoring them would add dead code. The MAX_STALENESS doc example is restored to the extension's `INTERVAL "8:0:0" HOUR TO SECOND`; the ledger and #3036 mislabeled which kit owns this param - it actually lives in firestore-bigquery-export, so that is where the fix lands, and it is a JSDoc comment only, so no tests were added for it. Checked #2983, #2980, #2960, #2963 for collisions: none add or rename `writeRunResultsToFirestore` in logs.ts, though #2963 also extends helper.test.ts and may need a trivial merge. Part of #3036.
…ccess and onCompletion (#3071) The kit README's Events section claimed the function publishes `onStart`, `onError`, `onSuccess`, and `onCompletion`. The code publishes `onStart` and `onError` only: `src/handlers.ts` calls `recordStartEvent` and `recordErrorEvent`, and nothing calls `recordSuccessEvent` or `recordCompletionEvent`. The extension emitted `onSuccess` from its `syncBigQuery` task queue handler, which the kit deliberately removed, and the README's differences section already documents that. So the README was the wrong side; this corrects the Events section to list `onStart` and `onError` and point at the differences entry. Re-adding `onSuccess` emission (parity with the extension) is a separate decision, not attempted here. Doc-only change, so no tests. Note #3066 also edits this README; its hunks (config table, provisioning, region sections) do not overlap this one. Fixes #3018
…path (#3073) The `.txt` transcription output URI retained `replace("tmp/", "")` from the legacy extension, where the transcoded `.wav` was uploaded under an object name derived from its local `/tmp` path. The kit uploads the `.wav` bucket-relative, so the remnant only mangled object paths that legitimately contain `tmp/` (e.g. `audio/tmp/clip.mp3` produced a transcript at `audio/clip.mp3.wav_transcription.txt`). The transform is removed; the `.txt` now lands at `<transcoded object>_transcription.txt` exactly, as the README states. Added a unit test on `transcribeAndUpload` pinning the `gcsUri` for a `tmp/`-containing path; it was red against the remnant and is green after. Full vitest suite, `tsc -b` and prettier pass. Live transcription was not run. The open decision on where the transcoded `.wav` lands (#2974 Migration section) is out of scope and unchanged. Fixes #3026
…gurable The kit renamed the notification topic from ext-<instance id>-processMessages to kit-<INSTANCE_ID>-processMessages, so the update path, which reconciles notification_pubsub_topic to whatever the config names, repointed every adopted transfer config on first deploy. Anything else subscribed to the old topic, including an extension instance still installed, stopped receiving run notifications. PUB_SUB_TOPIC now names the topic, defaulting to the kit name. Migrating users can set the extension's topic and keep the transfer config untouched. A linked TRANSFER_CONFIG_NAME config is still never repointed, so a topic mismatch there now logs a warning instead of silently dropping every run.
…ig logs (#3077) The kit logs the full config object via `logs.init` at startup and `logs.start` on every invocation, and the config can carry `googleAiApiKey`, so the secret lands in Cloud Logging in cleartext per event. The fix masks secret-shaped config values as `<omitted>` inside the `start`/`init` message builders, following the firestore-send-email / bigquery-firestore-export convention. Redaction sits at the logging site rather than at the config merge, so it is order-independent with #3075 (still open), which changes where the config picks up the secret inside `getContext()`: whichever PR lands second cannot reintroduce the leak. The handlers test that previously asserted the merged secret appears in `logger.log` now observes merge precedence through the `googleAI` plugin mock instead. Repro-first tests cover both `start` and `init` paths (red on the old code, green now); full vitest suite (95 tests) and `tsc -b` pass. Fixes #3076
…ums and restore the PROJECT_ID error text (#3046) The kit typed safety settings as a local `{ category: string; threshold: string }`, dropping the enum-level typing the extension got from the SDK `SafetySetting` types. `SafetySetting` is now typed with template-literal unions over both pinned SDKs' enums (`@google/generative-ai` and `@google/genai` `HarmCategory` / `HarmBlockThreshold`), so misspelled values fail to compile while plain string literals and enum members both stay valid for lib consumers. An earlier revision also rejected non-enum values at runtime; that was dropped after review, because the extension never validated safety values at runtime (it casts raw env strings) and the pinned `@google/generative-ai` enums lag the live API (no `OFF`, no `HARM_CATEGORY_CIVIC_INTEGRITY`), so the rejection broke previously-working configs. `resolveConfig` now only checks safety settings structurally, and rejects an unknown provider with the extension's `Invalid Provider: X` wording. `getProjectId` now throws the extension's `Missing required environment variables: PROJECT_ID` wording instead of `FIREBASE_CONFIG is not set`, including when `FIREBASE_CONFIG` is present without a projectId. Covered by new resolveConfig, provider and getProjectId tests; full suite (29 tests), tsc and prettier are clean, and the test files were typechecked explicitly since tsconfig excludes them. Not verified against a live deploy. Part of #3036.
…3057) The `firestore-send-email` kit shipped with 14 tests against roughly 1,900 lines of source, while the legacy extension it was ported from carries around 2,000 lines of unit tests. This PR ports the four pure unit suites that transfer without an emulator: `validatePayload` (new `tests/validation.test.ts`), `setSmtpCredentials` / `isSendGrid` (new `tests/helpers.test.ts`), `SendGridTransport` (new `tests/nodemailer-sendgrid.test.ts`), and template merging appended to the existing `tests/prepare-payload.test.ts`. Jest goes to vitest, `it` to `test`, and the legacy `setDependencies` mocking is replaced by the kit's `PreparePayloadDependencies` seam. The kit test count goes from 14 to 115, all green, `tsc -b` clean, prettier clean. Only test files change; no source or manifest is touched. Three tests are new rather than ported, each mutation-verified by breaking the branch it covers and confirming it was the only failure. Two pin guards the kit's transport refactor added and the legacy transport lacked: an empty `watchHtml` emits no content entry, an empty `messageId` emits no header. The third covers the template merge falling back to the message's own attachments when the render supplies none. Deliberately not ported: everything gated on the `TESTING` env flag (the kit has no `process.env.TESTING`), the `describe.skip`'d SMTP e2e, and the `E2E_SENDGRID` live suite. Also dropped are the legacy helper tests' `regex.test(...)` assertions, which only exercised a regex literal declared inside the test file rather than the kit's own `SMTP_CONNECTION_URI` `validationRegex`. Two notes. #3040 also adds `tests/validation.test.ts` with `formatZodError` tests; the two files do not overlap in coverage but will need a trivial merge, whichever lands second. Its `invalid_string` branch is also the one real difference between the kit's `validation.ts` and the legacy file, which are otherwise logic-identical on every reachable path. And no test here touches the SendGrid OAuth2 secret gating in #3009, so nothing pins that bug. Part of #2974.
…e log Dropping it from logs.ts broke the build, since helper.ts still calls it. The run-results logs mock never listed it, so restoring the export alone leaves those tests failing.
The param takes a bare topic ID, but nothing enforced it, and a full projects/<project>/topics/<topic> value produced a double-prefixed notification topic. A validation regex rejects it when prompted, and notificationTopicName passes a resource name through for dotenv values, which the CLI does not validate.
…llback (#3090) The kit's `checkImageContent` threw `FUNCTION_REGION is required for Vertex AI filtering.` when no region was passed; the extension fell back to `us-central1` (master, storage-resize-images/functions/src/content-filter.ts:121). This restores the fallback at the same point of use: the Vertex AI plugin now receives `location ?? "us-central1"` and the throw is gone. `config.ts` and `export-config.ts` are untouched, so there is no overlap with #3002 and the resolved config still reports `FUNCTION_REGION` faithfully. Normal CLI deploys never hit the throw: firebase-tools injects `FUNCTION_REGION` into every gen2 function's env (verified in 15.26.0, lib/gcp/cloudfunctionsv2.js:197). It was reachable for library consumers of `checkImageContent`, emulator runs, and hand-rolled envs. The throw test is replaced by a fallback test (verified to fail against the old code) plus an explicit-location passthrough test; README, CHANGELOG, and a stale test comment are updated. 182 tests and `tsc --noEmit` pass; the live Vertex filtering path was not exercised. This instantiates a "FUNCTION_REGION if set, else us-central1" rule relevant to the open decision in #3028. Fixes #3023
fix(bigquery-firestore-export): stop retrying the two failures the extension treated as terminal
**What was wrong** The `Use Java 21 for the emulator` step sets `JAVA_HOME`, but firebase-tools never reads it: `checkJavaMajorVersion` spawns a bare `java` (confirmed in firebase-tools 15.28.2, `lib/emulator/commandUtils.js`, where `JAVA_HOME` appears nowhere in the package). The runner's default Java 17 stayed in front on PATH, so every emulator-gated kit suite failed with "firebase-tools no longer supports Java version before 21". **What changed** The step now also appends `$JAVA_HOME_21_X64/bin` to `GITHUB_PATH`, so the `java` firebase-tools resolves is 21. `JAVA_HOME` is kept for anything else that honours it. **How it was verified** Read against the published firebase-tools 15 source to confirm the version check reads PATH only, and traced the failure to that step in the run for #3087. `prettier --check` passes and the workflow still parses as YAML. Java is referenced in no other live workflow, and the two steps after this one (Firebase CLI install, emulator tests) are the only consumers in the job, so nothing else moves off 17. CI on this PR does not exercise the fix, since no kit changes here and the emulator job only runs for changed kits. Retargeting a kit PR at this branch, or merging and re-running #3087, is what proves it.
…ot-generation-options
…tion-options docs(kits): note that genai chatbot generation options now reach the model
…the merge The merge into this branch left two vi.mock calls for src/dts and stranded two logs mock keys inside one of them, so the file no longer parsed.
…e path (#3065) On the queryOnWrite path, `handleQueryOnWrite` cast `data.prefilters as Prefilter[]` without validation, so malformed prefilters on a watched query document (a non-array, or non-object entries) either failed downstream inside the Firestore query or silently misbehaved. The legacy extension (firestore-vector-search v0.1.3) zod-parses prefilters with `z.array(prefilterSchema)` on this path (parity ledger #2974, item 7b). This reuses the kit's existing `prefilterSchema` via a new `parsePrefilters` helper and replaces the cast at the point of use, throwing `Invalid prefilters: ...` before any embedding work. The legacy processor additionally caught the error and wrote an ERROR status to the document; the kit throws out of this handler today, and status parity is deferred to ledger item 7c. Tests: a new `handleQueryOnWrite prefilters validation` describe block, confirmed red before the fix; full suite, `tsc -b`, and prettier pass. Note #3038 touches the head of the same function and appends its own onWrite tests; whichever lands second rebases trivially. Fixes #3013 Following review (050ce5d): an explicit `prefilters: null` is treated as no prefilters, preserving the `?? []` behavior the parse replaced, and validation errors include each issue's path so a mixed array names the index of the bad entry. Note the parse checks the top-level shape only (an array of objects), matching legacy's `z.record(z.any())` prefilterSchema; a typo'd key inside a prefilter is not caught here and still surfaces from the Firestore query downstream.
…ion-topic fix(bigquery-firestore-export): make the DTS notification topic configurable
…per process (#3075) The kit's `handleDocumentWrite` called `createTranslationService` on every invocation, so each event built a new `TranslationService` and a fresh translation client. The legacy extension constructs the client once at module scope. Following the kit family's lazy-context pattern (delete-user-data's `getContext`), the service now lives on the memoized `HandlerContext` built once per process in `getContext()`, which also merges the runtime Google AI API key secret into the config there. The `./lib` entry stays side-effect free. New `tests/context.test.ts` drives the real trigger path twice with a mocked `v2.Translate` constructor and pins a single construction; it failed with two constructions before the fix. Full suite (90 tests) and `tsc -b` pass. Fixes #3021
…3038) handleQueryOnWrite ran a vector query and wrote the result back onto the same document it watches, re-firing itself in a self-sustaining loop, billed one embedding call plus one vector query per pass (parity ledger #2974, firestore-vector-search section 7). An earlier revision guarded on the event's before/after snapshots, but that races: if a slow run overwrites a newer query's result, the echo sees unchanged inputs plus a result and skips, stranding query B's inputs with query A's result permanently. The guard now uses stored state instead: the result write also stores the request (query, limit, prefilters) that produced it in the status field, and a trigger skips only when the document's current inputs deep-match that stored record. A stale overwrite mismatches, re-runs on the current inputs, and the corrective echo matches and stops. This is in the spirit of the legacy extension's FirestoreOnWriteProcessor (which the kit cannot consume, being firebase-functions v1-tied) but deliberately stronger: the legacy processor never re-ran a completed query document at all, even when the query changed, and did not track prefilters. The kit re-runs on any input edit, matching its embed-path rule; the README documents the new query-doc status shape and this divergence. Vitest pins the guard, the re-run paths, a legacy doc without a record, and the full race sequence; guard mutations fail 5-11 tests depending on the mutation, including an asymmetric write-path mutation that would loop forever. Kit suite: 65 passed. Unit tests only, not verified against live Firestore. Fixes #3010
…with a multi-region mapping (#3101) This partially reverts #3066, by agreement with the firebase-tools team. #3066 removed the DATABASE_REGION param because its raw value was used as the function region, which hard-failed deploys for multi-region databases (#3017). But the CLI's region inference the kit fell back to is unreliable for param-declared databases: region resolution runs before param substitution and silently defaults to us-central1 (firebase/firebase-tools#11020). Since the extension-to-kit migration exports DATABASE_REGION into the user's .env, the decision is to keep using it, with the mapping that makes it safe where the pre-#3066 code failed. The restored param now places all three functions: Firestore multi-region locations map to a Cloud Run region (nam5/nam7 to us-central1, eur3 to europe-west1, mirroring the CLI's own FIRESTORE_DUAL_REGION_TO_REGION_MAPPING); regional locations pass through; unset keeps today's no-region behavior. The region is read from process.env at module load, which requires firebase-tools >= 15.28.0 (firebase/firebase-tools#10936) to be present during discovery; on older CLIs it degrades to the no-region fallback rather than failing. Tests pin all mapping cases and the unset case, and breaking the mapping fails them. No live multi-region deploy was run this time; #3066's no-region behavior was live-verified on nam5.
….2-rc.2 [skip ci]
…-bugs docs(kits): add bug reporting instructions
…ncurrency fix(storage-resize-images): match the extension's Gen1 concurrency and CPU
…nd OUTPUT_OPTIONS at deploy The CLI applies a param's validationRegex only at the prompt, so a bad value in .env deployed and then failed every upload. Check these values at module load so discovery fails naming the param, and document quoting JSON values in .env.
…OR severity An error thrown before the resize, such as an invalid SHARP_OPTIONS, reached the logs only as unstructured stderr. Log it with logger.error and rethrow, and note in the README that 2nd gen failures should be alerted on from logs.
…ploy europe-north2 and northamerica-south1 have no Cloud Functions location, and the CLI only lets a function listen to a regional bucket from the same region, so neither option can deploy.
…and OUTPUT_OPTIONS
…tions Reject multi-line SHARP_OPTIONS and OUTPUT_OPTIONS as the extension does, give OUTPUT_OPTIONS an error that matches what is checked, and say to single-quote JSON values in .env.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Matches the extension's ERROR entry so Error Reporting groups each failure once. The README now says that failed events are always recorded as HTTP 200 and that timeouts are never logged at ERROR.
…ress (#3276) Pins the extension's `concurrency: 1`, `cpu: "gcf_gen1"` and `ingressSettings: "ALLOW_INTERNAL_ONLY"` on all three kit functions, so auto-discovery no longer runs `handleSearch` out of memory and silently skips deletions. Fixes #3250. Follows #3209 (`firestore-bigquery-export`) and #3233 (`firestore-send-email`). #3206 sets concurrency and ingress for this kit but not `cpu`, and is open with conflicts, so this lands the `delete-user-data` part on its own; #3206 can drop this kit. ## Changes - `clearData`, `handleSearch` and `handleDeletion` declare `concurrency: 1`, `cpu: "gcf_gen1"` and `ingressSettings: "ALLOW_INTERNAL_ONLY"`. - README: notes the matching runtime settings, and the remaining max-instances difference with how to raise it (`setGlobalOptions({ maxInstances })` before loading the kit). - CHANGELOG entry. - Test that each function's `__endpoint` has the three options. ## Testing Deployed side by side on a test project, each with its own Firestore database: extension `firebase/delete-user-data@0.1.30`, the kit from `kits` @ fcdd555, and the kit from this branch. Same config for all: auto-discovery on, depth 1, default search fields, shallow mode, no paths. Each database has 20 root collections × 2,500 docs (~2 KB each) plus one doc per collection owned by the test user. I then created and deleted the user and counted the user's docs about 3 minutes later. Two runs: | | Extension | Kit before | Kit after | |---|---|---|---| | Concurrency | 1 | 80 | 1 | | CPU | 1st gen, 256MB | 1 | 0.1666 | | Ingress | `ALLOW_INTERNAL_ONLY` | `ALLOW_ALL` | `ALLOW_INTERNAL_ONLY` | | Max instances | 3000 | 100 (default) | 100 (default) | | User docs deleted, run 1 | 20/20 | 0/20 | 20/20 | | User docs deleted, run 2 | 20/20 | 1/20 | 20/20 | | `handleSearch` failures | none | 1 × `Memory limit of 256 MiB exceeded`, 18–19 × "The request failed because ... connection to the instance had an error" per run | none | - With internal-only ingress, the kit still receives the Auth deletion event (`clearData`) and both Pub/Sub topics (20 `handleSearch` and 20 `handleDeletion` requests per run). - The 100-instance cap didn't matter here (20 searches per deletion), so it is left at the default and documented. - `vitest run`: 122 tests pass. Prettier passes on the changed files. `tsc` passes once `@types/node` is available; the kit's tsconfig lists it, but it isn't installed on `kits`, so `pnpm build` fails there with or without this change.
…rted-regions fix(storage-resize-images): drop BUCKET_REGION options that cannot deploy
…e-env-params fix(storage-resize-images): reject invalid IMG_SIZES, SHARP_OPTIONS and OUTPUT_OPTIONS at deploy
…dler-errors fix(storage-resize-images): log errors that escape the trigger at ERROR severity
…t deploy (#3278) Rejects the `.env` values the extension refuses at install time, so the kit's deploy fails instead of deploying and quietly deleting less data. Values the extension accepts, its option labels included, still deploy and run as they did in the extension. Fixes #3258 (part of #3249). ## Changes - `assertValidParams()` in `src/config.ts`. It reads each param's declared `input` (no copied lists): a select value must be one of the option values or labels, and a text value must match its `validationRegex`. The error names the param, the bad value and the allowed values, and lists every bad param at once. - Unset and empty values are skipped, so optional params can stay blank as in the extension. Blank required params are still handled by `assertRequiredParams()` (see #3256). - `assertParams()` runs both checks at module load and throws once, so a blank required param and an invalid value are reported in the same deploy. `assertRequiredParams()` itself is unchanged, as the other kits share it. - Option labels (`Recursive`, `Shallow`, `Yes`, `No`, `United States`, `Belgium`, `Singapore`) are accepted, as the extension's installer accepted them. They run as they did in the extension: `Recursive` deletes shallowly, `Yes` leaves auto-discovery off, and a location label gives a database URL that doesn't exist. The README warns about this and says to use the values. - Tests in `tests/valid-params.test.ts` and `tests/index.test.ts`. README (Configuration) and CHANGELOG updated. - Issue edit: the "Precedent: #3124" line now points at the existing `assertRequiredParams()` / `validatePathListsFromEnv()` pattern. #3124 was closed; #3169 (open, into `next`) proposes the `IMAGE_TYPE` checks. Example error: ``` Error: Invalid parameter values: FIRESTORE_DELETE_MODE="RECURSIVE" must be one of: recursive, shallow. Fix them in this instance's .env or .env.<projectId> file, or remove the entries to use their defaults. ``` ## Testing Deployed on a test project: the extension `firebase/delete-user-data@0.1.30`, the kit from `kits` and the fixed kit, each with its own Firestore database. Each had `FIRESTORE_PATHS=users/{UID}` and was seeded with `users/<uid>`, `users/<uid>/sub/s1`, `things/t-<uid> {uid}` and a control doc; then a test user was deleted. Bad values (extension checked with the instances API `validateOnly=true`; kits with a real `firebase deploy`): | `.env` value | Extension | Kit before | Kit after | |---|---|---|---| | `FIRESTORE_DELETE_MODE=RECURSIVE` / `recursivex` | rejected | deploys | deploy fails | | `FIRESTORE_DELETE_MODE=Recursive` (label) | accepted | deploys | deploys¹ | | `ENABLE_AUTO_DISCOVERY=true` / `YES` | rejected | deploys | deploy fails | | `SELECTED_DATABASE_LOCATION=us-east1` / `US-CENTRAL1` | rejected | deploys | deploy fails | | `SELECTED_DATABASE_INSTANCE=https://x.firebaseio.com` | rejected | deploys | deploy fails | | `CLOUD_STORAGE_BUCKET=gs://x` / `Upper_Case` | rejected | deploys | deploy fails | | blank `SELECTED_DATABASE_INSTANCE` / `SELECTED_DATABASE_LOCATION` | accepted | deploys | deploys | ¹ The deploy run rejected labels; accepting them came later (32a478f) and is covered by unit tests, not a fresh deploy. The kit before deployed with all five bad values in one `.env`; the runtime env held them as written. User deletion (extension and fixed kit with `recursive` / `yes`, kit before with `RECURSIVE` / `true`): | Doc | Extension | Kit before | Kit after | |---|---|---|---| | `users/<uid>` | deleted | deleted | deleted | | `users/<uid>/sub/s1` | deleted | **left behind** | deleted | | `things/t-<uid>` (`uid` field, auto-discovery) | deleted | **left behind** | deleted | | control doc | kept | kept | kept | The kit before logged `firestoreDeleteMode: "RECURSIVE"`, `enableAutoDiscovery: false` and a non-recursive delete. Unit tests: `vitest run` passes (16 files, 165 tests), including every option label being accepted and a blank required param plus an invalid value being reported in one error. Prettier passes on the changed files. `tsc` passes, but only with a temporarily available `@types/node`: on `kits`, `pnpm build` fails with `TS2688: Cannot find type definition file for 'node'` because `@types/node` isn't installed, which this change doesn't cause. Other kits read `.env` the same way and probably have the same gap.
…NT_FILTER_LEVEL An invalid SHARP_OPTIONS is now rejected when the module loads, so it no longer reaches the handler's error logging.
…error-test test(storage-resize-images): fix the config-load error test
…ION_DEFAULT_REGION (#3277) Sets the region on the kit's three functions from `FUNCTION_DEFAULT_REGION` (default `us-central1`), so they deploy where the extension did. Before, the kit set no region and the Firebase CLI put them in `us-east1`, while the README said `us-central1`. Fixes #3252 (part of #3249). | | Extension | Kit before | Kit after | |---|---|---|---| | Region with nothing set | `us-central1` | `us-east1` | `us-central1` | | Region per instance | yes, chosen at install | only with a `setGlobalOptions({ region })` entry file, like the one `kits:install` generates | yes, `FUNCTION_DEFAULT_REGION` in each instance's `.env` | | `setGlobalOptions({ region })` moves the functions | n/a | yes | no | ## Changes - `src/config.ts`: a new `FUNCTION_DEFAULT_REGION` string param ("Cloud Functions location", default `us-central1`). It's the name `firebase functions:kits:install` and `ext:migrate` already use, so a migrated instance keeps its extension's region, and each instance can have its own region. - `src/index.ts`: `clearData`, `handleSearch` and `handleDeletion` take their `region` from it. Because the region is set on each function, `setGlobalOptions({ region })` no longer moves them. - README: a row in the config table, and the "Functions deploy to …" section now describes `FUNCTION_DEFAULT_REGION`, says to keep the functions in the Firestore database's region, and says `setGlobalOptions({ region })` doesn't apply. - Tests: `tests/region.test.ts` checks all three functions read `FUNCTION_DEFAULT_REGION` with default `us-central1`; `tests/index.test.ts` now expects the kit's region over a global one. - CHANGELOG entry. ## Testing Deployed this branch (4433882) to a test project with firebase-tools 15.31.0, using the README's setup (an entry file that re-exports the three functions) unless noted. Each instance had `FIRESTORE_PATHS=r77-<instance>/{UID}`. For the deletion check, I wrote a doc at each instance's path, deleted an Auth user, and waited for the docs to go. | Setup | `FUNCTION_DEFAULT_REGION` | Deployed to | User data deleted | |---|---|---|---| | New instance | `us-central1` | `us-central1` | yes (10s) | | New instance | `europe-west2` | `europe-west2` | yes (6s) | | New instance | not in `.env` | deploy fails (non-interactive) | — | | `kits:install`-style entry file (its own `defineString("FUNCTION_DEFAULT_REGION")` + `setGlobalOptions({ region })`) | `europe-west2` | `europe-west2` | yes (6s) | | Kit from `kits`, for comparison | — | `us-east1` | yes (7s) | `vitest run`: 17 files, 166 tests pass. `tsc` still reports `TS2688: Cannot find type definition file for 'node'` on `kits` because `@types/node` isn't installed. This change doesn't cause that, and the output is emitted.
…1st gen limit (#3312) Defaults the kit's three functions to `maxInstances: 3000`, the extension's 1st gen limit, instead of the 2nd gen default of 100. Fixes #3311 (part of #3249). | | Extension | Kit before | Kit after | |---|---|---|---| | Max instances per function | 3000 | 100 | 3000 | | `setGlobalOptions({ maxInstances })` changes it | n/a | yes | yes | | `setGlobalOptions` changes concurrency, CPU or ingress | n/a | no | no | Function-level options win over `setGlobalOptions`, so the kit sets `maxInstances` only when no global value is set. Concurrency, CPU and ingress stay fixed. ## Changes - `src/index.ts`: defaults `maxInstances` to 3000 unless `setGlobalOptions` sets it. `getGlobalOptions` isn't in the `.d.ts`, so the kit reads it from the SDK's `globalThis` symbol. - README, tests and CHANGELOG updated. ## Testing - A 2nd gen function with the kit's defaults deployed to a test project with `maxInstances` 3000. - `vitest run`: 167 tests pass, including a global `maxInstances` overriding the default while a global `concurrency: 80` doesn't. - Not tested: a full kit deploy, or a burst of more than 100 events.
There was a problem hiding this comment.
Code Review
This pull request introduces Firebase Function Kits, specifically packaging the firestore-bigquery-export extension as a deployable npm package under the new kits/ directory, along with corresponding configuration updates, documentation, and comprehensive unit tests. The code review feedback is highly constructive and identifies several key improvements: mapping the missing asia3 multi-region to prevent deployment failures, recalculating the task retry jitter inside the loop to ensure proper randomized backoff, explicitly typing the wildcard resolution accumulator to prevent strict TypeScript compilation errors, and removing unused lodash dependencies from package.json.
# Conflicts: # README.md # firestore-bigquery-export/firestore-bigquery-change-tracker/package.json
cabljac
left a comment
There was a problem hiding this comment.
The kit source and tests match the kits branch; the only package differences are removal of the unused lodash dependencies.
Two things before merging:
- The build check fails during README generation with pnpm: not found. Can we install pnpm in that workflow or keep that step using npm?
- We need to check: do releases now come from next? The release workflow still checks out and pushes version commits to kits, so changes merged here won’t be what it publishes.
Brings the
firestore-bigquery-exportkit fromkitsintonext, without the other kits.kits(2a760638), then removed every kit underkits/exceptfirestore-bigquery-export.kits/README.md(the README'sfirebase.jsonexample now usesfirestore-bigquery-export).pnpm-lock.yaml. The old lockfile was out of date for this kit (firebase-admin^14.2.0 /firebase-functions^7.3.3-rc.2 vs ^14.4.0 / ^7.4.0 in itspackage.json), so that's fixed here too.