golang.org/x/playground@v0.0.0-20230418134305-14ebe15bcd59/cmd/latestgo/main.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // latestgo prints the latest Go release tag to stdout as a part of the playground deployment process.
     6  package main
     7  
     8  import (
     9  	"context"
    10  	"flag"
    11  	"fmt"
    12  	"log"
    13  	"sort"
    14  	"strings"
    15  	"time"
    16  
    17  	"golang.org/x/build/gerrit"
    18  	"golang.org/x/build/maintner/maintnerd/maintapi/version"
    19  )
    20  
    21  var prev = flag.Bool("prev", false, "whether to query the previous Go release, rather than the last (e.g. 1.17 versus 1.18)")
    22  
    23  func main() {
    24  	client := gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
    25  
    26  	flag.Parse()
    27  
    28  	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
    29  	defer cancel()
    30  
    31  	tagInfo, err := client.GetProjectTags(ctx, "go")
    32  	if err != nil {
    33  		log.Fatalf("error retrieving project tags for 'go': %v", err)
    34  	}
    35  
    36  	if len(tagInfo) == 0 {
    37  		log.Fatalln("no project tags found for 'go'")
    38  	}
    39  
    40  	// Find the latest patch version for each major Go version.
    41  	type majMin struct {
    42  		maj, min int // maj, min in semver terminology, which corresponds to a major go release
    43  	}
    44  	type patchTag struct {
    45  		patch int
    46  		tag   string // Go repo tag for this version
    47  	}
    48  	latestPatches := make(map[majMin]patchTag) // (maj, min) -> latest patch info
    49  
    50  	for _, tag := range tagInfo {
    51  		tagName := strings.TrimPrefix(tag.Ref, "refs/tags/")
    52  		maj, min, patch, ok := version.ParseTag(tagName)
    53  		if !ok {
    54  			continue
    55  		}
    56  
    57  		mm := majMin{maj, min}
    58  		if latest, ok := latestPatches[mm]; !ok || latest.patch < patch {
    59  			latestPatches[mm] = patchTag{patch, tagName}
    60  		}
    61  	}
    62  
    63  	var mms []majMin
    64  	for mm := range latestPatches {
    65  		mms = append(mms, mm)
    66  	}
    67  	sort.Slice(mms, func(i, j int) bool {
    68  		if mms[i].maj != mms[j].maj {
    69  			return mms[i].maj < mms[j].maj
    70  		}
    71  		return mms[i].min < mms[j].min
    72  	})
    73  
    74  	var mm majMin
    75  	if *prev && len(mms) > 1 {
    76  		mm = mms[len(mms)-2] // latest patch of the previous Go release
    77  	} else {
    78  		mm = mms[len(mms)-1]
    79  	}
    80  	fmt.Print(latestPatches[mm].tag)
    81  }