diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 8eeffe512506..2433e581f994 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -112,9 +112,13 @@ jobs: run: bin/task docker-local FILE=production - name: Extract Docker image names - id: extract + id: tag uses: FerretDB/github-actions/extract-docker-tag@main + # - name: Define Docker image names + # id: tag + # run: bin/definedockertag + - name: Login to Docker Hub uses: docker/login-action@v3 with: @@ -135,17 +139,17 @@ jobs: username: ferretdbbot password: ${{ secrets.QUAY_TOKEN }} - - name: Build and push all-in-one Docker images ${{ steps.extract.outputs.all_in_one_images }} - if: steps.extract.outputs.all_in_one_images != '' - run: bin/task docker-all-in-one-push DOCKER_IMAGES=${{ steps.extract.outputs.all_in_one_images }} + - name: Build and push all-in-one Docker images ${{ steps.tag.outputs.all_in_one_images }} + if: steps.tag.outputs.all_in_one_images != '' + run: bin/task docker-all-in-one-push DOCKER_IMAGES=${{ steps.tag.outputs.all_in_one_images }} - - name: Build and push development Docker images ${{ steps.extract.outputs.development_images }} - if: steps.extract.outputs.development_images != '' - run: bin/task docker-development-push DOCKER_IMAGES=${{ steps.extract.outputs.development_images }} + - name: Build and push development Docker images ${{ steps.tag.outputs.development_images }} + if: steps.tag.outputs.development_images != '' + run: bin/task docker-development-push DOCKER_IMAGES=${{ steps.tag.outputs.development_images }} - - name: Build and push production Docker images ${{ steps.extract.outputs.production_images }} - if: steps.extract.outputs.production_images != '' - run: bin/task docker-production-push DOCKER_IMAGES=${{ steps.extract.outputs.production_images }} + - name: Build and push production Docker images ${{ steps.tag.outputs.production_images }} + if: steps.tag.outputs.production_images != '' + run: bin/task docker-production-push DOCKER_IMAGES=${{ steps.tag.outputs.production_images }} - name: Build development binaries run: bin/task build-development diff --git a/build/ferretdb/all-in-one.Dockerfile b/build/ferretdb/all-in-one.Dockerfile index ea390133471f..39bf5445e365 100644 --- a/build/ferretdb/all-in-one.Dockerfile +++ b/build/ferretdb/all-in-one.Dockerfile @@ -14,7 +14,7 @@ ARG LABEL_COMMIT # prepare stage -FROM --platform=$BUILDPLATFORM golang:1.23.1 AS all-in-one-prepare +FROM --platform=$BUILDPLATFORM golang:1.23.2 AS all-in-one-prepare # use a single directory for all Go caches to simpliy RUN --mount commands below ENV GOPATH=/cache/gopath @@ -38,7 +38,7 @@ EOF # build stage -FROM golang:1.23.1 AS all-in-one-build +FROM golang:1.23.2 AS all-in-one-build ARG TARGETARCH diff --git a/build/ferretdb/development.Dockerfile b/build/ferretdb/development.Dockerfile index 8bd33ced7b7f..068d6229123c 100644 --- a/build/ferretdb/development.Dockerfile +++ b/build/ferretdb/development.Dockerfile @@ -12,7 +12,7 @@ ARG LABEL_COMMIT # prepare stage -FROM --platform=$BUILDPLATFORM golang:1.23.1 AS development-prepare +FROM --platform=$BUILDPLATFORM golang:1.23.2 AS development-prepare # use a single directory for all Go caches to simpliy RUN --mount commands below ENV GOPATH=/cache/gopath @@ -36,7 +36,7 @@ EOF # build stage -FROM golang:1.23.1 AS development-build +FROM golang:1.23.2 AS development-build ARG TARGETARCH ARG TARGETVARIANT @@ -107,7 +107,7 @@ COPY --from=development-build /src/bin/ferretdb /ferretdb # final stage -FROM golang:1.23.1 AS development +FROM golang:1.23.2 AS development ENV GOCOVERDIR=/tmp/cover ENV GORACE=halt_on_error=1,history_size=2 diff --git a/build/ferretdb/production.Dockerfile b/build/ferretdb/production.Dockerfile index 5e2ea9e2ec38..d6fd043095f6 100644 --- a/build/ferretdb/production.Dockerfile +++ b/build/ferretdb/production.Dockerfile @@ -12,7 +12,7 @@ ARG LABEL_COMMIT # prepare stage -FROM --platform=$BUILDPLATFORM golang:1.23.1 AS production-prepare +FROM --platform=$BUILDPLATFORM golang:1.23.2 AS production-prepare # use a single directory for all Go caches to simpliy RUN --mount commands below ENV GOPATH=/cache/gopath @@ -36,7 +36,7 @@ EOF # build stage -FROM golang:1.23.1 AS production-build +FROM golang:1.23.2 AS production-build ARG TARGETARCH ARG TARGETVARIANT diff --git a/go.mod b/go.mod index daa60ed5c51d..3ceb06bb948d 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/FerretDB/FerretDB go 1.23 -toolchain go1.23.1 +toolchain go1.23.2 require ( github.com/AlekSi/pointer v1.2.0 diff --git a/integration/go.mod b/integration/go.mod index dd970720fccd..c514e1d24829 100644 --- a/integration/go.mod +++ b/integration/go.mod @@ -2,7 +2,7 @@ module github.com/FerretDB/FerretDB/integration go 1.23 -toolchain go1.23.1 +toolchain go1.23.2 replace github.com/FerretDB/FerretDB => ../ diff --git a/tools/definedockertag/main.go b/tools/definedockertag/main.go new file mode 100644 index 000000000000..b56d78fa9242 --- /dev/null +++ b/tools/definedockertag/main.go @@ -0,0 +1,302 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package main contains tool for defining Docker image tags on CI. +// +//nolint:goconst // "ferretdb" means different things +package main + +import ( + "flag" + "fmt" + "os" + "regexp" + "slices" + "strings" + "text/tabwriter" + + "github.com/sethvargo/go-githubactions" +) + +func main() { + flag.Parse() + + action := githubactions.New() + + debugEnv(action) + + res, err := define(action.Getenv) + if err != nil { + action.Fatalf("%s", err) + } + + setResults(action, res) +} + +// result represents Docker image names and tags extracted from the environment. +type result struct { + allInOneImages []string + developmentImages []string + productionImages []string +} + +// semVerTag is a https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string, +// but with a leading `v`. +// +//nolint:lll // for readibility +var semVerTag = regexp.MustCompile(`^v(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) + +// debugEnv logs all environment variables that start with `GITHUB_` or `INPUT_` +// in debug level. +func debugEnv(action *githubactions.Action) { + res := make([]string, 0, 30) + + for _, l := range os.Environ() { + if strings.HasPrefix(l, "GITHUB_") || strings.HasPrefix(l, "INPUT_") { + res = append(res, l) + } + } + + slices.Sort(res) + + action.Debugf("Dumping environment variables:") + + for _, l := range res { + action.Debugf("\t%s", l) + } +} + +// Define extracts Docker image names and tags from the environment variables defined by GitHub Actions. +func define(getenv githubactions.GetenvFunc) (*result, error) { + repo := getenv("GITHUB_REPOSITORY") + + // to support GitHub forks + parts := strings.Split(strings.ToLower(repo), "/") + if len(parts) != 2 { + return nil, fmt.Errorf("failed to split %q into owner and name", repo) + } + owner := parts[0] + repo = parts[1] + + var res *result + var err error + + switch event := getenv("GITHUB_EVENT_NAME"); event { + case "pull_request", "pull_request_target": + branch := strings.ToLower(getenv("GITHUB_HEAD_REF")) + res = defineForPR(owner, repo, branch) + + case "push", "schedule", "workflow_run": + refName := strings.ToLower(getenv("GITHUB_REF_NAME")) + + switch refType := strings.ToLower(getenv("GITHUB_REF_TYPE")); refType { + case "branch": + res, err = defineForBranch(owner, repo, refName) + + case "tag": + match := semVerTag.FindStringSubmatch(refName) + if match == nil || len(match) != semVerTag.NumSubexp()+1 { + return nil, fmt.Errorf("unexpected git tag %q", refName) + } + + major := match[semVerTag.SubexpIndex("major")] + minor := match[semVerTag.SubexpIndex("minor")] + patch := match[semVerTag.SubexpIndex("patch")] + prerelease := match[semVerTag.SubexpIndex("prerelease")] + + var tags []string + if prerelease == "" { + tags = []string{ + major, + major + "." + minor, + major + "." + minor + "." + patch, + // No "latest", because we don't know if, say, 2.0.2 is really the latest version + // (for example, when 2.1.0 already exists). + } + } else { + tags = []string{major + "." + minor + "." + patch + "-" + prerelease} + } + + res = defineForTag(owner, repo, tags) + + default: + err = fmt.Errorf("unhandled ref type %q for event %q", refType, event) + } + + default: + err = fmt.Errorf("unhandled event type %q", event) + } + + if err != nil { + return nil, err + } + + slices.Sort(res.allInOneImages) + slices.Sort(res.developmentImages) + slices.Sort(res.productionImages) + + return res, nil +} + +// allInOneRepo returns a part of Docker repository name for the given GitHub repository name. +func allInOneRepo(repo string) string { + if repo == "ferretdb" { + return "all-in-one" + } + + return repo + "-all-in-one" +} + +// defineForPR defines Docker image names and tags for pull requests. +func defineForPR(owner, repo, branch string) *result { + // for branches like "dependabot/submodules/XXX" + parts := strings.Split(branch, "/") + branch = parts[len(parts)-1] + + res := &result{ + allInOneImages: []string{ + fmt.Sprintf("ghcr.io/%s/%s:pr-%s", owner, allInOneRepo(repo), branch), + }, + developmentImages: []string{ + fmt.Sprintf("ghcr.io/%s/%s-dev:pr-%s", owner, repo, branch), + }, + } + + // PRs are only for testing; no Quay.io and Docker Hub repos + + return res +} + +// defineForBranch defines Docker image names and tags for branch builds. +func defineForBranch(owner, repo, branch string) (*result, error) { + // see packages.yml + switch { + case branch == "main": + fallthrough + case strings.HasPrefix(branch, "main-"): + fallthrough + case strings.HasPrefix(branch, "releases/"): + branch = strings.ReplaceAll(branch, "/", "-") + + default: + return nil, fmt.Errorf("unhandled branch %q", branch) + } + + res := &result{ + allInOneImages: []string{ + fmt.Sprintf("ghcr.io/%s/%s:%s", owner, allInOneRepo(repo), branch), + }, + developmentImages: []string{ + fmt.Sprintf("ghcr.io/%s/%s-dev:%s", owner, repo, branch), + }, + } + + // forks don't have Quay.io and Docker Hub orgs + if owner != "ferretdb" { + return res, nil + } + + // we don't have Quay.io and Docker Hub repos for other GitHub repos + if repo != "ferretdb" { + return res, nil + } + + res.allInOneImages = append(res.allInOneImages, fmt.Sprintf("quay.io/ferretdb/all-in-one:%s", branch)) + res.developmentImages = append(res.developmentImages, fmt.Sprintf("quay.io/ferretdb/ferretdb-dev:%s", branch)) + + res.allInOneImages = append(res.allInOneImages, fmt.Sprintf("ferretdb/all-in-one:%s", branch)) + res.developmentImages = append(res.developmentImages, fmt.Sprintf("ferretdb/ferretdb-dev:%s", branch)) + + return res, nil +} + +// defineForTag defines Docker image names and tags for prerelease tag builds. +func defineForTag(owner, repo string, tags []string) *result { + res := new(result) + + for _, t := range tags { + res.allInOneImages = append(res.allInOneImages, fmt.Sprintf("ghcr.io/%s/%s:%s", owner, allInOneRepo(repo), t)) + res.developmentImages = append(res.developmentImages, fmt.Sprintf("ghcr.io/%s/%s-dev:%s", owner, repo, t)) + res.productionImages = append(res.productionImages, fmt.Sprintf("ghcr.io/%s/%s:%s", owner, repo, t)) + } + + // forks don't have Quay.io and Docker Hub orgs + if owner != "ferretdb" { + return res + } + + // we don't have Quay.io and Docker Hub repos for other GitHub repos + if repo != "ferretdb" { + return res + } + + for _, t := range tags { + res.allInOneImages = append(res.allInOneImages, fmt.Sprintf("quay.io/ferretdb/all-in-one:%s", t)) + res.developmentImages = append(res.developmentImages, fmt.Sprintf("quay.io/ferretdb/ferretdb-dev:%s", t)) + res.productionImages = append(res.productionImages, fmt.Sprintf("quay.io/ferretdb/ferretdb:%s", t)) + + res.allInOneImages = append(res.allInOneImages, fmt.Sprintf("ferretdb/all-in-one:%s", t)) + res.developmentImages = append(res.developmentImages, fmt.Sprintf("ferretdb/ferretdb-dev:%s", t)) + res.productionImages = append(res.productionImages, fmt.Sprintf("ferretdb/ferretdb:%s", t)) + } + + return res +} + +// setResults sets action output parameters, summary, etc. +func setResults(action *githubactions.Action, res *result) { + var buf strings.Builder + w := tabwriter.NewWriter(&buf, 1, 1, 1, ' ', tabwriter.Debug) + fmt.Fprintf(w, "\tType\tImage\t\n") + fmt.Fprintf(w, "\t----\t-----\t\n") + + for _, image := range res.allInOneImages { + u := imageURL(image) + fmt.Fprintf(w, "\tAll-in-one\t[`%s`](%s)\t\n", image, u) + } + + for _, image := range res.developmentImages { + u := imageURL(image) + fmt.Fprintf(w, "\tDevelopment\t[`%s`](%s)\t\n", image, u) + } + + for _, image := range res.productionImages { + u := imageURL(image) + fmt.Fprintf(w, "\tProduction\t[`%s`](%s)\t\n", image, u) + } + + _ = w.Flush() + + action.AddStepSummary(buf.String()) + action.Infof("%s", buf.String()) + + action.SetOutput("all_in_one_images", strings.Join(res.allInOneImages, ",")) + action.SetOutput("development_images", strings.Join(res.developmentImages, ",")) + action.SetOutput("production_images", strings.Join(res.productionImages, ",")) +} + +// imageURL returns HTML page URL for the given image name and tag. +func imageURL(name string) string { + switch { + case strings.HasPrefix(name, "ghcr.io/"): + return fmt.Sprintf("https://%s", name) + case strings.HasPrefix(name, "quay.io/"): + return fmt.Sprintf("https://%s", name) + } + + name, _, _ = strings.Cut(name, ":") + + // there is not easy way to get Docker Hub URL for the given tag + return fmt.Sprintf("https://hub.docker.com/r/%s/tags", name) +} diff --git a/tools/definedockertag/main_test.go b/tools/definedockertag/main_test.go new file mode 100644 index 000000000000..72c5d798f225 --- /dev/null +++ b/tools/definedockertag/main_test.go @@ -0,0 +1,889 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "io" + "os" + "strings" + "testing" + + "github.com/sethvargo/go-githubactions" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// getEnvFunc implements [os.Getenv] for testing. +func getEnvFunc(t *testing.T, env map[string]string) func(string) string { + t.Helper() + + return func(key string) string { + val, ok := env[key] + require.True(t, ok, "missing key %q", key) + + return val + } +} + +func TestDefineFerretDB(t *testing.T) { + t.Run("pull_request", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request", + "GITHUB_HEAD_REF": "define-docker-tag", + "GITHUB_REF_NAME": "1/merge", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/all-in-one:pr-define-docker-tag", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/ferretdb-dev:pr-define-docker-tag", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("pull_request_target", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request_target", + "GITHUB_HEAD_REF": "define-docker-tag", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/all-in-one:pr-define-docker-tag", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/ferretdb-dev:pr-define-docker-tag", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("pull_request/dependabot", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request", + "GITHUB_HEAD_REF": "dependabot/submodules/tests/mongo-go-driver-29d768e", + "GITHUB_REF_NAME": "58/merge", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/all-in-one:pr-mongo-go-driver-29d768e", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/ferretdb-dev:pr-mongo-go-driver-29d768e", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/main", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:main", + "ghcr.io/ferretdb/all-in-one:main", + "quay.io/ferretdb/all-in-one:main", + }, + developmentImages: []string{ + "ferretdb/ferretdb-dev:main", + "ghcr.io/ferretdb/ferretdb-dev:main", + "quay.io/ferretdb/ferretdb-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/release", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "releases/2.1", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:releases-2.1", + "ghcr.io/ferretdb/all-in-one:releases-2.1", + "quay.io/ferretdb/all-in-one:releases-2.1", + }, + developmentImages: []string{ + "ferretdb/ferretdb-dev:releases-2.1", + "ghcr.io/ferretdb/ferretdb-dev:releases-2.1", + "quay.io/ferretdb/ferretdb-dev:releases-2.1", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/beta", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "v2.1.0-beta", + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:2.1.0-beta", + "ghcr.io/ferretdb/all-in-one:2.1.0-beta", + "quay.io/ferretdb/all-in-one:2.1.0-beta", + }, + developmentImages: []string{ + "ferretdb/ferretdb-dev:2.1.0-beta", + "ghcr.io/ferretdb/ferretdb-dev:2.1.0-beta", + "quay.io/ferretdb/ferretdb-dev:2.1.0-beta", + }, + productionImages: []string{ + "ferretdb/ferretdb:2.1.0-beta", + "ghcr.io/ferretdb/ferretdb:2.1.0-beta", + "quay.io/ferretdb/ferretdb:2.1.0-beta", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/release", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "v2.1.0", + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:2", + "ferretdb/all-in-one:2.1", + "ferretdb/all-in-one:2.1.0", + "ghcr.io/ferretdb/all-in-one:2", + "ghcr.io/ferretdb/all-in-one:2.1", + "ghcr.io/ferretdb/all-in-one:2.1.0", + "quay.io/ferretdb/all-in-one:2", + "quay.io/ferretdb/all-in-one:2.1", + "quay.io/ferretdb/all-in-one:2.1.0", + }, + developmentImages: []string{ + "ferretdb/ferretdb-dev:2", + "ferretdb/ferretdb-dev:2.1", + "ferretdb/ferretdb-dev:2.1.0", + "ghcr.io/ferretdb/ferretdb-dev:2", + "ghcr.io/ferretdb/ferretdb-dev:2.1", + "ghcr.io/ferretdb/ferretdb-dev:2.1.0", + "quay.io/ferretdb/ferretdb-dev:2", + "quay.io/ferretdb/ferretdb-dev:2.1", + "quay.io/ferretdb/ferretdb-dev:2.1.0", + }, + productionImages: []string{ + "ferretdb/ferretdb:2", + "ferretdb/ferretdb:2.1", + "ferretdb/ferretdb:2.1.0", + "ghcr.io/ferretdb/ferretdb:2", + "ghcr.io/ferretdb/ferretdb:2.1", + "ghcr.io/ferretdb/ferretdb:2.1.0", + "quay.io/ferretdb/ferretdb:2", + "quay.io/ferretdb/ferretdb:2.1", + "quay.io/ferretdb/ferretdb:2.1.0", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/wrong", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "2.1.0", // no leading v + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + _, err := define(getenv) + require.Error(t, err) + }) + + t.Run("schedule", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "schedule", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:main", + "ghcr.io/ferretdb/all-in-one:main", + "quay.io/ferretdb/all-in-one:main", + }, + developmentImages: []string{ + "ferretdb/ferretdb-dev:main", + "ghcr.io/ferretdb/ferretdb-dev:main", + "quay.io/ferretdb/ferretdb-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("workflow_run", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "workflow_run", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:main", + "ghcr.io/ferretdb/all-in-one:main", + "quay.io/ferretdb/all-in-one:main", + }, + developmentImages: []string{ + "ferretdb/ferretdb-dev:main", + "ghcr.io/ferretdb/ferretdb-dev:main", + "quay.io/ferretdb/ferretdb-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) +} + +func TestDefineOtherOrg(t *testing.T) { + t.Run("pull_request", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request", + "GITHUB_HEAD_REF": "define-docker-tag", + "GITHUB_REF_NAME": "1/merge", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:pr-define-docker-tag", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:pr-define-docker-tag", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("pull_request_target", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request_target", + "GITHUB_HEAD_REF": "define-docker-tag", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:pr-define-docker-tag", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:pr-define-docker-tag", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("pull_request/dependabot", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request", + "GITHUB_HEAD_REF": "dependabot/submodules/tests/mongo-go-driver-29d768e", + "GITHUB_REF_NAME": "58/merge", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:pr-mongo-go-driver-29d768e", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:pr-mongo-go-driver-29d768e", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/main", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:main", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/release", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "releases/2.1", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:releases-2.1", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:releases-2.1", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/beta", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "v2.1.0-beta", + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:2.1.0-beta", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:2.1.0-beta", + }, + productionImages: []string{ + "ghcr.io/otherorg/ferretdb:2.1.0-beta", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/release", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "v2.1.0", + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:2", + "ghcr.io/otherorg/all-in-one:2.1", + "ghcr.io/otherorg/all-in-one:2.1.0", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:2", + "ghcr.io/otherorg/ferretdb-dev:2.1", + "ghcr.io/otherorg/ferretdb-dev:2.1.0", + }, + productionImages: []string{ + "ghcr.io/otherorg/ferretdb:2", + "ghcr.io/otherorg/ferretdb:2.1", + "ghcr.io/otherorg/ferretdb:2.1.0", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/wrong", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "2.1.0", // no leading v + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + _, err := define(getenv) + require.Error(t, err) + }) + + t.Run("schedule", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "schedule", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:main", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("workflow_run", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "workflow_run", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "OtherOrg/FerretDB", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/otherorg/all-in-one:main", + }, + developmentImages: []string{ + "ghcr.io/otherorg/ferretdb-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) +} + +func TestDefineOtherRepo(t *testing.T) { + t.Run("pull_request", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request", + "GITHUB_HEAD_REF": "define-docker-tag", + "GITHUB_REF_NAME": "1/merge", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:pr-define-docker-tag", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:pr-define-docker-tag", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("pull_request_target", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request_target", + "GITHUB_HEAD_REF": "define-docker-tag", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:pr-define-docker-tag", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:pr-define-docker-tag", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("pull_request/dependabot", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "main", + "GITHUB_EVENT_NAME": "pull_request", + "GITHUB_HEAD_REF": "dependabot/submodules/tests/mongo-go-driver-29d768e", + "GITHUB_REF_NAME": "58/merge", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:pr-mongo-go-driver-29d768e", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:pr-mongo-go-driver-29d768e", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/main", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:main", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/release", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "releases/2.1", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:releases-2.1", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:releases-2.1", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/beta", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "v2.1.0-beta", + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:2.1.0-beta", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:2.1.0-beta", + }, + productionImages: []string{ + "ghcr.io/ferretdb/otherrepo:2.1.0-beta", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/release", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "v2.1.0", + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:2", + "ghcr.io/ferretdb/otherrepo-all-in-one:2.1", + "ghcr.io/ferretdb/otherrepo-all-in-one:2.1.0", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:2", + "ghcr.io/ferretdb/otherrepo-dev:2.1", + "ghcr.io/ferretdb/otherrepo-dev:2.1.0", + }, + productionImages: []string{ + "ghcr.io/ferretdb/otherrepo:2", + "ghcr.io/ferretdb/otherrepo:2.1", + "ghcr.io/ferretdb/otherrepo:2.1.0", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("push/tag/wrong", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "push", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "2.1.0", // no leading v + "GITHUB_REF_TYPE": "tag", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + _, err := define(getenv) + require.Error(t, err) + }) + + t.Run("schedule", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "schedule", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:main", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) + + t.Run("workflow_run", func(t *testing.T) { + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_BASE_REF": "", + "GITHUB_EVENT_NAME": "workflow_run", + "GITHUB_HEAD_REF": "", + "GITHUB_REF_NAME": "main", + "GITHUB_REF_TYPE": "branch", + "GITHUB_REPOSITORY": "FerretDB/OtherRepo", + }) + + actual, err := define(getenv) + require.NoError(t, err) + + expected := &result{ + allInOneImages: []string{ + "ghcr.io/ferretdb/otherrepo-all-in-one:main", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/otherrepo-dev:main", + }, + } + assert.Equal(t, expected, actual) + }) +} + +//nolint:lll // it is more readable this way +func TestImageURL(t *testing.T) { + // expected URLs should work + assert.Equal(t, "https://ghcr.io/ferretdb/all-in-one:pr-define-docker-tag", imageURL("ghcr.io/ferretdb/all-in-one:pr-define-docker-tag")) + assert.Equal(t, "https://quay.io/ferretdb/all-in-one:pr-define-docker-tag", imageURL("quay.io/ferretdb/all-in-one:pr-define-docker-tag")) + assert.Equal(t, "https://hub.docker.com/r/ferretdb/all-in-one/tags", imageURL("ferretdb/all-in-one:pr-define-docker-tag")) +} + +func TestResults(t *testing.T) { + dir := t.TempDir() + + summaryF, err := os.CreateTemp(dir, "summary") + require.NoError(t, err) + defer summaryF.Close() //nolint:errcheck // temporary file for testing + + outputF, err := os.CreateTemp(dir, "output") + require.NoError(t, err) + defer outputF.Close() //nolint:errcheck // temporary file for testing + + var stdout bytes.Buffer + getenv := getEnvFunc(t, map[string]string{ + "GITHUB_STEP_SUMMARY": summaryF.Name(), + "GITHUB_OUTPUT": outputF.Name(), + }) + action := githubactions.New(githubactions.WithGetenv(getenv), githubactions.WithWriter(&stdout)) + + result := &result{ + allInOneImages: []string{ + "ferretdb/all-in-one:2.1.0", + }, + developmentImages: []string{ + "ghcr.io/ferretdb/ferretdb-dev:2", + }, + productionImages: []string{ + "quay.io/ferretdb/ferretdb:latest", + }, + } + + setResults(action, result) + + expectedStdout := strings.ReplaceAll(` + |Type |Image | + |---- |----- | + |All-in-one |['ferretdb/all-in-one:2.1.0'](https://hub.docker.com/r/ferretdb/all-in-one/tags) | + |Development |['ghcr.io/ferretdb/ferretdb-dev:2'](https://ghcr.io/ferretdb/ferretdb-dev:2) | + |Production |['quay.io/ferretdb/ferretdb:latest'](https://quay.io/ferretdb/ferretdb:latest) | + +`[1:], "'", "`") + assert.Equal(t, expectedStdout, stdout.String(), "stdout does not match") + + expectedSummary := strings.ReplaceAll(` + |Type |Image | + |---- |----- | + |All-in-one |['ferretdb/all-in-one:2.1.0'](https://hub.docker.com/r/ferretdb/all-in-one/tags) | + |Development |['ghcr.io/ferretdb/ferretdb-dev:2'](https://ghcr.io/ferretdb/ferretdb-dev:2) | + |Production |['quay.io/ferretdb/ferretdb:latest'](https://quay.io/ferretdb/ferretdb:latest) | + +`[1:], "'", "`") + b, err := io.ReadAll(summaryF) + require.NoError(t, err) + assert.Equal(t, expectedSummary, string(b), "summary does not match") + + expectedOutput := ` +all_in_one_images<<_GitHubActionsFileCommandDelimeter_ +ferretdb/all-in-one:2.1.0 +_GitHubActionsFileCommandDelimeter_ +development_images<<_GitHubActionsFileCommandDelimeter_ +ghcr.io/ferretdb/ferretdb-dev:2 +_GitHubActionsFileCommandDelimeter_ +production_images<<_GitHubActionsFileCommandDelimeter_ +quay.io/ferretdb/ferretdb:latest +_GitHubActionsFileCommandDelimeter_ +`[1:] + b, err = io.ReadAll(outputF) + require.NoError(t, err) + assert.Equal(t, expectedOutput, string(b), "output parameters does not match") +} diff --git a/tools/go.mod b/tools/go.mod index f95e74606606..2eb008484122 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -2,7 +2,7 @@ module github.com/FerretDB/FerretDB/tools go 1.23 -toolchain go1.23.1 +toolchain go1.23.2 require ( github.com/AlekSi/pointer v1.2.0 @@ -12,6 +12,7 @@ require ( github.com/goreleaser/nfpm/v2 v2.39.0 github.com/quasilyte/go-consistent v0.6.1 github.com/rogpeppe/go-internal v1.12.0 + github.com/sethvargo/go-githubactions v1.3.0 github.com/stretchr/testify v1.9.0 golang.org/x/perf v0.0.0-20240806191124-3f62151e343c golang.org/x/pkgsite v0.0.0-20240824135812-676c19eae995 diff --git a/tools/go.sum b/tools/go.sum index 0fe22b2a089c..3d86289e444e 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -219,6 +219,8 @@ github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtC github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sethvargo/go-githubactions v1.3.0 h1:Kg633LIUV2IrJsqy2MfveiED/Ouo+H2P0itWS0eLh8A= +github.com/sethvargo/go-githubactions v1.3.0/go.mod h1:7/4WeHgYfSz9U5vwuToCK9KPnELVHAhGtRwLREOQV80= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= diff --git a/tools/golangci/go.mod b/tools/golangci/go.mod index 813538eb6bbb..9fb5e02b3a2d 100644 --- a/tools/golangci/go.mod +++ b/tools/golangci/go.mod @@ -4,7 +4,7 @@ module github.com/FerretDB/FerretDB/tools/golangci go 1.23 -toolchain go1.23.1 +toolchain go1.23.2 require github.com/golangci/golangci-lint v1.60.3 diff --git a/tools/tools.go b/tools/tools.go index 30b350060cb3..b332068e8bf9 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -27,9 +27,10 @@ import ( _ "mvdan.cc/gofumpt" ) +//go:generate go build -v -o ../bin/ ./checkcomments //go:generate go build -v -o ../bin/ ./checkdocs //go:generate go build -v -o ../bin/ ./checkswitch -//go:generate go build -v -o ../bin/ ./checkcomments +//go:generate go build -v -o ../bin/ ./definedockertag //go:generate go build -v -o ../bin/ ./generatechangelog //go:generate go build -v -o ../bin/ github.com/go-task/task/v3/cmd/task diff --git a/website/go.mod b/website/go.mod index 447402c4d7a4..a4f11c235c61 100644 --- a/website/go.mod +++ b/website/go.mod @@ -5,4 +5,4 @@ module ferretdb.com/website go 1.23 -toolchain go1.23.1 +toolchain go1.23.2