Skip to content

Commit 795292d

Browse files
fix(featureFlags): resolve linearToggleEnabled through resolveFlag (Comfy-Org#15135)
## ELI-5 Nightly builds always turned the linear toggle on, no matter what. That "always on" check ran *before* the code that looks at `?ff=` URL overrides, `ff:` localStorage overrides, remote config, and the server flag — so on nightly none of those could ever turn it off. Now nightly is the *default* value fed into the normal resolution chain, so it stays on unless something explicitly says otherwise. ## Summary `linearToggleEnabled` short-circuited with `if (isNightly) return true` above its `resolveFlag(...)` call, so the session-override and dev-override layers (which live inside `resolveFlag`) were silently ignored on nightly builds. Passing `isNightly` as `resolveFlag`'s default instead keeps nightly on by default while letting every override layer work. ## Changes - **What**: `linearToggleEnabled` now resolves through `resolveFlag(LINEAR_TOGGLE_ENABLED, remoteConfig.value.linear_toggle_enabled, isNightly)` with no short-circuit. Tests updated for the new nightly behavior plus three new cases (remote-config `false`, server-served `false`, session override `false` over an enabled remote config). - **Breaking**: none. Off nightly, `isNightly` is `false`, which is byte-identical to the previous `false` default — production and stable behavior is unchanged. ## Review Focus Two intentional behavior deltas, both nightly-only: (1) `?ff=linear_toggle_enabled:false` and the `ff:` localStorage dev override now change the flag, so an employee can reproduce the non-nightly experience; (2) an explicitly-served `false` from remote config or the server flag now wins over the built-in nightly on. When nothing is served, `getServerFeature(LINEAR_TOGGLE_ENABLED, true)` returns the `true` default, so nightly stays on. The default is deliberately `isNightly` alone, **not** `isNightly || import.meta.env.DEV` as in the neighbouring `nodeLibraryEssentialsEnabled` getter — this flag has never defaulted on in dev and that is preserved. Judgment calls: the first existing test asserted `expect(api.getServerFeature).not.toHaveBeenCalled()`, which pinned the removed short-circuit; it is rewritten to assert the flag still resolves `true` and that `getServerFeature` is called with `(LINEAR_TOGGLE_ENABLED, true)`. `isNightly = false` was added to the `session override precedence` block's `afterEach` so the new nightly case there cannot leak into the auth-gated tests that follow. Verification: all four new/changed tests were confirmed red against the pre-change getter and green after (41 passed in `useFeatureFlags.test.ts`, 23 in `useWorkflowActionsMenu.test.ts` — the only non-test consumer). `pnpm typecheck`, oxfmt and eslint ran clean via the pre-commit hook. Co-authored-by: Christian Byrne <cbyrne@comfy.org>
1 parent a2603c5 commit 795292d

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

src/composables/useFeatureFlags.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,23 @@ describe('useFeatureFlags', () => {
148148
})
149149

150150
describe('linearToggleEnabled', () => {
151+
afterEach(() => {
152+
vi.mocked(distributionTypes).isNightly = false
153+
remoteConfig.value = {}
154+
})
155+
151156
it('should return true when isNightly is true', () => {
152157
vi.mocked(distributionTypes).isNightly = true
158+
vi.mocked(api.getServerFeature).mockImplementation(
159+
(_path, defaultValue) => defaultValue
160+
)
153161

154162
const { flags } = useFeatureFlags()
155163
expect(flags.linearToggleEnabled).toBe(true)
156-
expect(api.getServerFeature).not.toHaveBeenCalled()
164+
expect(api.getServerFeature).toHaveBeenCalledWith(
165+
ServerFeatureFlag.LINEAR_TOGGLE_ENABLED,
166+
true
167+
)
157168
})
158169

159170
it('should check remote config and server feature when isNightly is false', () => {
@@ -182,6 +193,30 @@ describe('useFeatureFlags', () => {
182193
const { flags } = useFeatureFlags()
183194
expect(flags.linearToggleEnabled).toBe(false)
184195
})
196+
197+
it('lets a remote config false turn off the nightly default', () => {
198+
vi.mocked(distributionTypes).isNightly = true
199+
remoteConfig.value = { linear_toggle_enabled: false }
200+
vi.mocked(api.getServerFeature).mockImplementation(
201+
(_path, defaultValue) => defaultValue
202+
)
203+
204+
const { flags } = useFeatureFlags()
205+
expect(flags.linearToggleEnabled).toBe(false)
206+
})
207+
208+
it('lets a served server false turn off the nightly default', () => {
209+
vi.mocked(distributionTypes).isNightly = true
210+
vi.mocked(api.getServerFeature).mockImplementation(
211+
(path, defaultValue) =>
212+
path === ServerFeatureFlag.LINEAR_TOGGLE_ENABLED
213+
? false
214+
: defaultValue
215+
)
216+
217+
const { flags } = useFeatureFlags()
218+
expect(flags.linearToggleEnabled).toBe(false)
219+
})
185220
})
186221

187222
describe('nodeLibraryEssentialsEnabled', () => {
@@ -595,6 +630,7 @@ describe('useFeatureFlags', () => {
595630
afterEach(() => {
596631
vi.mocked(getSessionOverride).mockReset()
597632
vi.mocked(distributionTypes).isCloud = false
633+
vi.mocked(distributionTypes).isNightly = false
598634
remoteConfigState.value = 'unloaded'
599635
cachedBillingControlEnabled.value = undefined
600636
remoteConfig.value = {}
@@ -627,6 +663,18 @@ describe('useFeatureFlags', () => {
627663
expect(flags.workflowSharingEnabled).toBe(false)
628664
})
629665

666+
it('turns the linear toggle off against an enabled remote config', () => {
667+
vi.mocked(distributionTypes).isNightly = true
668+
vi.mocked(getSessionOverride).mockImplementation((flagKey) =>
669+
flagKey === ServerFeatureFlag.LINEAR_TOGGLE_ENABLED ? false : undefined
670+
)
671+
remoteConfig.value = { linear_toggle_enabled: true }
672+
vi.mocked(api.getServerFeature).mockReturnValue(true)
673+
674+
const { flags } = useFeatureFlags()
675+
expect(flags.linearToggleEnabled).toBe(false)
676+
})
677+
630678
it('turns the node library essentials tab off against an enabled remote config', () => {
631679
vi.mocked(getSessionOverride).mockImplementation((flagKey) =>
632680
flagKey === ServerFeatureFlag.NODE_LIBRARY_ESSENTIALS_ENABLED

src/composables/useFeatureFlags.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,10 @@ export function useFeatureFlags() {
127127
)
128128
},
129129
get linearToggleEnabled() {
130-
if (isNightly) return true
131-
132130
return resolveFlag(
133131
ServerFeatureFlag.LINEAR_TOGGLE_ENABLED,
134132
remoteConfig.value.linear_toggle_enabled,
135-
false
133+
isNightly
136134
)
137135
},
138136
get partnerNodeGovernanceEnabled() {

0 commit comments

Comments
 (0)