Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions kits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Firebase Functions codebase and deploy into your own project.
While an extension is installed as a managed instance configured through the
Firebase console or CLI, a kit is code you own: you install the package, export
the functions you want from your functions entry file, configure it with a
`.env`, and deploy with `firebase deploy`. There is no hosted version, so the
functions run in your project, under your service account, on your deployment
schedule. That also means you can read the source, fork it, or import the
package's `./lib` entry point and register the triggers yourself.
`.env.<projectId>` file, and deploy with `firebase deploy`. There is no hosted
version, so the functions run in your project, under your service account, on
your deployment schedule. That also means you can read the source, fork it, or
import the package's `./lib` entry point and register the triggers yourself.

Each directory here contains the source code for a kit and a README explaining
how it works, including the roles it needs, the settings it reads, and the
Expand Down Expand Up @@ -63,10 +63,16 @@ instances to deploy:
}
```

Each instance ID maps to the directory holding that instance's `.env`, and the
CLI prefixes every function name with `kit-<instance-id>-`, so one kit can run
several independently configured instances side by side. See each kit's README
for its exports, its settings, and the roles the CLI grants on deploy.
Each instance ID maps to the directory holding that instance's
`.env.<projectId>` file, and the CLI prefixes every function name with
`kit-<instance-id>-`, so one kit can run several independently configured
instances side by side. See each kit's README for its exports, its settings, and
the roles the CLI grants on deploy.

Use a `.env.<projectId>` file rather than a plain `.env`.
`firebase functions:kits:uninstall` only deletes what is deployed to a project
with a `.env.<projectId>` file; with a plain `.env` it removes the instance from
`firebase.json` but leaves its functions running.

## Migrating from an extension

Expand Down
2 changes: 2 additions & 0 deletions kits/delete-user-data/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- fix: the README now recommends `.env.<projectId>` for instance config and has an Uninstall section. `firebase functions:kits:uninstall` only deletes deployed resources for a project with a `.env.<projectId>` file, so with the plain `.env` the README suggested before, it removed the instance from `firebase.json` and exited without an error but left the functions running and deleting user data. The new section also covers the Pub/Sub topics and IAM role bindings that uninstall leaves behind.
Comment thread
CorieW marked this conversation as resolved.
Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Nit: "Fixes #3262" in the PR description will close the issue before its firebase-tools half is fixed. Use "Part of #3262", or file the firebase-tools issue and link it.


- fix: `EXT_SELECTED_EVENTS` is validated at deploy, as the extension's install did. firebase-admin splits the list on commas without trimming, so `a, b, c` published only `a` and silently dropped the rest, and a type with different case or a typo was dropped without a warning. The deploy now fails if an entry has spaces or different case, isn't one of the three event types, or is listed twice. It also fails if event types are listed without `EVENTARC_CHANNEL`, or the channel isn't a full `projects/<project id>/locations/<location>/channels/<channel id>` name in this project and a location the extension supported (`us-central1`, `us-west1`, `europe-west4` or `asia-northeast1`); before, events were silently turned off. Empty entries are still skipped, and an unset or empty value still publishes nothing.

- fix: `clearData`, `handleSearch` and `handleDeletion` can scale to 3000 instances each again, as the extension's 1st gen functions could. The kit set no `maxInstances`, so each function took the 2nd gen default of 100, and with one event per instance it handled at most 100 deletions or searches at once. `setGlobalOptions({ maxInstances })` still overrides it. Existing kit deployments switch on their next deploy.
Expand Down
85 changes: 75 additions & 10 deletions kits/delete-user-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ export {
} from "@firebase-function-kits/delete-user-data";
```

