Skip to content

Global feature flags via environment variables#1158

Merged
3mcd merged 6 commits into
em/disabled-actionsfrom
em/flags
Apr 14, 2025
Merged

Global feature flags via environment variables#1158
3mcd merged 6 commits into
em/disabled-actionsfrom
em/flags

Conversation

@3mcd
Copy link
Copy Markdown
Collaborator

@3mcd 3mcd commented Apr 14, 2025

Issue(s) Resolved

Partial #1140

High-level Explanation of PR

This PR introduces a simple pattern for implementing global (i.e. not community-level) feature flags.

One would create a new feature flag by adding a tuple to the new flagSchema zod type in env.ts, where the first element of the tuple is a unique flag name, and the second element is the flag "args" or options. Default flag states/args are defined using Zod's .default method.

Turning a flag on or off is as simple as starting the app with FLAGS=flag-name:off. You can toggle multiple flags using a comma separated list, e.g. FLAGS=flag-1:off,flag-2:on.

Some flags may take slightly more complex options than just "off" or "on". For example, the disabled-actions flag has a transformer that parses the following flag expression:

disabled-actions:http+email

into

["http", "email"]

The state and/or arguments of a flag can be retrieved on the server like

env.FLAGS.get("disabled-actions") // ["http", "email"]
env.FLAGS.get("uploads") // false

The flags I've introduced here don't do anything yet. I intend to utilize them in the em/disabled-actions branch, and a small follow-up branch to disable file uploads and member invites in our sandbox environment.

Test Plan

  1. Start the app with FLAGS=uploads:off,invites:off. It should start successfully! (These flags don't do anything yet).
  2. Try running the app with an unsupported flag turned on or off. The app should fail to start with an environment error.
  3. Try running the app with an unsupported flag state, e.g. FLAGS=uploads:pancakes. The app should fail to start again.

Screenshots (if applicable)

Notes

Setting a feature flag currently doesn't have any effect, this PR just introduces the pattern.

@3mcd 3mcd changed the base branch from main to em/disabled-actions April 14, 2025 17:18
Comment thread core/lib/env/env.ts
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

All of the important changes are in this file!

Copy link
Copy Markdown
Contributor

@allisonking allisonking left a comment

Choose a reason for hiding this comment

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

worked as promised! although just a note that the check does not kick in on server reload. if I make my .env.local invalid, I'll get a message on the server that says "Reload env: .env.local" but the server will keep working fine. I think this is okay, but I guess means we can't dynamically swap out feature flags without restarting the server?

@3mcd
Copy link
Copy Markdown
Collaborator Author

3mcd commented Apr 14, 2025

@allisonking I'm not totally sure what's causing the issue with reloading. Because we'll probably have a more robust solution in the future (i.e. one that supports per-community settings), I think I'm okay with the limitation of a server restart for global feature flags for now!

@3mcd 3mcd merged commit 06ef9d1 into em/disabled-actions Apr 14, 2025
14 of 15 checks passed
@3mcd 3mcd deleted the em/flags branch April 14, 2025 20:54
3mcd added a commit that referenced this pull request Apr 15, 2025
* feat: disable specific actions using environment variable

* feat: validate disabled actions using action names

* Global feature flags via environment variables (#1158)

* feat: simple feature flagging via new FLAGS env var

* feat: use fflag for disabled actions

* fix: default to [] for disabled-actions

* fix: another stab at the env.FLAGS undefined problem

* refactor: move flags into separate module

* woops

* feat: use transformer again

* fix: test errors

* fix: try explicit mock

* test: try this

* fix: okay do this for now

* chore: cleanup
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