Skip to content

Conversation

@JPrevost
Copy link
Member

@JPrevost JPrevost commented Oct 23, 2025

Why are these changes being introduced:

  • FlipFlip has not been maintained in years and we believe it is causing
    more problems than it is solving. We need a simpler, more maintainable
    feature flag system.
  • Our needs are simple: we need to be able to turn features on and off
    based on environment variables.

Relevant ticket(s):

How does this address that need:

  • Created a simple Feature model that reads from environment variables
    to determine if a feature is enabled or not.
  • Created a FeaturesHelper module that provides convenience methods
    for checking if a feature is enabled.
  • Introduces consistent naming patterns for feature ENV variables.

Document any side effects to this change:

  • This only introduces the new feature flag system. No existing
    feature flags have been migrated yet and FlipFlip is still present.
  • Also introduces the Makefile from TACOS for common dev commands along with adding the gem yard to allow for documentation generation

Developer

Accessibility
  • ANDI or WAVE has been run in accordance to our guide.
  • This PR contains no changes to the view layer.
  • New issues flagged by ANDI or WAVE have been resolved.
  • New issues flagged by ANDI or WAVE have been ticketed (link in the Pull Request details above).
  • No new accessibility issues have been flagged.
New ENV
  • All new ENV is documented in README.
  • All new ENV has been added to Heroku Pipeline, Staging and Prod.
  • ENV has not changed (YET).
Approval beyond code review
  • UXWS/stakeholder approval has been confirmed.
  • UXWS/stakeholder review will be completed retroactively.
  • UXWS/stakeholder review is not needed.
Additional context needed to review

E.g., if the PR includes updated dependencies and/or data
migration, or how to confirm the feature is working.

Code Reviewer

Code
  • I have confirmed that the code works as intended.
  • Any CodeClimate issues have been fixed or confirmed as
    added technical debt.
Documentation
  • The commit message is clear and follows our guidelines
    (not just this pull request message).
  • The documentation has been updated or is unnecessary.
  • New dependencies are appropriate or there were no changes.
Testing
  • There are appropriate tests covering any new functionality.
  • No additional test coverage is required.

@mitlib mitlib temporarily deployed to timdex-ui-pi-use-77-fea-eekv0l October 23, 2025 12:41 Inactive
@jazairi jazairi self-assigned this Oct 23, 2025
Copy link
Contributor

@jazairi jazairi left a comment

Choose a reason for hiding this comment

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

This is a great foundation to get away from FlipFlip! I'm especially impressed with the documentation, which is thorough and easy to follow.

I noted a small typo and raised a question about the use of define_singleton_method. I'm not yet requesting a change on the latter, but I wanted to confirm the intention behind using that instead of define_method.

# Predefine convenience methods for each valid feature
# Allows for direct calls like feature_geodata?
Feature::VALID_FEATURES.each do |name|
define_singleton_method("feature_#{name}?") do
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this creates methods on the module itself, rather than instances. Is that the intended behavior? I.e., in the views, do we want to call if FeaturesHelper.feature_geodata? or if feature_geodata??

Copy link
Member Author

Choose a reason for hiding this comment

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

I was aiming for if feature_geodata?... I think this works that way but haven't checked in views. If it requires the full call then I think just ditching the Helper and using Feature.enabled?(:geodata) will be simpler. Let me confirm if it works the way I think it does and you can let me know if the intended syntax feels good or if we should just keep it simple and go with always using the model functions and ditch the Helper regardless :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Confirmed it works like I wanted (still open to ditching it entirely and just using views):

Example of what this allows

<% if @suggestions.present? && !feature_geodata? %>

Example of just ditching the Helper entirely:

<% if @suggestions.present? && !Feature.enabled?(:geodata) %>

I like the first but am worried that the inconsistency between how we call feature flags in Views vs Models may leads to us forgetting about the shorthand and always using the model version and not the helper over time 🤷🏻‍♂️

Copy link
Member Author

Choose a reason for hiding this comment

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

Alternative that I still sort of like (this doesn't work with this code but would be easy to swap to if we like it better):

<% if @suggestions.present? && !geodata_enabled? %>

Copy link
Contributor

@jazairi jazairi Oct 23, 2025

Choose a reason for hiding this comment

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

I think it works because it's falling back to method_missing, not using the predefined convenience methods. For example, modifying shared/_site_title like so renders the GeoData site title:

<% if FeaturesHelper.feature_geodata? %>
  <h2>Search for geospatial/GIS data</h2>
  <p id="site-desc">Find GIS data held at MIT and other institutions</p>
<% else %>
  <h2>Search the MIT Libraries</h2>
<% end %>

It also works as expected using Feature.enabled?(:geodata) and feature_geodata?, which I think are the two feature-flipping methods we want. However, if we remove this bit of code at the end of the helper, Feature.enabled?(:geodata) and feature_geodata? still work, but FeaturesHelper.feature_geodata? doesn't.

I'm still not sure I fully understand the intent, though, so a synchronous chat might be helpful!

@JPrevost JPrevost temporarily deployed to timdex-ui-pi-use-77-fea-eekv0l October 23, 2025 16:10 Inactive
Copy link
Contributor

@jazairi jazairi left a comment

Choose a reason for hiding this comment

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

As discussed in Slack, I'd like to propose removing the dynamic feature flag handling provided by FeaturesHelper. I'm open to retaining it, though, and I'll leave that call to you. If we do decide to retain it, let's remove lines 48-52 to avoid confusion.

@JPrevost JPrevost temporarily deployed to timdex-ui-pi-use-77-fea-eekv0l October 23, 2025 18:05 Inactive
@JPrevost JPrevost requested a review from jazairi October 23, 2025 18:06
# # In models/controllers:
# return unless Feature.enabled?(:geodata)
#
# # In views (using FeaturesHelper):
Copy link
Member Author

Choose a reason for hiding this comment

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

Doh, this mentions the helper that no longer exists.. I'll fixup the words and not just the example :)

@JPrevost JPrevost temporarily deployed to timdex-ui-pi-use-77-fea-eekv0l October 23, 2025 18:20 Inactive
Copy link
Contributor

@jazairi jazairi left a comment

Choose a reason for hiding this comment

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

Thanks for talking through this!

Why are these changes being introduced:

* FlipFlip has not been maintained in years and we believe it is causing
  more problems than it is solving. We need a simpler, more maintainable
  feature flag system.
* Our needs are simple: we need to be able to turn features on and off
  based on environment variables.

Relevant ticket(s):

* https://mitlibraries.atlassian.net/browse/USE-77

How does this address that need:

* Created a simple Feature model that reads from environment variables
  to determine if a feature is enabled or not.
* Introduces consistent naming patterns for feature ENV variables.

Document any side effects to this change:

* This only introduces the new feature flag system. No existing
  feature flags have been migrated yet and FlipFlip is still present.
@JPrevost JPrevost force-pushed the use-77-feature-flags branch from 7b00392 to a5d6666 Compare October 23, 2025 19:50
@JPrevost JPrevost temporarily deployed to timdex-ui-pi-use-77-fea-eekv0l October 23, 2025 19:51 Inactive
@JPrevost JPrevost merged commit 5478181 into main Oct 23, 2025
5 of 6 checks passed
@JPrevost JPrevost deleted the use-77-feature-flags branch October 23, 2025 19:52
@coveralls
Copy link

Pull Request Test Coverage Report for Build 18760201952

Details

  • 5 of 5 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.01%) to 98.311%

Totals Coverage Status
Change from base Build 18750605528: 0.01%
Covered Lines: 815
Relevant Lines: 829

💛 - Coveralls

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.

5 participants