Skip to content

Commit

Permalink
Test against multiple supported Go versions
Browse files Browse the repository at this point in the history
  • Loading branch information
mumoshu committed Nov 19, 2024
1 parent 4befcd7 commit 390964c
Show file tree
Hide file tree
Showing 5 changed files with 1,079 additions and 13 deletions.
29 changes: 16 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,21 @@ on:
- main

jobs:
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
release-go-version: ${{ steps.set.outputs.release-go-version }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- id: set
run: go run ./tools/setghaoutputs | tee -a "$GITHUB_OUTPUT"
test:
needs: setup
runs-on: ubuntu-latest
strategy:
matrix: ${{fromJson(needs.setup.outputs.matrix)}}
permissions:
# This is required to push changes back to the repository
contents: write
Expand All @@ -17,18 +30,12 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.22
go-version: ${{ matrix.go-version }}
- name: Start LocalStack
uses: LocalStack/[email protected]
with:
image-tag: 'latest'
install-awslocal: 'true'
- name: Set up Git user
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "aws-checker@@users.noreply.github.com"
- name: Bump Go versions in go.mod and workflows if necessary
run: go run ./tools/syncgover
- name: Run tests
run: go test -v ./...
env:
Expand All @@ -48,19 +55,15 @@ jobs:
DYNAMODB_TABLE: mytable
# This one is for setupSQSQueue in main_test
SQS_QUEUE_URL: https://sqs.ap-northeast-1.amazonaws.com/123456789012/myqueue
- name: Push code changes back to the repository
if: github.event_name == 'pull_request'
run: |
echo Pushing changes to ${GITHUB_HEAD_REF}
git push origin HEAD:${GITHUB_HEAD_REF} || echo "Unable to push changes"
goreleaser:
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.22
go-version: ${{ needs.setup.outputs.release-go-version }}
- name: Goreleaser image building test
uses: goreleaser/goreleaser-action@v6
with:
Expand Down
21 changes: 21 additions & 0 deletions tools/setghaoutputs/gover_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func TestGover(t *testing.T) {
goDevDLJson := filepath.Join("testdata", "go.dev.dl.json")

data, err := os.ReadFile(goDevDLJson)
require.NoError(t, err)

versions, err := getGoVersions(data)
require.NoError(t, err)

require.Equal(t, [2]string{"1.23.3", "1.22.9"}, versions)
}
145 changes: 145 additions & 0 deletions tools/setghaoutputs/setghaoutputs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package main

import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"sort"
"strconv"
"strings"
)

// setghaoutputs is a tool to fetch the latest two stable Go versions from the Go website,
// and set the Go versions to the GitHub Actions workflow matrix and the release Go version outputs.
func main() {
if err := setGHAOutputs(os.Stdout, http.Get); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

type ghaMatrix struct {
Include []Include `json:"include"`
}

type Include struct {
GoVersion string `json:"go-version"`
}

func setGHAOutputs(w io.Writer, httpGet func(string) (*http.Response, error)) error {
vers, err := getGoVersionsFromAPI(httpGet)
if err != nil {
return err
}

data, err := json.Marshal(ghaMatrix{
Include: []Include{
{GoVersion: vers[0]},
{GoVersion: vers[1]},
},
})
if err != nil {
return err
}

if _, err := fmt.Fprint(w, "matrix="); err != nil {
return fmt.Errorf("failed to write the Go versions to the output: %w", err)
}

if _, err := fmt.Fprintln(w, string(data)); err != nil {
return fmt.Errorf("failed to write the Go versions to the output: %w", err)
}

if _, err := fmt.Fprintf(w, "release-go-version=%s\n", vers[1]); err != nil {
return fmt.Errorf("failed to write the release Go version to the output: %w", err)
}

return nil
}

type Releases []Release

type Release struct {
Version string `json:"version"`
Stable bool `json:"stable"`
}

func getGoVersionsFromAPI(httpGet func(string) (*http.Response, error)) ([2]string, error) {
url := "https://go.dev/dl/?mode=json"

res, err := httpGet(url)
if err != nil {
return [2]string{}, err
}

data, err := io.ReadAll(res.Body)
if err != nil {
return [2]string{}, err
}

return getGoVersions(data)
}

func getGoVersions(data []byte) ([2]string, error) {
var releases Releases
if err := json.Unmarshal(data, &releases); err != nil {
return [2]string{}, err
}

type semver struct {
major, minor, patch int
}

var latestToOlder []semver
for _, r := range releases {
if !r.Stable {
continue
}

v := strings.TrimPrefix(r.Version, "go")

splits := strings.Split(v, ".")
if len(splits) != 3 {
continue
}

major, err := strconv.Atoi(splits[0])
if err != nil {
continue
}

minor, err := strconv.Atoi(splits[1])
if err != nil {
continue
}

patch, err := strconv.Atoi(splits[2])
if err != nil {
continue
}

latestToOlder = append(latestToOlder, semver{major, minor, patch})
}

if len(latestToOlder) < 2 {
return [2]string{}, fmt.Errorf("could not find two stable Go versions")
}

// Sort the versions from the latest to the older.
sort.Slice(latestToOlder, func(i, j int) bool {
if latestToOlder[i].major != latestToOlder[j].major {
return latestToOlder[i].major > latestToOlder[j].major
}
if latestToOlder[i].minor != latestToOlder[j].minor {
return latestToOlder[i].minor > latestToOlder[j].minor
}
return latestToOlder[i].patch > latestToOlder[j].patch
})

return [2]string{
fmt.Sprintf("%d.%d.%d", latestToOlder[0].major, latestToOlder[0].minor, latestToOlder[0].patch),
fmt.Sprintf("%d.%d.%d", latestToOlder[1].major, latestToOlder[1].minor, latestToOlder[1].patch),
}, nil
}
28 changes: 28 additions & 0 deletions tools/setghaoutputs/setghaoutputs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"bytes"
"io"
"net/http"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func TestFetchGoVer(t *testing.T) {
goDevDLJson, err := os.ReadFile(filepath.Join("testdata", "go.dev.dl.json"))
require.NoError(t, err)

var b bytes.Buffer
require.NoError(t, setGHAOutputs(&b, func(string) (*http.Response, error) {
return &http.Response{
Body: io.NopCloser(bytes.NewReader(goDevDLJson)),
}, nil
}))

require.Equal(t, `matrix={"include":[{"go-version":"1.23.3"},{"go-version":"1.22.9"}]}
release-go-version=1.22.9
`, b.String())
}
Loading

0 comments on commit 390964c

Please sign in to comment.