diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 769dc48dcb..94e51dab0c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,6 +32,10 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v6 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25.0" # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v4 @@ -40,8 +44,19 @@ jobs: build-mode: manual - name: Install Taskfile support uses: arduino/setup-task@v2 - - shell: bash - run: task build + - name: Install libmongocrypt + run: task install-libmongocrypt + - name: Build (CodeQL-instrumented) + shell: bash + env: + GOTOOLCHAIN: local + run: | + # TODO(GODRIVER-3723): Run using taskfile targets. + go build ./... + go build ${BUILD_TAGS} ./... + go test -short ${BUILD_TAGS} -run ^$$ ./... + + go test -v ./internal/test/compilecheck -run '^TestCompileCheck/go:1\.19$' - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: diff --git a/.gitignore b/.gitignore index c4a9fcbfad..7c96c9c291 100644 --- a/.gitignore +++ b/.gitignore @@ -31,10 +31,6 @@ bin internal/cmd/faas/awslambda/.aws-sam internal/cmd/faas/awslambda/events/event.json -# Ignore compiled binaries from the compilecheck -internal/cmd/compilecheck/compilecheck -internal/cmd/compilecheck/compilecheck.so - # Ignore api report files api-report.md api-report.txt diff --git a/Dockerfile b/Dockerfile index 46b6cee71b..c1c6b783c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Dockerfile for Go Driver local development. # Build libmongocrypt in a separate build stage. -FROM artifactory.corp.mongodb.com/dockerhub/ubuntu:20.04 as libmongocrypt +FROM golang:1.25.5-trixie AS libmongocrypt RUN apt-get -qq update && \ apt-get -qqy install --no-install-recommends \ @@ -10,16 +10,19 @@ RUN apt-get -qq update && \ curl \ build-essential \ libssl-dev \ - python + pkg-config \ + python3 \ + python3-packaging \ + python-is-python3 && \ + rm -rf /var/lib/apt/lists/* COPY etc/install-libmongocrypt.sh /root/install-libmongocrypt.sh RUN cd /root && bash ./install-libmongocrypt.sh -# Copy in the files from the libmongocrypt build stage. -FROM artifactory.corp.mongodb.com/dockerhub/ubuntu:20.04 +# Final dev image (already has Go 1.25.x). +FROM golang:1.25.5-trixie -# Install common deps. RUN export DEBIAN_FRONTEND=noninteractive && \ export TZ=Etc/UTC && \ apt-get -qq update && \ @@ -30,33 +33,22 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ wget \ sudo \ tzdata \ - ca-certificates \ pkg-config \ - software-properties-common \ gpg \ apt-utils \ libc6-dev \ gcc \ - make && \ - sudo update-ca-certificates && \ - rm -rf /var/lib/apt/lists/* - -# Install golang from the golang-backports ppa. -RUN export DEBIAN_FRONTEND=noninteractive && \ - export TZ=Etc/UTC && \ - export LC_ALL=C.UTF-8 && \ - sudo -E apt-add-repository "ppa:longsleep/golang-backports" && \ - apt-get -qq update --option Acquire::Retries=100 --option Acquire::http::Timeout="60" && \ - apt-get -qqy install --option Acquire::Retries=100 --option Acquire::http::Timeout="60" --no-install-recommends golang-go && \ + make \ + libkrb5-dev && \ + update-ca-certificates && \ rm -rf /var/lib/apt/lists/* -# Install taskfile -RUN go install github.com/go-task/task/v3/cmd/task@latest - -COPY ./etc/docker_entry.sh /root/docker_entry.sh +COPY etc/docker_entry.sh /root/docker_entry.sh COPY --from=libmongocrypt /root/install /root/install -ENV DOCKER_RUNNING=true +# Copy the Go driver source for local development and compile checks. +COPY . /mongo-go-driver +ENV DOCKER_RUNNING=true ENTRYPOINT ["/bin/bash", "/root/docker_entry.sh"] diff --git a/Taskfile.yml b/Taskfile.yml index 73842ab9c9..150402b4c1 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -17,19 +17,15 @@ tasks: - go build ./... - go build ${BUILD_TAGS} ./... - task: build-tests - - task: build-compile-check - - task: cross-compile + - task: compilecheck-119 build-tests: go test -short ${BUILD_TAGS} -run ^$$ ./... - build-compile-check: bash etc/compile_check.sh + compilecheck-119: + dir: internal/test/compilecheck + cmds: + - go mod download + - GOTOOLCHAIN=auto go test -v -run '^TestCompileCheck/go:1\.19$' build-compile-check-all: bash etc/run-compile-check-test.sh build-aws-ecs-test: go test -c ./internal/test/aws -o aws.testbin - cross-compile: - - GOOS=linux GOARCH=386 go build ./... - - GOOS=linux GOARCH=arm go build ./... - - GOOS=linux GOARCH=arm64 go build ./... - - GOOS=linux GOARCH=amd64 go build ./... - - GOOS=linux GOARCH=ppc64le go build ./... - - GOOS=linux GOARCH=s390x go build ./... check-fmt: deps: [install-lll] cmds: diff --git a/etc/compile_check.sh b/etc/compile_check.sh deleted file mode 100755 index 457b8e9e92..0000000000 --- a/etc/compile_check.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -set -e # exit when any command fails -set -x # show all commands being run - -: ${GC:=go${GO_VERSION="1.19"}} - -COMPILE_CHECK_DIR="internal/cmd/compilecheck" -ARCHITECTURES=("386" "arm" "arm64" "ppc64le" "s390x") -BUILD_CMD="${GC} build -buildvcs=false" - -# compile_check will attempt to build the internal/test/compilecheck project -# using the provided Go version. This is to simulate an end-to-end use case. -function compile_check { - # Change the directory to the compilecheck test directory. - pushd "${COMPILE_CHECK_DIR}" >/dev/null - - # If a custom Go version is set using the GO_VERSION env var (e.g. "1.18"), - # add the GOPATH bin directory to PATH and then install that Go version. - if [ ! -z "$GO_VERSION" ]; then - PATH=$(go env GOPATH)/bin:$PATH - export PATH - - go install golang.org/dl/go$GO_VERSION@latest - ${GC} download - fi - - ${GC} version - ${GC} mod tidy - - # Standard build - $BUILD_CMD ./... - - # Dynamic linking - $BUILD_CMD -buildmode=plugin - - # Check build with tags. - [[ -n "$BUILD_TAGS" ]] && $BUILD_CMD $BUILD_TAGS ./... - - # Check build with various architectures. - for ARCH in "${ARCHITECTURES[@]}"; do - GOOS=linux GOARCH=$ARCH $BUILD_CMD ./... - done - - # Change the directory back to the working directory. - popd >/dev/null -} - -compile_check diff --git a/etc/run-compile-check-test.sh b/etc/run-compile-check-test.sh index abd8b73bc6..4aa808c3ea 100755 --- a/etc/run-compile-check-test.sh +++ b/etc/run-compile-check-test.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # run-compile-check-test -# Run compile check tests. +# Run compile check tests for all supported Go versions. set -eu set +x echo "Running internal/test/compilecheck" pushd internal/test/compilecheck -GOWORK=off go test -timeout 30m -v ./... >>../../../test.suite +go test -timeout 30m -v ./... >>../../../test.suite popd diff --git a/go.work b/go.work index 43568f4aa7..5f684346ec 100644 --- a/go.work +++ b/go.work @@ -6,7 +6,6 @@ use ( ./examples/_logger/zap ./examples/_logger/zerolog ./internal/cmd/benchmark - ./internal/cmd/compilecheck ./internal/cmd/faas/awslambda/mongodb ./internal/test/compilecheck ./internal/test/goleak diff --git a/internal/cmd/compilecheck/go.mod b/internal/cmd/compilecheck/go.mod deleted file mode 100644 index 7328f4c1a6..0000000000 --- a/internal/cmd/compilecheck/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module go.mongodb.go/mongo-driver/v2/internal/cmd/compilecheck - -go 1.19 - -replace go.mongodb.org/mongo-driver/v2 => ../../../ - -// Note that the Go driver version is replaced with the local Go driver code by -// the replace directive above. -require go.mongodb.org/mongo-driver/v2 v2.0.0-alpha2 - -require ( - github.com/klauspost/compress v1.17.6 // indirect - github.com/xdg-go/pbkdf2 v1.0.0 // indirect - github.com/xdg-go/scram v1.2.0 // indirect - github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect - golang.org/x/crypto v0.33.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/text v0.22.0 // indirect -) diff --git a/internal/cmd/compilecheck/go.sum b/internal/cmd/compilecheck/go.sum deleted file mode 100644 index b71abc26e7..0000000000 --- a/internal/cmd/compilecheck/go.sum +++ /dev/null @@ -1,42 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs= -github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8= -github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= -github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/cmd/compilecheck/go.work b/internal/cmd/compilecheck/go.work deleted file mode 100644 index 6da44691e9..0000000000 --- a/internal/cmd/compilecheck/go.work +++ /dev/null @@ -1,5 +0,0 @@ -go 1.19 - -use ( - . -) diff --git a/internal/cmd/compilecheck/main.go b/internal/cmd/compilecheck/main.go deleted file mode 100644 index 1661c6e097..0000000000 --- a/internal/cmd/compilecheck/main.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2023-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package main - -import ( - "fmt" - - "go.mongodb.org/mongo-driver/v2/bson" - "go.mongodb.org/mongo-driver/v2/mongo" - "go.mongodb.org/mongo-driver/v2/mongo/options" - "go.mongodb.org/mongo-driver/v2/x/mongo/driver/xoptions" -) - -func main() { - opts := options.Client() - xoptions.SetInternalClientOptions(opts, "foo", "bar") - - _, _ = mongo.Connect(options.Client()) - fmt.Println(bson.D{{Key: "key", Value: "value"}}) -} diff --git a/internal/test/compilecheck/compile_check_test.go b/internal/test/compilecheck/compile_check_test.go index 2eef836190..7c9cd28963 100644 --- a/internal/test/compilecheck/compile_check_test.go +++ b/internal/test/compilecheck/compile_check_test.go @@ -12,21 +12,74 @@ import ( "io" "os" "path/filepath" + "strings" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" ) -var versions = []string{ - "1.19", - "1.20", - "1.21", - "1.22", - "1.23", - "1.24", - "1.25", +const mainGo = `package main + +import ( + "fmt" + + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" +) + +func main() { + _, _ = mongo.Connect(options.Client()) + fmt.Println(bson.D{{Key: "key", Value: "value"}}) +} +` + +const goMod = `module compilecheck + +go 1.19 + +require go.mongodb.org/mongo-driver/v2 v2.1.0 + +replace go.mongodb.org/mongo-driver/v2 => /mongo-go-driver +` + +// goVersions is the list of Go versions to test compilation against. +// To run tests for specific version(s), use the -run flag: +// +// go test -v -run '^TestCompileCheck/go:1.19$' +// go test -v -run '^TestCompileCheck/go:1\.(19|20)$' +var goVersions = []string{"1.19", "1.20", "1.21", "1.22", "1.23", "1.24", "1.25"} +var architectures = []string{ + "386", + "amd64", + "arm", + "arm64", + "mips", + "mips64", + "mips64le", + "mipsle", + "ppc64", + "ppc64le", + "riscv64", + "s390x", +} + +// goBuild constructs a build command that tries GOTOOLCHAIN=goX.Y.0 first, then falls back to goX.Y. +func goBuild(ver, workdir string, env, extraFlags []string) string { + baseEnv := "PATH=/usr/local/go/bin:$PATH" + envStr := baseEnv + if len(env) > 0 { + envStr = strings.Join(env, " ") + " " + baseEnv + } + + flags := "-buildvcs=false" + if len(extraFlags) > 0 { + flags += " " + strings.Join(extraFlags, " ") + } + + return fmt.Sprintf("cd %s && %s GOTOOLCHAIN=go%s.0 go build %s -o /dev/null main.go 2>&1 || %s GOTOOLCHAIN=go%s go build %s -o /dev/null main.go 2>&1", + workdir, envStr, ver, flags, envStr, ver, flags) } func TestCompileCheck(t *testing.T) { @@ -35,50 +88,130 @@ func TestCompileCheck(t *testing.T) { rootDir := filepath.Dir(filepath.Dir(filepath.Dir(cwd))) - for _, version := range versions { - version := version // Capture range variable. + // Build the image and start one container we can reuse for all subtests. + req := testcontainers.ContainerRequest{ + FromDockerfile: testcontainers.FromDockerfile{ + Context: rootDir, + Dockerfile: "Dockerfile", + PrintBuildLog: true, + }, + Entrypoint: []string{"tail", "-f", "/dev/null"}, + WorkingDir: "/workspace", + } + + genReq := testcontainers.GenericContainerRequest{ContainerRequest: req, Started: true} + + container, err := testcontainers.GenericContainer(context.Background(), genReq) + require.NoError(t, err) + + t.Cleanup(func() { + require.NoError(t, container.Terminate(context.Background())) + }) + + // Write main.go into the container. + exitCode, outputReader, err := container.Exec(context.Background(), []string{"sh", "-c", fmt.Sprintf("cat > /workspace/main.go << 'GOFILE'\n%s\nGOFILE", mainGo)}) + require.NoError(t, err) + + output, err := io.ReadAll(outputReader) + require.NoError(t, err) + require.Equal(t, 0, exitCode, "failed to write main.go: %s", output) + + // Write go.mod into the container. + exitCode, outputReader, err = container.Exec(context.Background(), []string{"sh", "-c", fmt.Sprintf("cat > /workspace/go.mod << 'GOMOD'\n%s\nGOMOD", goMod)}) + require.NoError(t, err) + + output, err = io.ReadAll(outputReader) + require.NoError(t, err) + require.Equal(t, 0, exitCode, "failed to write go.mod: %s", output) - image := fmt.Sprintf("golang:%s", version) - t.Run(image, func(t *testing.T) { + exitCode, outputReader, err = container.Exec(context.Background(), []string{"sh", "-c", "cd /workspace && PATH=/usr/local/go/bin:$PATH go mod tidy 2>&1"}) + require.NoError(t, err) + + output, err = io.ReadAll(outputReader) + require.NoError(t, err) + require.Equal(t, 0, exitCode, "failed to tidy dependencies: %s", output) + + for _, ver := range goVersions { + ver := ver // capture + t.Run("go:"+ver, func(t *testing.T) { t.Parallel() - req := testcontainers.ContainerRequest{ - Image: image, - Cmd: []string{"tail", "-f", "/dev/null"}, - Mounts: []testcontainers.ContainerMount{ - testcontainers.BindMount(rootDir, "/workspace"), - }, - WorkingDir: "/workspace", - Env: map[string]string{ - "GC": "go", - // Compilation modules are not part of the workspace as testcontainers requires - // a version of klauspost/compress not supported by the Go Driver / other modules - // in the workspace. - "GOWORK": "off", - }, - } + // Each version gets its own workspace to avoid conflicts when running in parallel. + workspace := fmt.Sprintf("/workspace-%s", ver) - genReq := testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, - } + setupCmd := fmt.Sprintf("mkdir -p %[1]s && cp /workspace/main.go /workspace/go.mod /workspace/go.sum %[1]s/", workspace) + exitCode, outputReader, err := container.Exec(context.Background(), []string{"sh", "-c", setupCmd}) + require.NoError(t, err) - container, err := testcontainers.GenericContainer(context.Background(), genReq) + output, err := io.ReadAll(outputReader) require.NoError(t, err) + require.Equal(t, 0, exitCode, "failed to setup workspace: %s", output) - defer func() { - err := container.Terminate(context.Background()) - require.NoError(t, err) - }() + cmd := fmt.Sprintf("PATH=/usr/local/go/bin:$PATH GOTOOLCHAIN=go%[1]s.0+auto go version || PATH=/usr/local/go/bin:$PATH GOTOOLCHAIN=go%[1]s go version", ver) - exitCode, outputReader, err := container.Exec(context.Background(), []string{"bash", "etc/compile_check.sh"}) + exit, out, err := container.Exec(context.Background(), []string{"bash", "-lc", cmd}) require.NoError(t, err) - output, err := io.ReadAll(outputReader) + b, err := io.ReadAll(out) + + require.NoError(t, err) + require.Equal(t, 0, exit, "go version failed: %s", b) + require.Contains(t, string(b), "go"+ver, "unexpected go version: %s", b) + + // Standard build. + exitCode, outputReader, err = container.Exec(context.Background(), []string{ + "sh", "-c", goBuild(ver, workspace, nil, nil), + }) + require.NoError(t, err) + + output, err = io.ReadAll(outputReader) + require.NoError(t, err) + + require.Equal(t, 0, exitCode, "standard build failed: %s", output) + + // Dynamic linking build. + exitCode, outputReader, err = container.Exec(context.Background(), []string{ + "sh", "-c", goBuild(ver, workspace, nil, []string{"-buildmode=plugin"}), + }) + require.NoError(t, err) + + output, err = io.ReadAll(outputReader) + require.NoError(t, err) + + require.Equal(t, 0, exitCode, "dynamic linking build failed: %s", output) + + // Build with build tags. + cgoEnv := []string{ + "PKG_CONFIG_PATH=/root/install/libmongocrypt/lib/pkgconfig", + "CGO_CFLAGS='-I/root/install/libmongocrypt/include'", + "CGO_LDFLAGS='-L/root/install/libmongocrypt/lib -Wl,-rpath,/root/install/libmongocrypt/lib'", + } + exitCode, outputReader, err = container.Exec(context.Background(), []string{ + "sh", "-c", goBuild(ver, workspace, cgoEnv, []string{"-tags=cse,gssapi,mongointernal"}), + }) + require.NoError(t, err) + + output, err = io.ReadAll(outputReader) require.NoError(t, err) - t.Logf("output: %s", output) - assert.Equal(t, 0, exitCode) + require.Equal(t, 0, exitCode, "build with build tags failed: %s", output) + + // Build for each architecture. + for _, architecture := range architectures { + archEnv := []string{"GOOS=linux", "GOARCH=" + architecture} + exitCode, outputReader, err = container.Exec( + context.Background(), + []string{"sh", "-c", goBuild(ver, workspace, archEnv, nil)}, + ) + require.NoError(t, err) + + output, err := io.ReadAll(outputReader) + require.NoError(t, err) + + require.Equal(t, 0, exitCode, "build failed for architecture %s: %s", architecture, output) + } + + t.Logf("compilation checks passed for Go ver %s", ver) }) } }