|
1 | 1 | package main
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "context" |
| 4 | + "encoding/json" |
5 | 5 | "fmt"
|
| 6 | + "net/http" |
6 | 7 | "os"
|
7 | 8 |
|
8 |
| - "github.com/google/go-github/github" |
9 | 9 | "github.com/masterminds/semver"
|
10 | 10 | )
|
11 | 11 |
|
12 | 12 | func main() {
|
13 |
| - client := github.NewClient(nil) |
14 |
| - // We consider the latest release as 'mainline' |
15 |
| - ctx, cancel := context.WithCancel(context.Background()) |
16 |
| - defer cancel() |
17 |
| - latest, _, err := client.Repositories.GetLatestRelease(ctx, "coder", "coder") |
18 |
| - if err != nil { |
19 |
| - fatal("get mainline release: %w\n", err) |
20 |
| - } |
| 13 | + releases := fetchReleases() |
21 | 14 |
|
22 |
| - if latest.TagName == nil { |
23 |
| - fatal("latest release is not tagged", err) |
24 |
| - } |
| 15 | + mainlineVer := semver.MustParse("v0.0.0") |
| 16 | + for _, rel := range releases { |
| 17 | + if rel == "" { |
| 18 | + debug("ignoring untagged version %s\n", rel) |
| 19 | + continue |
| 20 | + } |
25 | 21 |
|
26 |
| - mainlineVer, err := semver.NewVersion(*latest.TagName) |
27 |
| - if err != nil { |
28 |
| - fatal("invalid mainline tag name: %w\n", err) |
| 22 | + ver, err := semver.NewVersion(rel) |
| 23 | + if err != nil { |
| 24 | + debug("skipping invalid version %s\n", rel) |
| 25 | + } |
| 26 | + |
| 27 | + if ver.Compare(mainlineVer) > 0 { |
| 28 | + mainlineVer = ver |
| 29 | + continue |
| 30 | + } |
29 | 31 | }
|
| 32 | + |
30 | 33 | mainline := fmt.Sprintf("v%d.%d.%d", mainlineVer.Major(), mainlineVer.Minor(), mainlineVer.Patch())
|
| 34 | + _, _ = fmt.Fprintf(os.Stdout, "CODER_MAINLINE_VERSION=%q\n", mainline) |
31 | 35 |
|
32 | 36 | expectedStableMinor := mainlineVer.Minor() - 1
|
33 | 37 | if expectedStableMinor < 0 {
|
34 |
| - fatal("unexpected minor version 0") |
| 38 | + expectedStableMinor = 0 |
35 | 39 | }
|
36 |
| - |
37 |
| - previousReleases, _, err := client.Repositories.ListReleases(ctx, "coder", "coder", &github.ListOptions{ |
38 |
| - Page: 0, |
39 |
| - PerPage: 100, |
40 |
| - }) |
41 |
| - if err != nil { |
42 |
| - fatal("list previous releases: %w\n", err) |
43 |
| - } |
44 |
| - |
45 |
| - var stable string |
46 |
| - for _, rel := range previousReleases { |
47 |
| - if rel.TagName == nil { |
48 |
| - debug("ignoring untagged version %s\n", rel.String()) |
| 40 | + debug("expected stable minor: %d\n", expectedStableMinor) |
| 41 | + stableVer := semver.MustParse("v0.0.0") |
| 42 | + for _, rel := range releases { |
| 43 | + debug("check version %s\n", rel) |
| 44 | + if rel == "" { |
| 45 | + debug("ignoring untagged version %s\n", rel) |
49 | 46 | continue
|
50 | 47 | }
|
51 | 48 |
|
52 |
| - ver, err := semver.NewVersion(*rel.TagName) |
| 49 | + ver, err := semver.NewVersion(rel) |
53 | 50 | if err != nil {
|
54 |
| - debug("skipping invalid version %s\n", *rel.TagName) |
| 51 | + debug("skipping invalid version %s\n", rel) |
55 | 52 | }
|
56 | 53 |
|
57 |
| - // Assuming that the first one we find with minor-1 is what we want |
58 |
| - if ver.Minor() == expectedStableMinor { |
59 |
| - debug("found stable version %s\n", *rel.TagName) |
60 |
| - stable = fmt.Sprintf("v%d.%d.%d", ver.Major(), ver.Minor(), ver.Patch()) |
61 |
| - break |
| 54 | + if ver.Minor() != expectedStableMinor { |
| 55 | + debug("skipping version %s\n", rel) |
| 56 | + continue |
62 | 57 | }
|
63 | 58 |
|
| 59 | + if ver.Compare(stableVer) > 0 { |
| 60 | + stableVer = ver |
| 61 | + continue |
| 62 | + } |
64 | 63 | }
|
65 |
| - _, _ = fmt.Fprintf(os.Stdout, "CODER_MAINLINE_VERSION=%q\n", mainline) |
| 64 | + |
| 65 | + stable := fmt.Sprintf("v%d.%d.%d", stableVer.Major(), stableVer.Minor(), stableVer.Patch()) |
66 | 66 | _, _ = fmt.Fprintf(os.Stdout, "CODER_STABLE_VERSION=%q\n", stable)
|
67 | 67 | }
|
68 | 68 |
|
| 69 | +type release struct { |
| 70 | + TagName string `json:"tag_name"` |
| 71 | +} |
| 72 | + |
| 73 | +const releasesURL = "https://api.github.com/repos/coder/coder/releases" |
| 74 | + |
| 75 | +// fetchReleases fetches the releases of coder/coder |
| 76 | +// this is done directly via JSON API to avoid pulling in the entire |
| 77 | +// github client |
| 78 | +func fetchReleases() []string { |
| 79 | + resp, err := http.Get(releasesURL) |
| 80 | + if err != nil { |
| 81 | + fatal("get releases: %w", err) |
| 82 | + } |
| 83 | + defer resp.Body.Close() |
| 84 | + |
| 85 | + var releases []release |
| 86 | + if err := json.NewDecoder(resp.Body).Decode(&releases); err != nil { |
| 87 | + fatal("parse releases: %w", err) |
| 88 | + } |
| 89 | + |
| 90 | + var ss []string |
| 91 | + for _, rel := range releases { |
| 92 | + if rel.TagName != "" { |
| 93 | + ss = append(ss, rel.TagName) |
| 94 | + |
| 95 | + } |
| 96 | + } |
| 97 | + return ss |
| 98 | +} |
| 99 | + |
69 | 100 | func debug(format string, args ...any) {
|
70 | 101 | if _, ok := os.LookupEnv("VERBOSE"); ok {
|
71 | 102 | _, _ = fmt.Fprintf(os.Stderr, format, args...)
|
|
0 commit comments