-
Notifications
You must be signed in to change notification settings - Fork 91
feat: Normalize selector handling across sync, evaluation, and OFREP services #1815
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
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for polite-licorice-3db33c canceled.
|
Co-authored-by: aepfli <9987394+aepfli@users.noreply.github.com>
Co-authored-by: aepfli <9987394+aepfli@users.noreply.github.com>
|
/Gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request normalizes selector handling in the sync service to align with other services, prioritizing the Flagd-Selector header while maintaining backward compatibility with the request body selector. The changes are well-implemented and include comprehensive tests for all scenarios. My review includes a few suggestions to refactor the new logic and test code for improved maintainability and to reduce duplication.
| logs := observedLogs.All() | ||
| for _, log := range logs { | ||
| assert.NotContains(t, log.Message, "deprecated", "Should not log deprecation warning when using header") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic to verify that no deprecation warning was logged is duplicated across TestSyncHandler_SelectorHeaderTakesPrecedence and TestSyncHandler_FetchAllFlags_SelectorFromHeader. Consider extracting it into a shared helper function to improve code reuse and maintainability.
For example:
func assertNoDeprecationWarning(t *testing.T, logs *observer.ObservedLogs) {
t.Helper()
for _, entry := range logs.All() {
assert.NotContains(t, entry.Message, "deprecated", "Should not log deprecation warning")
}
}You could then call assertNoDeprecationWarning(t, observedLogs) in all relevant tests.
| logs := observedLogs.All() | ||
| require.Greater(t, len(logs), 0, "Expected at least one log entry") | ||
| found := false | ||
| for _, log := range logs { | ||
| if log.Level == zapcore.WarnLevel { | ||
| assert.Contains(t, log.Message, "deprecated", "Should log deprecation warning when using request body selector") | ||
| assert.Contains(t, log.Message, "Flagd-Selector", "Deprecation message should mention the header name") | ||
| found = true | ||
| break | ||
| } | ||
| } | ||
| assert.True(t, found, "Expected to find deprecation warning in logs") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic to verify the deprecation warning is duplicated in TestSyncHandler_FetchAllFlags_SelectorFromRequestBody. To improve maintainability and reduce code duplication, consider extracting this block into a shared helper function.
For example:
func assertDeprecationWarning(t *testing.T, logs *observer.ObservedLogs) {
t.Helper()
entries := logs.All()
require.NotEmpty(t, entries, "Expected at least one log entry")
found := false
for _, entry := range entries {
if entry.Level == zapcore.WarnLevel {
assert.Contains(t, entry.Message, "deprecated")
assert.Contains(t, entry.Message, "Flagd-Selector")
found = true
break
}
}
assert.True(t, found, "Expected to find deprecation warning in logs")
}You could then call assertDeprecationWarning(t, observedLogs) here and in the other test.
Co-authored-by: aepfli <9987394+aepfli@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Problem
Currently, flagd services have inconsistent handling of selectors:
selectorfield from the request bodyFlagd-SelectorheaderFlagd-SelectorheaderThis inconsistency makes the API surface less predictable and can lead to confusion for users.
Solution
This PR normalizes selector handling by updating the sync service to accept the
Flagd-Selectorheader as the primary method, aligning it with the evaluation and OFREP services. The implementation maintains full backward compatibility by falling back to the request body selector when the header is not present.Changes
Core Implementation
Modified
flagd/pkg/service/flag-sync/handler.go:getSelectorExpression()helper method that checks forFlagd-Selectorheader (via gRPC metadata) firstselectorfield if header is not presentSyncFlags()andFetchAllFlags()methodsTest Coverage
Added 5 comprehensive test cases in
handler_test.go:All existing tests continue to pass.
Migration Path
The change is fully backward compatible. Users can migrate at their convenience:
Current (deprecated):
Recommended:
Benefits
Flagd-Selectorheader patternBreaking Changes
None. The request body selector will be removed in a future major version (e.g., v2.0.0).
Related
Addresses #[issue_number]
Original prompt
Fixes #1814
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.