Add support for customizable precedence in Settings Module
<!--IssueSummary start--> <details> <summary> Everyone can contribute. [Help move this issue forward](https://handbook.gitlab.com/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows/#contributor-links) while earning points, leveling up and collecting rewards. </summary> - [Work on this issue](https://contributors.gitlab.com/manage-issue?action=work&projectId=278964&issueIid=479703) - [Close this issue](https://contributors.gitlab.com/manage-issue?action=close&projectId=278964&issueIid=479703) </details> <!--IssueSummary end--> MR: Pending ## Description Add support for customizable precedence in Settings Module. There may be cases where we want different settings in the settings module to have different precedence rules, and rather than be stuck with a one-size-fits-all, lets go ahead and add support for making the precedence rules configurable on a per-setting basis. This will have the additional benefit of further abstracting/standardizing the existing support for determining "relevant settings" for a given step, which currently relies on manual per-step logic and guard clauses. See related discussion in [this thread](https://gitlab.com/groups/gitlab-org/-/work_items/14186#note_2052379090). - See https://gitlab.com/groups/gitlab-org/-/epics/14186+ for overview and more context - See [Related Issues and MRs section in that epic](https://gitlab.com/groups/gitlab-org/-/epics/14186#related-issues-and-mrs) for related issues and MRs ## Acceptance Criteria - [ ] Precedence rules can be configured on a per-setting basis ## Technical Requirements Here is an initial idea of what this API might look like: ```ruby module RemoteDevelopment module Settings class DefaultSettings def self.default_settings { some_setting: { default_value: 1, type: Integer, sources: [SomeSettingsReader, SomeOtherSettingsReader] }, # ... } end end end end module RemoteDevelopment module Settings class SomeSettingsReader def self.read(context) err_result = nil SettingsBuilder.provide_settings_values(step_class: self, context: context) do |setting_name, values_from_previous_steps| # NOTE: values_from_previous_steps can be used if this step needs to know the values of other settings begin ClassToReadSomeSetting.read(setting_name) # read and return setting value from some source, to contribute to context rescue err_result = Gitlab::Fp::Result.err(SettingsSomeSettingsReadFailed.new(details: "Some failure for #{setting_name}")) break end # provide_settings_values will take the returned setting value, and add it to the list of "contributed" settings end return err_result if err_result Gitlab::Fp::Result.ok(context) end end end end module RemoteDevelopment module Settings class SettingsPrecedenceSorter # last step in the Settings Module ROP chain def self.sort(context) context[:settings] = SettingsBuilder.sort(context) # sort out the settings based on order of sources context end end end end ``` ## Design Requirements None, no UI changes.
issue