From a734733560733d4b91d18c4a2f5054e00a95248f Mon Sep 17 00:00:00 2001
From: cahillsf <stephen.cahill@datadoghq.com>
Date: Tue, 29 Aug 2023 21:40:21 -0400
Subject: [PATCH 1/2] update doc behavior to respect semver ordering when tag
 is not specified in URL params

---
 cmd/doc/main.go | 82 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 50 insertions(+), 32 deletions(-)

diff --git a/cmd/doc/main.go b/cmd/doc/main.go
index 44b70e3..cc81bfc 100644
--- a/cmd/doc/main.go
+++ b/cmd/doc/main.go
@@ -26,6 +26,7 @@ import (
 	"net/rpc"
 	"net/url"
 	"os"
+	"sort"
 	"strings"
 
 	crdutil "github.com/crdsdev/doc/pkg/crd"
@@ -36,6 +37,7 @@ import (
 	"github.com/jackc/pgx/v4/pgxpool"
 	flag "github.com/spf13/pflag"
 	"github.com/unrolled/render"
+	"golang.org/x/mod/semver"
 	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
 	v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	"sigs.k8s.io/yaml"
@@ -291,40 +293,10 @@ func org(w http.ResponseWriter, r *http.Request) {
 	pageData := getPageData(r, fmt.Sprintf("%s/%s", org, repo), false)
 	fullRepo := fmt.Sprintf("%s/%s/%s", "github.com", org, repo)
 	b := &pgx.Batch{}
-	if tag == "" {
-		b.Queue("SELECT t.name, c.group, c.version, c.kind FROM tags t INNER JOIN crds c ON (c.tag_id = t.id) WHERE LOWER(t.repo)=LOWER($1) AND t.id = (SELECT id FROM tags WHERE LOWER(repo) = LOWER($1) ORDER BY time DESC LIMIT 1);", fullRepo)
-	} else {
-		pageData.Title += fmt.Sprintf("@%s", tag)
-		b.Queue("SELECT t.name, c.group, c.version, c.kind FROM tags t INNER JOIN crds c ON (c.tag_id = t.id) WHERE LOWER(t.repo)=LOWER($1) AND t.name=$2;", fullRepo, tag)
-	}
 	b.Queue("SELECT name FROM tags WHERE LOWER(repo)=LOWER($1) ORDER BY time DESC;", fullRepo)
 	br := db.SendBatch(context.Background(), b)
 	defer br.Close()
 	c, err := br.Query()
-	if err != nil {
-		log.Printf("failed to get CRDs for %s : %v", repo, err)
-		if err := page.HTML(w, http.StatusOK, "new", baseData{Page: pageData}); err != nil {
-			log.Printf("newTemplate.Execute(): %v", err)
-			fmt.Fprint(w, "Unable to render new template.")
-		}
-		return
-	}
-	repoCRDs := map[string]models.RepoCRD{}
-	foundTag := tag
-	for c.Next() {
-		var t, g, v, k string
-		if err := c.Scan(&t, &g, &v, &k); err != nil {
-			log.Printf("newTemplate.Execute(): %v", err)
-			fmt.Fprint(w, "Unable to render new template.")
-		}
-		foundTag = t
-		repoCRDs[g+"/"+v+"/"+k] = models.RepoCRD{
-			Group:   g,
-			Version: v,
-			Kind:    k,
-		}
-	}
-	c, err = br.Query()
 	if err != nil {
 		log.Printf("failed to get tags for %s : %v", repo, err)
 		if err := page.HTML(w, http.StatusOK, "new", baseData{Page: pageData}); err != nil {
@@ -335,6 +307,7 @@ func org(w http.ResponseWriter, r *http.Request) {
 	}
 	tags := []string{}
 	tagExists := false
+	followsSemver := false
 	for c.Next() {
 		var t string
 		if err := c.Scan(&t); err != nil {
@@ -344,6 +317,10 @@ func org(w http.ResponseWriter, r *http.Request) {
 		if !tagExists && t == tag {
 			tagExists = true
 		}
+		if semver.IsValid(t) {
+			log.Println("tag follows semver -- will select latest semver version if tag has not been specified in url params")
+			followsSemver = true
+		}
 		tags = append(tags, t)
 	}
 	if len(tags) == 0 || (!tagExists && tag != "") {
@@ -358,8 +335,49 @@ func org(w http.ResponseWriter, r *http.Request) {
 		}
 		return
 	}
-	if foundTag == "" {
-		foundTag = tags[0]
+	if tag == "" {
+		if len(tags) == 1 || !followsSemver {
+			tag = tags[0]
+		} else {
+			sort.SliceStable(tags, func(i, j int) bool {
+				switch res := semver.Compare(tags[i], tags[j]); res {
+				case -1:
+					return false
+				default:
+					return true
+				}
+			})
+			tag = tags[0]
+		}
+	} else {
+		pageData.Title += fmt.Sprintf("@%s", tag)
+	}
+	b = &pgx.Batch{}
+	b.Queue("SELECT t.name, c.group, c.version, c.kind FROM tags t INNER JOIN crds c ON (c.tag_id = t.id) WHERE LOWER(t.repo)=LOWER($1) AND t.name=$2;", fullRepo, tag)
+	br = db.SendBatch(context.Background(), b)
+	defer br.Close()
+	c, err = br.Query()
+	if err != nil {
+		log.Printf("failed to get CRDs for %s : %v", repo, err)
+		if err := page.HTML(w, http.StatusOK, "new", baseData{Page: pageData}); err != nil {
+			log.Printf("newTemplate.Execute(): %v", err)
+			fmt.Fprint(w, "Unable to render new template.")
+		}
+		return
+	}
+	repoCRDs := map[string]models.RepoCRD{}
+	foundTag := tag
+	for c.Next() {
+		var t, g, v, k string
+		if err := c.Scan(&t, &g, &v, &k); err != nil {
+			log.Printf("error scanning in results: %v", err)
+		}
+		foundTag = t
+		repoCRDs[g+"/"+v+"/"+k] = models.RepoCRD{
+			Group:   g,
+			Version: v,
+			Kind:    k,
+		}
 	}
 	if err := page.HTML(w, http.StatusOK, "org", orgData{
 		Page:  pageData,

From 0ea63c5de7edc5a070e1c3c1d05c37876305ffb2 Mon Sep 17 00:00:00 2001
From: cahillsf <stephen.cahill@datadoghq.com>
Date: Tue, 29 Aug 2023 21:40:40 -0400
Subject: [PATCH 2/2] add semver package to go deps

---
 go.mod | 1 +
 go.sum | 1 +
 2 files changed, 2 insertions(+)

diff --git a/go.mod b/go.mod
index 376681f..8292dc3 100644
--- a/go.mod
+++ b/go.mod
@@ -17,6 +17,7 @@ require (
 	github.com/prometheus/client_golang v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5
 	github.com/unrolled/render v1.0.3
+	golang.org/x/mod v0.3.0
 	golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect
 	golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 // indirect
 	golang.org/x/text v0.3.4 // indirect
diff --git a/go.sum b/go.sum
index 5e6c839..73fb68e 100644
--- a/go.sum
+++ b/go.sum
@@ -556,6 +556,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=