{"id":15151251,"url":"https://github.com/servactory/featury","last_synced_at":"2026-03-06T23:32:25.530Z","repository":{"id":245526622,"uuid":"817856824","full_name":"servactory/featury","owner":"servactory","description":"Managing Ruby application features","archived":false,"fork":false,"pushed_at":"2025-11-30T18:23:03.000Z","size":133,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-27T05:59:15.845Z","etag":null,"topics":["configs","features","managing-features","rails","ruby","ruby-on-rails","settings"],"latest_commit_sha":null,"homepage":"https://featury.servactory.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/servactory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-20T15:24:46.000Z","updated_at":"2025-11-30T18:23:05.000Z","dependencies_parsed_at":"2024-09-02T15:24:44.152Z","dependency_job_id":"de78afbc-740e-41cd-8dd0-9ec41a58db02","html_url":"https://github.com/servactory/featury","commit_stats":null,"previous_names":["servactory/featury"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/servactory/featury","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/servactory%2Ffeatury","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/servactory%2Ffeatury/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/servactory%2Ffeatury/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/servactory%2Ffeatury/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/servactory","download_url":"https://codeload.github.com/servactory/featury/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/servactory%2Ffeatury/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30203348,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configs","features","managing-features","rails","ruby","ruby-on-rails","settings"],"created_at":"2024-09-26T15:01:11.718Z","updated_at":"2026-03-06T23:32:25.522Z","avatar_url":"https://github.com/servactory.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://servactory.com\" target=\"_blank\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/servactory/featury/main/.github/logo-dark.svg\"\u003e\n      \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/servactory/featury/main/.github/logo-light.svg\"\u003e\n      \u003cimg alt=\"Featury\" src=\"https://raw.githubusercontent.com/servactory/featury/main/.github/logo-light.svg\" width=\"350\" height=\"70\" style=\"max-width: 100%;\"\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://rubygems.org/gems/featury\"\u003e\u003cimg src=\"https://img.shields.io/gem/v/featury?logo=rubygems\u0026logoColor=fff\" alt=\"Gem version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/servactory/featury/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/release-date/servactory/featury\" alt=\"Release Date\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## 📚 Documentation\n\nSee [featury.servactory.com](https://featury.servactory.com) for comprehensive guides and API documentation.\n\nComplete documentation is also available in the [docs](./docs) directory:\n\n- [Getting Started](./docs/getting-started.md)\n- [Features](./docs/features.md)\n- [Groups](./docs/groups.md)\n- [Actions](./docs/actions.md)\n- [Resources](./docs/resources.md)\n- [Conditions](./docs/conditions.md)\n- [Working with Features](./docs/working-with-features.md)\n- [Info and Introspection](./docs/info-and-introspection.md)\n- [Integration](./docs/integration.md)\n- [Examples](./docs/examples.md)\n- [Best Practices](./docs/best-practices.md)\n\n## 💡 Why Featury?\n\n- 🎯 **Unified Feature Management** — Group and manage multiple feature flags through a single interface with automatic prefix handling\n- 🔌 **Flexible Integration** — Works with any backend: Flipper, Redis, databases, HTTP APIs, or custom solutions\n- 🗂️ **Powerful Organization** — Organize features with prefixes, groups, and nested hierarchies for scalable feature management\n- 🔍 **Rich Introspection** — Full visibility into features, actions, and resources through the comprehensive info API\n- 🪝 **Lifecycle Hooks** — Before/after callbacks for actions with customizable scope and full context access\n- 🛡️ **Type-Safe Resources** — Built on Servactory for robust resource validation, type checking, and automatic coercion\n\n## 🚀 Quick Start\n\n### Installation\n\nAdd Featury to your Gemfile:\n\n```ruby\ngem \"featury\"\n```\n\n### ApplicationFeature\n\nCreate a base class that defines how features interact with your feature flag system:\n\n```ruby\nclass ApplicationFeature \u003c Featury::Base\n  action :enabled?, web: :enabled? do |features:, **options|\n    features.all? { |feature| Flipper.enabled?(feature, *options.values) }\n  end\n\n  action :disabled?, web: :regular do |features:, **options|\n    features.any? { |feature| !Flipper.enabled?(feature, *options.values) }\n  end\n\n  action :enable, web: :enable do |features:, **options|\n    features.all? { |feature| Flipper.enable(feature, *options.values) }\n  end\n\n  action :disable, web: :disable do |features:, **options|\n    features.all? { |feature| Flipper.disable(feature, *options.values) }\n  end\n\n  action :add, web: :regular do |features:, **options|\n    features.all? { |feature| Flipper.add(feature, *options.values) }\n  end\n\n  before do |action:, features:|\n    Slack::API::Notify.call!(action:, features:)\n  end\n\n  after :enabled?, :disabled? do |action:, features:|\n    Slack::API::Notify.call!(action:, features:)\n  end\nend\n```\n\n### Feature Definitions\n\nDefine features with prefixes, resources, conditions, and groups:\n\n```ruby\nclass User::OnboardingFeature \u003c ApplicationFeature\n  prefix :user_onboarding\n\n  resource :user, type: User\n\n  condition -\u003e(resources:) { resources.user.onboarding_awaiting? }\n\n  feature :passage, description: \"User onboarding passage feature\" # =\u003e :user_onboarding_passage\n\n  group BillingFeature, description: \"Billing functionality group\"\n  group PaymentSystemFeature, description: \"Payment system functionality group\"\nend\n```\n\n```ruby\nclass BillingFeature \u003c ApplicationFeature\n  prefix :billing\n\n  feature :api, description: \"Billing API feature\"        # =\u003e :billing_api\n  feature :webhooks, description: \"Billing webhooks feature\"    # =\u003e :billing_webhooks\nend\n```\n\n```ruby\nclass PaymentSystemFeature \u003c ApplicationFeature\n  prefix :payment_system\n\n  feature :api, description: \"Payment system API feature\"      # =\u003e :payment_system_api\n  feature :webhooks, description: \"Payment system webhooks feature\"  # =\u003e :payment_system_webhooks\nend\n```\n\n### Usage\n\n```ruby\n# Direct method calls\nUser::OnboardingFeature.enabled?(user:) # =\u003e true\nUser::OnboardingFeature.enable(user:)   # =\u003e true\nUser::OnboardingFeature.disable(user:)  # =\u003e true\n\n# Using .with() method\nfeature = User::OnboardingFeature.with(user:)\nfeature.enabled? # =\u003e true\nfeature.enable   # =\u003e true\nfeature.disable  # =\u003e true\n```\n\n## 🤝 Contributing\n\nThis project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./CONTRIBUTING.md) as well.\n\n## 🙏 Acknowledgments\n\nFeatury is built and maintained by amazing [contributors](https://github.com/servactory/featury/graphs/contributors).\n\n## 📄 License\n\nFeatury is available as open source under the terms of the [MIT License](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fservactory%2Ffeatury","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fservactory%2Ffeatury","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fservactory%2Ffeatury/lists"}