diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e056fbcf4..d76b2148c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ All notable changes to `src-cli` are documented in this file. ### Added +- When used with Sourcegraph 3.18 or later, campaigns can now be created on GitLab. [#231](https://github.com/sourcegraph/src-cli/pull/231) + ### Changed ### Fixed diff --git a/cmd/src/actions_exec.go b/cmd/src/actions_exec.go index bfad8e43dd..81368c29af 100644 --- a/cmd/src/actions_exec.go +++ b/cmd/src/actions_exec.go @@ -448,9 +448,15 @@ fragment repositoryFields on Repository { } // Skip repos from unsupported code hosts but don't report them explicitly. - if !includeUnsupported && strings.ToLower(repo.ExternalRepository.ServiceType) != "github" && strings.ToLower(repo.ExternalRepository.ServiceType) != "bitbucketserver" { - unsupported = append(unsupported, repo.Name) - continue + if !includeUnsupported { + ok, err := isCodeHostSupportedForCampaigns(repo.ExternalRepository.ServiceType) + if err != nil { + return nil, errors.Wrap(err, "failed code host check") + } + if !ok { + unsupported = append(unsupported, repo.Name) + continue + } } if repo.DefaultBranch == nil || repo.DefaultBranch.Name == "" { @@ -517,3 +523,44 @@ func askForConfirmation(s string) (bool, error) { return false, nil } + +type minimumVersionDate struct { + version string + date string +} + +// codeHostCampaignVersions contains the minimum Sourcegraph version and build +// date required for the given code host kind. If a code host is present with a +// value of nil, this means that any Sourcegraph version will pass the check. +var codeHostCampaignVersions = map[string]*minimumVersionDate{ + "github": nil, + "bitbucketserver": nil, + "gitlab": { + version: "3.18.0", + date: "2020-07-14", + }, +} + +func isCodeHostSupportedForCampaigns(kind string) (bool, error) { + // TODO(LawnGnome): this is a temporary hack; I intend to improve our + // testing story including mocking requests to Sourcegraph as part of + // https://github.com/sourcegraph/sourcegraph/issues/12333 + return isCodeHostSupportedForCampaignsImpl(kind, getSourcegraphVersion) +} + +func isCodeHostSupportedForCampaignsImpl(kind string, getVersion func() (string, error)) (bool, error) { + mvd, ok := codeHostCampaignVersions[strings.ToLower(kind)] + if !ok { + return false, nil + } + if mvd == nil { + return true, nil + } + + ver, err := getVersion() + if err != nil { + return false, errors.Wrap(err, "getting Sourcegraph version") + } + + return sourcegraphVersionCheck(ver, fmt.Sprintf(">= %s", mvd.version), mvd.date) +} diff --git a/cmd/src/actions_exec_test.go b/cmd/src/actions_exec_test.go new file mode 100644 index 0000000000..ff68a31b12 --- /dev/null +++ b/cmd/src/actions_exec_test.go @@ -0,0 +1,83 @@ +package main + +import ( + "testing" + + "github.com/pkg/errors" +) + +func TestCodeHostSupported(t *testing.T) { + t.Run("error from getSourcegraphVersion", func(t *testing.T) { + want := errors.New("foo") + if _, have := isCodeHostSupportedForCampaignsImpl("GITLAB", func() (string, error) { + return "", want + }); !errors.Is(have, want) { + t.Errorf("unexpected error: have %+v; want %+v", have, want) + } + }) + + t.Run("error from sourcegraphVersionCheck", func(t *testing.T) { + if _, err := isCodeHostSupportedForCampaignsImpl("GITLAB", func() (string, error) { + return "x.y.z", nil + }); err == nil { + t.Error("unexpected nil error") + } + }) + + t.Run("no errors", func(t *testing.T) { + for name, tc := range map[string]struct { + want bool + kind string + version string + }{ + "GitHub": { + want: true, + kind: "GITHUB", + version: "1.2.3", + }, + "BitBucket": { + want: true, + kind: "BITBUCKETSERVER", + version: "1.2.3", + }, + "GitLab with old semver version": { + want: false, + kind: "GITLAB", + version: "1.2.3", + }, + "GitLab with old dev version": { + want: false, + kind: "GITLAB", + version: "68956_2019-07-21_c3a5992", + }, + "GitLab with new semver version": { + want: true, + kind: "GITLAB", + version: "3.18.0", + }, + "GitLab with new dev version": { + want: true, + kind: "GITLAB", + version: "68956_2020-07-21_c3a5992", + }, + "unknown kind": { + want: false, + kind: "CODE HOSTS R US", + version: "3.18.0", + }, + } { + t.Run(name, func(t *testing.T) { + have, err := isCodeHostSupportedForCampaignsImpl(tc.kind, func() (string, error) { + return tc.version, nil + }) + if err != nil { + t.Errorf("unexpected non-nil error: %+v", err) + } + + if have != tc.want { + t.Errorf("unexpected support status: have %v; want %v", have, tc.want) + } + }) + } + }) +}