diff --git a/ee/lib/remote_development/workspaces/reconcile/output/response_payload_builder.rb b/ee/lib/remote_development/workspaces/reconcile/output/response_payload_builder.rb index a731515d22b7c7dc0fea6fe42eeefbb4102019c1..5ff98387f1c0e5de4a3dc24ada96193e332e22ff 100644 --- a/ee/lib/remote_development/workspaces/reconcile/output/response_payload_builder.rb +++ b/ee/lib/remote_development/workspaces/reconcile/output/response_payload_builder.rb @@ -79,7 +79,7 @@ def self.config_to_apply(workspace:, update_type:, logger:) end desired_config_to_apply_array = workspace_resources.map do |resource| - YAML.dump(resource.deep_stringify_keys) + YAML.dump(Gitlab::Utils.deep_sort_hash(resource).deep_stringify_keys) end return unless desired_config_to_apply_array.present? diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb index a0df20c35a2f44909de834e4ff6bee85ddaf196c..e3dcd80082e8248288fec83b8c69f3985e70094f 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb @@ -568,8 +568,7 @@ let(:expected_workspace_rails_infos) { [expected_unprovisioned_workspace_rails_info] } - it 'returns proper response payload', - quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/457963' do + it 'returns proper response payload' do # verify initial states in db (sanity check of match between factory and fixtures) expect(unprovisioned_workspace.desired_state).to eq(desired_state) expect(unprovisioned_workspace.actual_state).to eq(actual_state) diff --git a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb index b49ad1346fdbe6a83c07ee9b465a7d752fe41193..8b501768acd77847a962fdf4d5df137bdcf87cbf 100644 --- a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb +++ b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb @@ -420,7 +420,7 @@ def create_config_to_apply_v3( resources << workspace_secret_file if include_all_resources resources.map do |resource| - YAML.dump(resource.deep_stringify_keys) + YAML.dump(Gitlab::Utils.deep_sort_hash(resource).deep_stringify_keys) end.join end @@ -525,7 +525,7 @@ def create_config_to_apply_v2( resources << workspace_secret_file if include_all_resources resources.map do |resource| - YAML.dump(resource.deep_stringify_keys) + YAML.dump(Gitlab::Utils.deep_sort_hash(resource).deep_stringify_keys) end.join end diff --git a/gems/gitlab-utils/lib/gitlab/utils.rb b/gems/gitlab-utils/lib/gitlab/utils.rb index 7f503ba279b2229f7a61afea9227a1a921db02d3..8ad4ad36b62ff18c66b3e400b95bbfc98467e7c4 100644 --- a/gems/gitlab-utils/lib/gitlab/utils.rb +++ b/gems/gitlab-utils/lib/gitlab/utils.rb @@ -311,5 +311,13 @@ def to_rails_log_level(input, fallback = nil) to_rails_log_level(fallback) end end + + # Use this method to recursively sort a hash on its keys + def deep_sort_hash(hash) + hash.keys.sort.each_with_object({}) do |key, sorted_hash| + value = hash[key] + sorted_hash[key] = value.is_a?(Hash) ? deep_sort_hash(value) : value + end + end end end diff --git a/gems/gitlab-utils/spec/gitlab/utils_spec.rb b/gems/gitlab-utils/spec/gitlab/utils_spec.rb index a728b73a3a320de18365a439be30669e8cf65c5d..68f346345c26b3a0d8a3f1813be1048efbf91b47 100644 --- a/gems/gitlab-utils/spec/gitlab/utils_spec.rb +++ b/gems/gitlab-utils/spec/gitlab/utils_spec.rb @@ -636,4 +636,39 @@ end end end + + describe '.deep_sort_hash' do + it 'recursively sorts a hash' do + hash = { + z: "record-z", + e: { y: "nested-record-y", a: "nested-record-a", b: "nested-record-b" }, + c: { + m: { + p: "doubly-nested-record-p", + o: "doubly-nested-record-o" + }, + k: { + v: "doubly-nested-record-v", + u: "doubly-nested-record-u" + } + } + } + expect(JSON.generate(described_class.deep_sort_hash(hash))).to eq(JSON.generate({ + c: { + k: { + u: "doubly-nested-record-u", + v: "doubly-nested-record-v" + }, + m: { + o: "doubly-nested-record-o", + p: "doubly-nested-record-p" + } + + }, + e: { a: "nested-record-a", b: "nested-record-b", + y: "nested-record-y" }, + z: "record-z" + })) + end + end end