internal/play: add goprevplay, load versions from back ends

This will let us have "Go 1.17" in the dropdown on go.dev/play.
And when the next release happens and goprevplay and play are
updated, the versions will update automatically in the UI.

Change-Id: Id76f89767c3a91a2c9e27c9fbdad5d6fd9674ab2
Reviewed-on: https://go-review.googlesource.com/c/website/+/393840
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/internal/play/play.go b/internal/play/play.go
index 4c34672..b6b459a 100644
--- a/internal/play/play.go
+++ b/internal/play/play.go
@@ -52,6 +52,7 @@
 	// Default set until we get the full list from play.golang.org.
 	playVersions.Store([]playVersion{
 		{Name: "Go release", Backend: ""},
+		{Name: "Go previous release", Backend: "goprev"},
 		{Name: "Go dev branch", Backend: "gotip"},
 	})
 
@@ -69,22 +70,32 @@
 	client := &http.Client{
 		Timeout: 2 * time.Minute,
 	}
-	resp, err := client.Get("https://play.golang.org/versions")
-	if err != nil {
-		return nil, fmt.Errorf("readVersions: %v", err)
-	}
-	defer resp.Body.Close()
 
-	js, err := io.ReadAll(resp.Body)
-	if err != nil {
-		return nil, fmt.Errorf("readVersions: %v", err)
-	}
-	if resp.StatusCode != 200 {
-		return nil, fmt.Errorf("readVersions: %s\n%s", resp.Status, js)
-	}
-
-	if err := json.Unmarshal(js, &list); err != nil || len(list) < 2 {
-		return nil, fmt.Errorf("readVersions: bad response: %#q", js)
+	list = append([]playVersion(nil), playVersions.Load().([]playVersion)...)
+	for i, v := range list {
+		resp, err := client.Get("https://" + v.Backend + "play.golang.org/version")
+		if err != nil {
+			log.Printf("readVersions: %v", err)
+			continue
+		}
+		js, err := io.ReadAll(resp.Body)
+		resp.Body.Close()
+		if err != nil {
+			log.Printf("readVersions: %v", err)
+			continue
+		}
+		if resp.StatusCode != 200 {
+			log.Printf("readVersions: %s\n%s", resp.Status, js)
+			continue
+		}
+		var data struct{ Name string }
+		if err := json.Unmarshal(js, &data); err != nil {
+			log.Printf("readVersions: %v", err)
+			continue
+		}
+		if data.Name != "" {
+			list[i].Name = data.Name
+		}
 	}
 	return list, nil
 }