From ff9a04cea125a19d16fefa43a701c776c7f69657 Mon Sep 17 00:00:00 2001
From: Chris Truter <crisptrutski@users.noreply.github.com>
Date: Thu, 4 Jan 2024 12:09:46 +0200
Subject: [PATCH] Guard against version duplication (#33803) (#37237)

---
 bin/build/src/release/version_info.clj       | 20 +++++---
 bin/build/test/release/version_info_test.clj | 53 ++++++++++++--------
 2 files changed, 44 insertions(+), 29 deletions(-)

diff --git a/bin/build/src/release/version_info.clj b/bin/build/src/release/version_info.clj
index 0240d014ea3..11f05f0ade9 100644
--- a/bin/build/src/release/version_info.clj
+++ b/bin/build/src/release/version_info.clj
@@ -47,19 +47,25 @@
    ;; TODO -- these need to be curated a bit before publishing...
    :highlights (mapv :title (github/milestone-issues))})
 
+(defn- update-version-info [{:keys [latest] :as info} new-version-info]
+  (if (= (:version new-version-info) (:version latest))
+    ;; if the latest version has not changed, just return the current info
+    info
+    (-> info
+        ;; move the current `:latest` to the beginning of `:older`
+        (update :older (fn [older] (distinct (cons latest older))))
+        (assoc :latest new-version-info))))
+
 (defn- generate-version-info! []
   (let [filename (version-info-filename)
         tmpname  (tmp-version-info-filename)]
     (u/step (format "Generate %s" filename)
       (u/step (format "Delete and create %s" tmpname)
         (u/delete-file-if-exists! tmpname)
-        (let [{:keys [latest], :as info} (current-version-info)]
-          (spit tmpname (-> info
-                            ;; move the current `:latest` to the beginning of `:older`
-                            (update :older (fn [older]
-                                             (distinct (cons latest older))))
-                            (assoc :latest (info-for-new-version))
-                            json/generate-string)))))))
+          (let [current-info     (current-version-info)
+                new-version-info (info-for-new-version)
+                new-info         (update-version-info current-info new-version-info)]
+            (spit tmpname (json/generate-string new-info)))))))
 
 (defn- upload-version-info! []
   (u/step "Upload version info"
diff --git a/bin/build/test/release/version_info_test.clj b/bin/build/test/release/version_info_test.clj
index 44964cd948d..d639778b74c 100644
--- a/bin/build/test/release/version_info_test.clj
+++ b/bin/build/test/release/version_info_test.clj
@@ -17,34 +17,43 @@
    :patch      patch
    :highlights highlights})
 
+;; TODO -- can result in a flakey test if the date changes during this test run
 (def ^:private today (.format (DateTimeFormatter/ofPattern "yyyy-MM-dd") (LocalDate/now)))
 
-(def ^:private test-versions [["39.0" today false ["Super New Fix 1" "Super New Fix 2"]]
-                              ["38.3" "2021-04-01" true ["Fix 1" "Fix 2"]]
-                              ["38.2" "2021-03-21" true ["Older Fix 1" "Older Fix 2"]]
-                              ["38.1" "2021-03-14" true ["Much Older Fix 1" "Much Older Fix 2"]]
-                              ["38.0" "2021-02-15" true ["Super Old Fix 1" "Super Old Fix 2"]]])
+(def ^:private test-versions
+  [["39.0" today false ["Super New Fix 1" "Super New Fix 2"]]
+   ["38.3" "2021-04-01" true ["Fix 1" "Fix 2"]]
+   ["38.2" "2021-03-21" true ["Older Fix 1" "Older Fix 2"]]
+   ["38.1" "2021-03-14" true ["Much Older Fix 1" "Much Older Fix 2"]]
+   ["38.0" "2021-02-15" true ["Super Old Fix 1" "Super Old Fix 2"]]])
 
 (defn- make-version-info [edition versions]
   (let [enterprise? (= edition :ee)]
     {:latest (apply make-version-map (conj (first versions) enterprise?))
-     :older  (map (fn [v]
-                    (apply make-version-map (conj v enterprise?)))
-                  (rest versions))}))
+     :older  (for [v (rest versions)]
+               (apply make-version-map (conj v enterprise?)))}))
+
+(defn- duplicate-version [versions]
+  (into [(first versions)] versions))
+
+(def ^:private previous-version-cases
+  {"with previous versions"           (rest test-versions)
+   "with duplicate previous versions" (duplicate-version (rest test-versions))
+   "including the current version"    test-versions})
 
 (deftest build-info-test
   (doseq [edition [:oss :ee]]
-    (testing (format "build-info.json file for %s edition is correct" (name edition))
-      (with-redefs [v-info/current-version-info (constantly (make-version-info edition (rest test-versions)))
-                    github/milestone-issues     (constantly (mapv (fn [title]
-                                                                    {:title title})
-                                                                  (last (first test-versions))))]
-        (c/set-version! (case edition :oss "0.39.0" "1.39.0"))
-        (c/set-branch!  "testing")
-        (c/set-edition! edition)
-        (#'v-info/generate-version-info!)
-        (let [actual (-> (#'v-info/tmp-version-info-filename)
-                         (slurp)
-                         (json/read-str :key-fn keyword))
-              expected (make-version-info edition test-versions)]
-          (is (= expected actual)))))))
+    (doseq [[case-label previous-versions] previous-version-cases]
+      (testing (format "build-info.json file for %s edition is correct when updating a version info file %s" (name edition) case-label)
+        (with-redefs [v-info/current-version-info (constantly (make-version-info edition previous-versions))
+                      github/milestone-issues     (constantly (vec (for [title (last (first test-versions))]
+                                                                     {:title title})))]
+          (c/set-version! (case edition :oss "0.39.0" "1.39.0"))
+          (c/set-branch!  "testing")
+          (c/set-edition! edition)
+          (#'v-info/generate-version-info!)
+          (let [actual (-> (#'v-info/tmp-version-info-filename)
+                           (slurp)
+                           (json/read-str :key-fn keyword))
+                expected (make-version-info edition test-versions)]
+            (is (= expected actual))))))))
-- 
GitLab