Skip to content

Releases: deftinc/feature_gate

v0.2.0

Choose a tag to compare

@thephw thephw released this 27 Oct 20:01
132c459

Per-actor feature flags (#24)

Turn a flag on for particular users or groups without enabling it for everyone.

client.enable_actor("new_ui", "user:42")    # or any object with a feature_gate_id attribute
client.disable_actor("new_ui", "org:7")
client.actors("new_ui")                     # ids in the order they were added
client.is_enabled("new_ui", user, user.org) # globally on, or on for any actor passed
  • Actors are namespaced strings ("user:42", "org:7") or objects with a feature_gate_id attribute. Bare integers are rejected so user 42 and org 42 can't collide. is_enabled skips None actors.
  • is_enabled(key, *actors) is true when the flag is on globally or for any actor passed. Pass a user together with their groups.
  • disable() only turns off the global switch; actors keep the flag until disable_actor().
  • PostgresAdapter: new <prefix>feature_actors table (migration 0002_create_feature_actors).
  • PosthogAdapter: actors are stored as a distinct_id release condition on the flag and evaluated by feature_gate. Other conditions you set up in PostHog are left alone, and enable_actor raises ValueError rather than activating an inactive flag that has them. Behavior without actors is unchanged.
  • See the Actors section of the README.

Upgrading

  • PostgresAdapter users: run feature-gate-migrate after upgrading. is_enabled(key) without actors keeps working until you do, but the actor methods need the new table.
  • On PostHog, disable() on a flag with actors keeps the flag active for those actors, so any other conditions on it keep running.

Full Changelog: v0.1.1...v0.2.0

v0.1.1

Choose a tag to compare

@thephw thephw released this 26 Oct 23:38
a4cf84d

Configurable logging with opt-in structured JSON logs (#21)

  • Every adapter (MemoryAdapter, PostgresAdapter, PosthogAdapter) and PosthogAPIClient takes a logger= argument. It defaults to structlog.get_logger(), so logs follow your application's structlog configuration.
  • feature_gate no longer calls structlog.configure, so creating an adapter no longer replaces your app's structlog config.
  • New feature_gate.structured_logging module for JSON logs:
    • json_logger(file=None): JSON-lines logger (stdout by default) to pass as logger=.
    • PROCESSORS: use with structlog.configure(processors=PROCESSORS) to render your whole app as JSON.
  • See the Logging section of the README.

Breaking changes

  • MemoryAdapter no longer writes ./logs/feature_gate.log, and PosthogAPIClient no longer writes $PROJECT_ROOT/logs/development.log; PROJECT_ROOT is no longer used. To keep a log file, pass logger=json_logger(open("logs/feature_gate.log", "a")).
  • Logs render however your app has configured structlog (structlog's console output if unconfigured) rather than always as JSON.

This is the first release with these changes on PyPI. 0.1.0 was never published there (PyPI blocks that filename from an earlier deleted upload).

Full Changelog: v0.0.9...v0.1.1

v0.0.9

Choose a tag to compare

@thephw thephw released this 22 Oct 21:01
dd1f07c

What's changed

New: PostgreSQL adapter

  • PostgresAdapter stores feature flags in your own PostgreSQL database. Install it with pip install "feature_gate[postgres]" (psycopg 3). psycopg is only imported when you use this adapter, so MemoryAdapter and PosthogAdapter work without it.
    • Configure it with PostgresAdapter(database_url=...), or FEATURE_GATE_DATABASE_URL, falling back to DATABASE_URL. You can also pass an existing psycopg connection; if it's already inside a transaction, the adapter's writes become part of it.
    • Behaves like MemoryAdapter: adding a flag that already exists is harmless, a missing key raises FeatureNotFound, and features() returns flags in the order they were added.
  • feature-gate-migrate command creates and updates the adapter's tables on your database. Running it again only applies new migrations, and a PostgreSQL advisory lock stops two deploys from migrating at the same time. You can also call it from Python as feature_gate.migrate.migrate(connection).
  • Configurable table prefix, defaulting to feature_gate_. Set it with table_prefix=, --table-prefix or FEATURE_GATE_TABLE_PREFIX. The migrations and the adapter must use the same prefix.
  • Feature IDs are UUIDv7s, created by a <prefix>uuidv7() function the migration adds, so PostgreSQL 13 and later are supported. The full schema is in the README.

Compatibility

  • PostgreSQL 13+ for the new adapter. CI tests it on PostgreSQL 16 and 18.
  • Python support is unchanged (3.10+). CI runs the suite on 3.10 and 3.15.

Development & packaging

  • New CI workflow runs the test suite on every pull request, on Python 3.10 and 3.15 against PostgreSQL 16 and 18.
  • The publish workflow now runs the PostgreSQL tests against a postgres:16 service before publishing.
  • PostgreSQL tests run locally when FEATURE_GATE_TEST_DATABASE_URL is set; otherwise they're skipped.

Full changelog: v0.0.8...v0.0.9

v0.0.8

Choose a tag to compare

@thephw thephw released this 22 Oct 20:24
8837596

What's changed

⚠️ Behavior change

  • Default PostHog host is now https://us.posthog.com (previously the legacy https://app.posthog.com). If you're on EU Cloud, set POSTHOG_API_BASE=https://eu.posthog.com; self-hosted users should set it to their own domain. POSTHOG_API_KEY must be a personal API key with the feature_flag:read and feature_flag:write scopes.

Fixes

  • from feature_gate.adapters import PosthogAdapter, MemoryAdapter now works as documented in the README.
  • MemoryAdapter.add no longer creates duplicate features when the same key is added twice.
  • FeatureNotFound messages now include the feature key instead of the literal text {feature_key}.
  • reload.py reloads the correct posthog_api_client module.

Compatibility

  • Tested on Python 3.10 through 3.15.
  • Minimum dependency versions raised to structlog>=26.1.0 and requests>=2.34.2.

Development & packaging

  • Replaced Poetry with uv. Python 3.15.1 and uv 0.13.5 are pinned in .tool-versions and installed with asdf. Builds use hatchling.
  • bin/bootstrap, bin/update, bin/ci and bin/repl now use uv sync / uv run and work with asdf 0.16+.
  • The publish workflow now runs the test suite before uv build and uv publish.

Full changelog: v0.0.7...v0.0.8

v0.0.7

Choose a tag to compare

@vinbarnes vinbarnes released this 07 Jun 14:31

What's Changed

  • Add logging for Client's public API calls by @vinbarnes in #14
  • add is_enabled test for the case when rate limiting error is returned by @vinbarnes in #16

Full Changelog: v0.0.6...v0.0.7

v0.0.6

Choose a tag to compare

@vinbarnes vinbarnes released this 06 Jun 15:07

What's Changed

Full Changelog: v0.0.5...v0.0.6

better handling of upstream posthog errors

Choose a tag to compare

@vinbarnes vinbarnes released this 11 Apr 13:27

What's Changed

  • fix KeyError by providing empty dict as default value by @vinbarnes in #10

Full Changelog: v0.0.4...v0.0.5

Better Logs

Choose a tag to compare

@thephw thephw released this 13 Mar 16:39
c6fb096

Changelog

  • Make sure to create the logs directory and the log file
  • Rename the log file to feature_gate.log

Move logs to log/development.log

Choose a tag to compare

@thephw thephw released this 27 Feb 17:39
e44ff00

Changelog

  • Merge #8 -- Store logs in log directory