Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: flag resolver should use stricter types #2571

Merged
merged 6 commits into from Dec 20, 2022

Conversation

nunogois
Copy link
Member

Adding stricter types to FlagResolver can possibly help improve our DX - Help us prevent errors like typos, guide us to correctly add a flag when needed, and warn us of stray checks whenever we do a clean up at a later stage.

@vercel
Copy link

vercel bot commented Nov 30, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated
unleash-monorepo-frontend ✅ Ready (Inspect) Visit Preview 💬 Add your feedback Dec 16, 2022 at 6:31PM (UTC)
1 Ignored Deployment
Name Status Preview Comments Updated
unleash-docs ⬜️ Ignored (Inspect) Dec 16, 2022 at 6:31PM (UTC)

@@ -112,6 +112,7 @@ class AdminApi extends Controller {
this.app.use(
'/invite-link',
conditionalMiddleware(
// @ts-expect-error
() => config.flagResolver.isEnabled('publicSignup'),
Copy link
Member Author

@nunogois nunogois Nov 30, 2022

Choose a reason for hiding this comment

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

One of the strays caught by the PR - Maybe it's a check we should clean up? Or, on the other hand, correctly add to the remaining feature flags?

Copy link
Contributor

Choose a reason for hiding this comment

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

This should be removed. @Tymek We might have missed this one when cleaning up?

@nunogois nunogois marked this pull request as ready for review November 30, 2022 11:35
@@ -64,15 +65,17 @@ export const defaultExperimentalOptions = {

export interface IExperimentalOptions {
flags: {
[key: string]: boolean;
E?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

It it supposed to be some generic or a typo?

Copy link
Member Author

Choose a reason for hiding this comment

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

Discussed in: https://unleash-internal.slack.com/archives/C046LV6HH6W/p1669880769980979 - Needed to include this option since it's being passed in:

function loadUI(options: IUnleashOptions): IUIConfig {
const uiO = options.ui || {};
const ui: IUIConfig = {
environment: 'Open Source',
};
ui.flags = {
E: true,
ENABLE_DARK_MODE_SUPPORT: false,
};
return mergeAll([ui, uiO]);
}

@@ -14,9 +14,11 @@ test('should produce UI flags with extra dynamic flags', () => {
...defaultExperimentalOptions,
flags: { extraFlag: false },
};
// @ts-expect-error
Copy link
Contributor

Choose a reason for hiding this comment

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

can we get rid of those?

Copy link
Contributor

Choose a reason for hiding this comment

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

e.g. const resolver = new FlagResolver(config as IExperimentalOptions);

Copy link
Contributor

Choose a reason for hiding this comment

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

casting seems to be more idiomatic in TS tests than expecting errors

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, addressed in e226e30.

Copy link
Contributor

@kwasniew kwasniew left a comment

Choose a reason for hiding this comment

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

questions inline

@nunogois nunogois force-pushed the refactor-flagresolver-stricter-types branch from d5af045 to e226e30 Compare December 2, 2022 14:04
@nunogois nunogois enabled auto-merge (squash) December 2, 2022 14:18
@FredrikOseberg
Copy link
Contributor

Before we merge this, will this break enterprise and cloud builds since they don't explicitly type? We should at least be aware that this can happen and update these in quick succession.

@FredrikOseberg
Copy link
Contributor

Thinking a bit more about this, the IFlagKey type might be too limiting. If we only allow the flags defined in unleash, then the external flag provider has to implement an interface that only allows these flags. This can be problematic when we have flags that we want to define outside of unleash. For example, what if we wanted to have a feature flag specifically for unleash-cloud or unleash-enterprise? One specific example that comes to mind is change requests, which is a flag that is not in experimental options in unleash, because it's only used in enterprise. I think we need to consider a less restrictive type, but one that still allows the autocompletion. There should be a possibility to a looser type using the index access type of an object.

@nunogois
Copy link
Member Author

nunogois commented Dec 5, 2022

Hey @FredrikOseberg,

Before we merge this, will this break enterprise and cloud builds since they don't explicitly type? We should at least be aware that this can happen and update these in quick succession.

A quick test locally seemed to work as intended, but it would be great if you could have a look as well just to double check.

Thinking a bit more about this, the IFlagKey type might be too limiting. If we only allow the flags defined in unleash, then the external flag provider has to implement an interface that only allows these flags. This can be problematic when we have flags that we want to define outside of unleash. For example, what if we wanted to have a feature flag specifically for unleash-cloud or unleash-enterprise? One specific example that comes to mind is change requests, which is a flag that is not in experimental options in unleash, because it's only used in enterprise. I think we need to consider a less restrictive type, but one that still allows the autocompletion. There should be a possibility to a looser type using the index access type of an object.

Seems like changeRequests is already part of experimental options in Unleash, even if it's an enterprise only feature:

changeRequests?: boolean;

This seems like the right approach to me.

A looser type would also mean we would lose some things, like easily catching a stray like this: #2571 (comment)

You would still have these options:

  • Adding the feature flag to Unleash so it's known, which is the ideal route;
  • Casting your flag string as IFlagKey for specific scenarios like tests;
  • // @ts-expect-erroring the line, which should be avoided;

This flow seems better to me and more explicit than what we had before, WDYT?

@nunogois nunogois force-pushed the refactor-flagresolver-stricter-types branch from 78cb843 to b82c679 Compare December 5, 2022 11:53
@nunogois nunogois force-pushed the refactor-flagresolver-stricter-types branch from b82c679 to fbdce30 Compare December 12, 2022 15:05
@nunogois nunogois force-pushed the refactor-flagresolver-stricter-types branch from 0992672 to 0186683 Compare December 16, 2022 18:03
Copy link
Contributor

@FredrikOseberg FredrikOseberg left a comment

Choose a reason for hiding this comment

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

LGTM for now. If we discover any limitations we could always go back.

Copy link
Contributor

@chriswk chriswk left a comment

Choose a reason for hiding this comment

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

I like that this should allow us to see which features are enabled, and what our legal keys to use are, rather than like what we have now, where you could theoretically just ask for any key.

The disadvantage is of course that we have to remember to code it in here, rather than having to just add a feature toggle in the Unleash Hosted UI. I find that I like the trade-off.

But would really like someone else to chime in as well.

Also, this looks quite like Cognite's way of doing the Rust client, where you need your feature key in an enum to be able to query for its enabled status. When writing tools like Edge and the proxy, it's a hindrance, but when using in our own controlled App, having a type that catches typos and non-existing toggles is 👍 for me

@nunogois nunogois merged commit 7ce5b3d into main Dec 20, 2022
@nunogois nunogois deleted the refactor-flagresolver-stricter-types branch December 20, 2022 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

4 participants