and configure with a `.env` (or `.env.<projectId>`).
and configure it in a `.env.<projectId>` file (see [Uninstall](#uninstall) for
why not a plain `.env`).
Comment thread
CorieW marked this conversation as resolved.
Resolved

Importing the package without exporting its functions deploys nothing — the CLI
only deploys what your entry file exports.
Expand All @@ -79,7 +80,7 @@ later, behind the `kits` experiment — earlier CLIs do not provide the
```

`instances` maps each instance id to the directory (relative to
`firebase.json`) holding that instance's `.env`. The CLI prefixes every
`firebase.json`) holding that instance's `.env.<projectId>`. The CLI prefixes every
function and task queue name with `kit-<instance id>-`, so the functions above
deploy as `kit-default-clearData`, `kit-default-handleSearch`, and
`kit-default-handleDeletion`.
Expand All @@ -93,10 +94,12 @@ Deploy a single instance with `firebase deploy --only functions:<instance id>`.

## Configuration

Set these values in a `.env` (or `.env.<projectId>`) file. The Firebase CLI
loads them at deploy time and prompts for any required values that are missing.
Set these values in a `.env.<projectId>` file, such as `.env.my-project`. The
Firebase CLI loads them at deploy time and prompts for any required values that
are missing. A plain `.env` deploys the same way, but
`functions:kits:uninstall` ignores it (see [Uninstall](#uninstall)).
Comment thread
CorieW marked this conversation as resolved.
Resolved

The CLI does not check values that are already in `.env`, so the kit checks
The CLI does not check values that are already in the file, so the kit checks
them itself when the deploy loads it, as the extension did at install time. The
deploy fails with an error naming the setting if `FIRESTORE_DELETE_MODE`,
`ENABLE_AUTO_DISCOVERY` or `SELECTED_DATABASE_LOCATION` is not one of the
Expand Down Expand Up @@ -140,7 +143,7 @@ overridden there.
## Multiple instances

To run several deletion pipelines, add one entry per instance to the `instances`
map, each pointing at its own config directory with its own `.env`:
map, each pointing at its own config directory with its own `.env.<projectId>`:

```json
{
Expand All @@ -167,7 +170,7 @@ in sync by hand.

The functions can publish deletion events for each backend under
`firebase.extensions.delete-user-data.v1.*` (`firestore`, `database`, and
`storage`). Set both of these in `.env` to turn them on:
`storage`). Set both of these in `.env.<projectId>` to turn them on:

| Env var | Description |
|---|---|
Expand All @@ -188,6 +191,68 @@ selected.
The channel must already exist. Deploying the kit does not create it, and
publishing to a missing channel logs a warning without failing the function.

## Uninstall

```sh
firebase functions:kits:uninstall --instance <instance id>
```
Comment thread
CorieW marked this conversation as resolved.
Resolved

This deletes the instance's functions, their triggers and Pub/Sub subscriptions,
and the service account the CLI created for them. It then removes the instance
from `firebase.json` and deletes its `.env.<projectId>` file. If it is the kit's
only instance, it removes the whole kit entry, leaving `"functions": []`.
Despite what the prompt says, it doesn't delete your functions source when the
kit is exported from your own codebase, as in [Usage](#usage).

The command asks you to confirm, twice if this is the kit's only instance. In a
non-interactive shell (CI, a script, any shell without a TTY, or when the CLI
detects an AI agent), add `--force`. Without it nothing is deleted: the command
exits 0 for the kit's only instance, and fails with `Command aborted.`
otherwise.

It only deletes what is deployed to a project with a `.env.<projectId>` file in
the instance's config directory. With only a plain `.env`, it still removes the
Comment thread
CorieW marked this conversation as resolved.
Resolved
instance from `firebase.json` and exits without an error, but the functions keep
running and keep deleting user data. Rename `.env` to `.env.<projectId>` before
you uninstall. If you already uninstalled with a plain `.env`, put the instance
(or, if it was the only one, the whole kit entry) back in `firebase.json`,
rename the file, and run the command again.

If the instance is deployed to more than one project, give each project its own
`.env.<projectId>` (copy a shared `.env`, don't rename it) and run the command
once per project with `--project <projectId>`. The instance stays in
`firebase.json` until the last project's file is gone.

Move any `.env.local` file (the emulator override) out of the instance's config
directory before you uninstall. Next to a plain `.env`, it makes the command
fail with "contains no .env file for current project". Next to
`.env.<projectId>`, the command deletes the functions but leaves the instance in
`firebase.json`, and running it again fails with that error.

Uninstalling the extension removed the same resources and kept its two Pub/Sub
Comment thread
CorieW marked this conversation as resolved.
Resolved
topics. The kit also keeps two things:

- The topics `kit-<instance id>-discovery` and `kit-<instance id>-deletion` (or
the names in `DISCOVERY_TOPIC_NAME` and `DELETION_TOPIC_NAME`). Delete them
with `gcloud pubsub topics delete <topic>`.
- The deleted service account's seven project roles, which the extension
removed. They no longer grant access, and show in your project's IAM policy
as members like
`deleted:serviceAccount:firebase-fn-<n>@<project id>.iam.gserviceaccount.com?uid=<n>`.
The account's name doesn't include the instance id, and other kits' deleted
accounts look the same, so note the `firebase-fn-<n>` account the uninstall
command prints ("The following managed service accounts will also be
deleted" or "Deleting managed service account"). List its roles with:

```sh
gcloud projects get-iam-policy <project id> --flatten="bindings[].members" --filter="bindings.members:deleted:serviceAccount:firebase-fn-<n>@" --format="value(bindings.role,bindings.members)"
```

and remove each one, one command per role, with
`gcloud projects remove-iam-policy-binding <project id> --member='<member>' --role=<role> --condition=None`.
Keep the quotes: the `?` in the member makes some shells, such as zsh, fail
with "no matches found".

## Differences from the Delete User Data extension

This kit is the extension repackaged as an npm package, but a few things behave
Expand Down Expand Up @@ -217,12 +282,12 @@ since one function publishes to a topic the other is triggered by.

The extension deployed to the location you picked at install time
(`us-central1` by default). The kit reads the region from
`FUNCTION_DEFAULT_REGION` in each instance's `.env`, also defaulting to
`FUNCTION_DEFAULT_REGION` in each instance's `.env.<projectId>`, also defaulting to
`us-central1`, so instances can deploy to different regions.
`firebase ext:migrate` writes it with the region the extension ran in.

```sh
# .env (or .env.<projectId>)
# .env.<projectId>
FUNCTION_DEFAULT_REGION=us-central1
```

Expand Down Expand Up @@ -308,7 +373,7 @@ using the bug template, with `delete-user-data kit` in the title. Include:
- The kit version (run `npm ls @firebase-function-kits/delete-user-data` in the
directory where you installed it), your `firebase-tools` version
(`firebase --version`) and Node.js version.
- Your configuration from your `.env` (or `.env.<projectId>`) file, with
- Your configuration from your `.env.<projectId>` (or `.env`) file, with
secrets and project details redacted.
- Steps to reproduce, the result you expected, and the result you got.
- Logs from the kit's functions in Cloud Logging (with their
Expand Down
Loading