mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 12:51:55 +00:00
executors: Provide more context when the semantic version is invalid (#55024)
The annoying error of `Invalid Semantic Version` tells us nothing and makes troubleshooting the issue difficult with lots of churn. I have update Executor usage of `semvar.NewVersion` to wrap the error with a message that include the actual version that causes the error. This will help us understand the specific version string that is causing the error and more quickly determine _why_ the version is getting injected. ## Test plan Update/add Go tests.
This commit is contained in:
parent
ea88de6697
commit
5a3fda4bd6
@ -323,6 +323,7 @@ go_library(
|
||||
"//internal/version",
|
||||
"//internal/version/upgradestore",
|
||||
"//internal/webhooks/outbound",
|
||||
"//lib/api",
|
||||
"//lib/batches",
|
||||
"//lib/errors",
|
||||
"//lib/output",
|
||||
|
||||
@ -11,6 +11,8 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/gqlutil"
|
||||
"github.com/sourcegraph/sourcegraph/internal/types"
|
||||
"github.com/sourcegraph/sourcegraph/internal/version"
|
||||
"github.com/sourcegraph/sourcegraph/lib/api"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
const oneReleaseCycle = 35 * 24 * time.Hour
|
||||
@ -122,12 +124,12 @@ func calculateExecutorCompatibility(ev string) (*string, error) {
|
||||
return compatibility.ToGraphQL(), nil
|
||||
}
|
||||
|
||||
s, err := semver.NewVersion(sv)
|
||||
s, err := getSemVer("sourcegraph", sv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e, err := semver.NewVersion(ev)
|
||||
e, err := getSemVer("executor", ev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -145,3 +147,24 @@ func calculateExecutorCompatibility(ev string) (*string, error) {
|
||||
|
||||
return compatibility.ToGraphQL(), nil
|
||||
}
|
||||
|
||||
func getSemVer(source string, version string) (*semver.Version, error) {
|
||||
v, err := semver.NewVersion(version)
|
||||
if err != nil {
|
||||
// Maybe the version is a daily build and need to extract the version from there.
|
||||
// We don't care about the error from getDailyBuildVersion because we already have the error.
|
||||
v, _ = getDailyBuildVersion(version)
|
||||
if v == nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse %s version %q", source, version)
|
||||
}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func getDailyBuildVersion(version string) (*semver.Version, error) {
|
||||
matches := api.BuildDateRegex.FindStringSubmatch(version)
|
||||
if len(matches) > 2 {
|
||||
return semver.NewVersion(matches[2])
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -1,183 +1,236 @@
|
||||
package graphqlbackend
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/version"
|
||||
)
|
||||
|
||||
func TestExecutorResolver(t *testing.T) {
|
||||
t.Run("isExecutorOutdated", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
executorVersion string
|
||||
sourcegraphVersion string
|
||||
isActive bool
|
||||
expected *string
|
||||
description string
|
||||
}{
|
||||
// The executor isn't outdated when in dev mode.
|
||||
{
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "executor and the Sourcegraph instance are in dev mode",
|
||||
},
|
||||
// The executor isn't outdated when it's inactive
|
||||
{
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: false,
|
||||
expected: nil,
|
||||
description: "executor is inactive",
|
||||
},
|
||||
// The executor is not outdated if it's one minor version behind the sourcegraph version (SEMVER)
|
||||
{
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.42.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityUpToDate.ToGraphQL(),
|
||||
description: "executor is one version ahead of the Sourcegraph instance",
|
||||
},
|
||||
// The executor is not outdated if it's one minor version ahead of the sourcegraph version (SEMVER)
|
||||
{
|
||||
executorVersion: "3.42.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityUpToDate.ToGraphQL(),
|
||||
description: "executor is one minor version ahead of the Sourcegraph instance",
|
||||
},
|
||||
// The executor is not outdated when both sourcegraph and executor are the same (SEMVER).
|
||||
{
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityUpToDate.ToGraphQL(),
|
||||
description: "executor and the sourcegraph instance are the same version (SEMVER)",
|
||||
},
|
||||
// The executor is not outdated when both sourcegraph and executor are the same (insiders).
|
||||
{
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-08-25_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-08-25_4.4-a2b623dce148",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityUpToDate.ToGraphQL(),
|
||||
description: "executor and the sourcegraph instance are the same version (insiders)",
|
||||
},
|
||||
{
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-08-25_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-08-25_a2b623dce148",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityUpToDate.ToGraphQL(),
|
||||
description: "executor and the sourcegraph instance are the same version (insiders - old version)",
|
||||
},
|
||||
// The executor is outdated if the sourcegraph version is more than one version
|
||||
// greater than the executor version (SEMVER).
|
||||
{
|
||||
executorVersion: "3.40.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityOutdated.ToGraphQL(),
|
||||
description: "executor is more than one minor version behind the Sourcegraph instance (SEMVER)",
|
||||
},
|
||||
{
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "4.0.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityOutdated.ToGraphQL(),
|
||||
description: "Sourcegraph instance is a major version ahead of the executor",
|
||||
},
|
||||
// The executor is too new if the executor is more than one version ahead of the sourcegraph version.
|
||||
{
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.40.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityVersionAhead.ToGraphQL(),
|
||||
description: "executor is more than one minor version ahead of the Sourcegraph instance (SEMVER)",
|
||||
},
|
||||
{
|
||||
executorVersion: "4.0.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityVersionAhead.ToGraphQL(),
|
||||
description: "executor is a major version ahead of the Sourcegraph instance",
|
||||
},
|
||||
// The executor is outdated if the sourcegraph version is greater than the executor version (insiders).
|
||||
{
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-06-10_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-07-25_a2b623dce148",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityOutdated.ToGraphQL(),
|
||||
description: "executor version is less than the Sourcegraph build date - one release cycle (insiders)",
|
||||
},
|
||||
// The executor is too new if the executor version is greater than the one release cycle + sourcegraph build date (insiders)
|
||||
{
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-10-30_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-09-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityVersionAhead.ToGraphQL(),
|
||||
description: "executor version is greater than the one release cycle + Sourcegraph build date (insiders)",
|
||||
},
|
||||
// The executor is up to date if the build date isn't greater than one release cycle + sourcegraph build date (insiders)
|
||||
{
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-08-20_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-08-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expected: ExecutorCompatibilityUpToDate.ToGraphQL(),
|
||||
description: "executor version is a few days ahead of the Sourcegraph instance (insiders)",
|
||||
},
|
||||
// version mismatch
|
||||
{
|
||||
executorVersion: "3.36.2",
|
||||
sourcegraphVersion: "169135_2022-08-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "Sourcegraph instance is on insiders version while the executor is tagged",
|
||||
},
|
||||
{
|
||||
executorVersion: "169135_2022-08-15_a2b623dce148",
|
||||
sourcegraphVersion: "3.39.2",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "executor is on insiders version while the Sourcegraph instance is tagged",
|
||||
},
|
||||
{
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "3.39.2",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "executor is in dev mode while Sourcegraph instance is tagged",
|
||||
},
|
||||
{
|
||||
executorVersion: "3.39.2",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "Sourcegraph instance is in dev mode while executor is tagged",
|
||||
},
|
||||
{
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "169135_2022-08-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "executor is in dev mode while Sourcegraph instance is on insiders version",
|
||||
},
|
||||
{
|
||||
executorVersion: "169135_2022-08-15_a2b623dce148",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: true,
|
||||
expected: nil,
|
||||
description: "Sourcegraph instance is in dev mode while executor is on insiders version",
|
||||
},
|
||||
}
|
||||
func TestCalculateExecutorCompatibility(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
executorVersion string
|
||||
sourcegraphVersion string
|
||||
isActive bool
|
||||
expectedCompatibility ExecutorCompatibility
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "Dev mode",
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Executor is inactive",
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: false,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Executor is one minor version behind",
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.42.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor is one minor version behind",
|
||||
executorVersion: "3.42.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor is the same version as the Sourcegraph instance",
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor is the same version as the Sourcegraph instance (insiders)",
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-08-25_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-08-25_4.4-a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor is the same version as the Sourcegraph instance (insiders - old version)",
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-08-25_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-08-25_a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor is multiple minor versions behind",
|
||||
executorVersion: "3.40.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityOutdated,
|
||||
},
|
||||
{
|
||||
name: "Executor is major version behind",
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "4.0.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityOutdated,
|
||||
},
|
||||
{
|
||||
name: "Executor is multiple patch versions behind",
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.43.12",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor is multiple minor version ahead",
|
||||
executorVersion: "3.43.0",
|
||||
sourcegraphVersion: "3.40.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityVersionAhead,
|
||||
},
|
||||
{
|
||||
executorVersion: "4.0.0",
|
||||
sourcegraphVersion: "3.43.0",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityVersionAhead,
|
||||
},
|
||||
{
|
||||
name: "Executor is one release cycle behind (insiders)",
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-06-10_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-07-25_a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityOutdated,
|
||||
},
|
||||
{
|
||||
name: "Executor is one release cycle ahead (insiders)",
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-10-30_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-09-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityVersionAhead,
|
||||
},
|
||||
{
|
||||
name: "Execcutor build date is greater than one release cycle + sourcegraph build date (insiders)",
|
||||
executorVersion: "executor-patch-notest-es-ignite-debug_168065_2022-08-20_e94e18c4ebcc_patch",
|
||||
sourcegraphVersion: "169135_2022-08-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Sourcegrpah version mismatch",
|
||||
executorVersion: "3.36.2",
|
||||
sourcegraphVersion: "169135_2022-08-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Executor version mismatch",
|
||||
executorVersion: "169135_2022-08-15_a2b623dce148",
|
||||
sourcegraphVersion: "3.39.2",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Executor is in dev mode",
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "3.39.2",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Sourcegraph instance is in dev mode",
|
||||
executorVersion: "3.39.2",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Executor is in dev mode and Sourcegraph instance is on insiders version",
|
||||
executorVersion: "0.0.0+dev",
|
||||
sourcegraphVersion: "169135_2022-08-15_a2b623dce148",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Sourcegraph instance is in dev mode and executor is on insiders version",
|
||||
executorVersion: "169135_2022-08-15_a2b623dce148",
|
||||
sourcegraphVersion: "0.0.0+dev",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
},
|
||||
{
|
||||
name: "Executor version is an invalid semver",
|
||||
executorVersion: "\n1.2",
|
||||
sourcegraphVersion: "3.39.2",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
expectedError: errors.New("failed to parse executor version \"\\n1.2\": Invalid Semantic Version"),
|
||||
},
|
||||
{
|
||||
name: "Sourcegraph version is an invalid semver",
|
||||
executorVersion: "4.0.1",
|
||||
sourcegraphVersion: "\n1.2",
|
||||
isActive: true,
|
||||
expectedCompatibility: "",
|
||||
expectedError: errors.New("failed to parse sourcegraph version \"\\n1.2\": Invalid Semantic Version"),
|
||||
},
|
||||
{
|
||||
name: "Executor release branch build",
|
||||
executorVersion: "5.1_231128_2023-06-27_5.0-7ac9ba347103",
|
||||
sourcegraphVersion: "5.0.3",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Sourcegraph release branch build",
|
||||
executorVersion: "5.0.3",
|
||||
sourcegraphVersion: "5.1_231128_2023-06-27_5.0-7ac9ba347103",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor release candidate",
|
||||
executorVersion: "5.1.3-rc.1",
|
||||
sourcegraphVersion: "5.1.3",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
{
|
||||
name: "Executor version missing patch",
|
||||
executorVersion: "5.1",
|
||||
sourcegraphVersion: "5.1.3",
|
||||
isActive: true,
|
||||
expectedCompatibility: ExecutorCompatibilityUpToDate,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
version.Mock(test.sourcegraphVersion)
|
||||
actual, err := calculateExecutorCompatibility(test.executorVersion)
|
||||
|
||||
for _, tc := range testCases {
|
||||
version.Mock(tc.sourcegraphVersion)
|
||||
want, err := calculateExecutorCompatibility(tc.executorVersion)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, want, tc.description)
|
||||
}
|
||||
})
|
||||
if test.expectedError != nil {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, test.expectedError.Error(), err.Error())
|
||||
assert.Nil(t, actual)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
// Once https://github.com/stretchr/testify/pull/1287 is merged, we can remove this and just use Equal.
|
||||
// When they are not equal we are just given the addresses which doesn't mean much to us, and tell us
|
||||
// how to fix the test.
|
||||
if test.expectedCompatibility != "" {
|
||||
require.NotNil(t, actual)
|
||||
assert.Equal(t, test.expectedCompatibility, ExecutorCompatibility(*actual))
|
||||
} else {
|
||||
assert.Nil(t, actual)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ func (h *handler[T]) dequeue(ctx context.Context, queueName string, metadata exe
|
||||
var err error
|
||||
version2Supported, err = api.CheckSourcegraphVersion(metadata.version, "4.3.0-0", "2022-11-24")
|
||||
if err != nil {
|
||||
return executortypes.Job{}, false, err
|
||||
return executortypes.Job{}, false, errors.Wrapf(err, "failed to check version %q", metadata.version)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ func TestHandler_HandleDequeue(t *testing.T) {
|
||||
name: "Invalid version",
|
||||
body: `{"executorName": "test-executor", "version":"\n1.2", "numCPUs": 1, "memory": "1GB", "diskSpace": "10GB"}`,
|
||||
expectedStatusCode: http.StatusInternalServerError,
|
||||
expectedResponseBody: `{"error":"Invalid Semantic Version"}`,
|
||||
expectedResponseBody: `{"error":"failed to check version \"\\n1.2\": Invalid Semantic Version"}`,
|
||||
assertionFunc: func(t *testing.T, mockStore *dbworkerstoremocks.MockStore[testRecord], jobTokenStore *executorstore.MockJobTokenStore) {
|
||||
require.Len(t, mockStore.DequeueFunc.History(), 0)
|
||||
require.Len(t, jobTokenStore.CreateFunc.History(), 0)
|
||||
|
||||
@ -91,7 +91,7 @@ func (m *MultiHandler) dequeue(ctx context.Context, req executortypes.DequeueReq
|
||||
var err error
|
||||
version2Supported, err = api.CheckSourcegraphVersion(req.Version, "4.3.0-0", "2022-11-24")
|
||||
if err != nil {
|
||||
return executortypes.Job{}, false, err
|
||||
return executortypes.Job{}, false, errors.Wrapf(err, "failed to check version %q", req.Version)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -235,7 +235,7 @@ func TestMultiHandler_HandleDequeue(t *testing.T) {
|
||||
dequeueEvents: []dequeueEvent{
|
||||
{
|
||||
expectedStatusCode: http.StatusInternalServerError,
|
||||
expectedResponseBody: `{"error":"Invalid Semantic Version"}`,
|
||||
expectedResponseBody: `{"error":"failed to check version \"\\n1.2\": Invalid Semantic Version"}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -17,4 +17,9 @@ go_test(
|
||||
timeout = "short",
|
||||
srcs = ["version_check_test.go"],
|
||||
embed = [":api"],
|
||||
deps = [
|
||||
"//lib/errors",
|
||||
"@com_github_stretchr_testify//assert",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
)
|
||||
|
||||
@ -6,8 +6,10 @@ import (
|
||||
"github.com/Masterminds/semver"
|
||||
)
|
||||
|
||||
var buildDate = regexp.MustCompile(`\d+_(\d{4}-\d{2}-\d{2})_(\d+\.\d+-)?[a-z0-9]{7,}(_patch)?$`)
|
||||
// BuildDateRegex matches the build date in a Sourcegraph version string.
|
||||
var BuildDateRegex = regexp.MustCompile(`\d+_(\d{4}-\d{2}-\d{2})_(\d+\.\d+)?-?[a-z0-9]{7,}(_patch)?$`)
|
||||
|
||||
// CheckSourcegraphVersion checks if the given version satisfies the given constraint.
|
||||
// NOTE: A version with a prerelease suffix (e.g. the "-rc.3" of "3.35.1-rc.3") is not
|
||||
// considered by semver to satisfy a constraint without a prerelease suffix, regardless of
|
||||
// whether or not the major/minor/patch version is greater than or equal to that of the
|
||||
@ -28,7 +30,7 @@ func CheckSourcegraphVersion(version, constraint, minDate string) (bool, error)
|
||||
// version string, we match on 7 or more characters. Currently, the Sourcegraph version
|
||||
// is expected to return 12:
|
||||
// https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/blob/enterprise/dev/ci/internal/ci/config.go?L96.
|
||||
matches := buildDate.FindStringSubmatch(version)
|
||||
matches := BuildDateRegex.FindStringSubmatch(version)
|
||||
if len(matches) > 1 {
|
||||
return matches[1] >= minDate, nil
|
||||
}
|
||||
|
||||
@ -1,126 +1,169 @@
|
||||
package api
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
func TestCheckSourcegraphVersion(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
currentVersion, constraint, minDate string
|
||||
expected bool
|
||||
tests := []struct {
|
||||
name string
|
||||
currentVersion string
|
||||
constraint string
|
||||
minDate string
|
||||
expected bool
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "Version matches constraint",
|
||||
currentVersion: "3.12.6",
|
||||
constraint: ">= 3.12.6",
|
||||
minDate: "2020-01-19",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Release candidate version matches constraint",
|
||||
currentVersion: "3.12.6-rc.1",
|
||||
constraint: ">= 3.12.6-0",
|
||||
minDate: "2020-01-19",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Newer release candidate version matches constraint",
|
||||
currentVersion: "3.12.6-rc.3",
|
||||
constraint: ">= 3.10.6-0",
|
||||
minDate: "2020-01-19",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Version does not match constraint",
|
||||
currentVersion: "3.12.6",
|
||||
constraint: ">= 3.13",
|
||||
minDate: "2020-01-19",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Constraint without patch version",
|
||||
currentVersion: "3.13.0",
|
||||
constraint: ">= 3.13",
|
||||
minDate: "2020-01-19",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Dev version",
|
||||
currentVersion: "dev",
|
||||
constraint: ">= 3.13",
|
||||
minDate: "2020-01-19",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Newer dev version",
|
||||
currentVersion: "0.0.0+dev",
|
||||
constraint: ">= 3.13",
|
||||
minDate: "2020-01-19",
|
||||
expected: true,
|
||||
},
|
||||
// 7-character abbreviated hash
|
||||
{
|
||||
name: "Seven character abbreviated hash",
|
||||
currentVersion: "54959_2020-01-29_9258595",
|
||||
minDate: "2020-01-19",
|
||||
constraint: ">= 999.13",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Seven character abbreviated hash too old",
|
||||
currentVersion: "54959_2020-01-29_9258595",
|
||||
minDate: "2020-01-30",
|
||||
constraint: ">= 999.13",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Seven character abbreviated hash matches date",
|
||||
currentVersion: "54959_2020-01-29_9258595",
|
||||
minDate: "2020-01-29",
|
||||
constraint: ">= 0.0",
|
||||
expected: true,
|
||||
},
|
||||
// 12-character abbreviated hash
|
||||
{
|
||||
name: "Twelve character abbreviated hash",
|
||||
currentVersion: "54959_2020-01-29_925859585436",
|
||||
minDate: "2020-01-19",
|
||||
constraint: ">= 999.13",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Twelve character abbreviated hash too old",
|
||||
currentVersion: "54959_2020-01-29_925859585436",
|
||||
minDate: "2020-01-30",
|
||||
constraint: ">= 999.13",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Twelve character abbreviated hash matches date",
|
||||
currentVersion: "54959_2020-01-29_925859585436",
|
||||
minDate: "2020-01-29",
|
||||
constraint: ">= 0.0",
|
||||
expected: true,
|
||||
},
|
||||
// 12-character abbreviated hash with latest version tag
|
||||
{
|
||||
name: "Twelve character abbreviated hash with tag",
|
||||
currentVersion: "54959_2020-01-29_4.4-925859585436",
|
||||
minDate: "2020-01-19",
|
||||
constraint: ">= 999.13",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Twelve character abbreviated hash with tag too old and does not match constraint",
|
||||
currentVersion: "54959_2020-01-29_4.4-925859585436",
|
||||
minDate: "2020-01-30",
|
||||
constraint: ">= 999.13",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Twelve character abbreviated hash with tag matches date",
|
||||
currentVersion: "54959_2020-01-29_4.4-925859585436",
|
||||
minDate: "2020-01-29",
|
||||
constraint: ">= 0.0",
|
||||
expected: true,
|
||||
},
|
||||
// Full 40-character hash, just for fun
|
||||
{
|
||||
name: "Forty character hash",
|
||||
currentVersion: "54959_2020-01-29_7db7d396346284fd0f8f79f130f38b16fb1d3d70",
|
||||
minDate: "2020-01-29",
|
||||
constraint: ">= 0.0",
|
||||
expected: true,
|
||||
},
|
||||
} {
|
||||
actual, err := CheckSourcegraphVersion(tc.currentVersion, tc.constraint, tc.minDate)
|
||||
if err != nil {
|
||||
t.Errorf("err: %s", err)
|
||||
}
|
||||
{
|
||||
name: "Daily release build",
|
||||
currentVersion: "5.1_231128_2023-06-27_5.0-7ac9ba347103",
|
||||
minDate: "2020-01-29",
|
||||
constraint: ">= 4.4",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid semantic version",
|
||||
currentVersion: "\n1.2",
|
||||
minDate: "2020-01-29",
|
||||
constraint: ">= 0.0",
|
||||
expected: false,
|
||||
expectedErr: errors.New("Invalid Semantic Version"),
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual, err := CheckSourcegraphVersion(test.currentVersion, test.constraint, test.minDate)
|
||||
|
||||
if actual != tc.expected {
|
||||
t.Errorf("wrong result. want=%t, got=%t (version=%q, constraint=%q)", tc.expected, actual, tc.currentVersion, tc.constraint)
|
||||
}
|
||||
if test.expectedErr != nil {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, test.expectedErr.Error(), err.Error())
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, test.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user