diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index af6656c13..dae86f58b 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -94,7 +94,18 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?", s.client.owner, s.client.project, repo) + // add tags + endpoint += fmt.Sprintf("filter=tags/") + // add target + endpoint += fmt.Sprintf("&api-version=7.1-preview.1") + out := new(tags) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + + return convertTags(out.Value), res, err } func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { @@ -202,6 +213,29 @@ type compare struct { TargetCommit string `json:"targetCommit"` } +type tags struct { + Value []*tag `json:"value"` + Count int `json:"count"` +} +type tag struct { + Name string `json:"name"` + ObjectID string `json:"objectId"` + Creator struct { + DisplayName string `json:"displayName"` + URL string `json:"url"` + Links struct { + Avatar struct { + Href string `json:"href"` + } `json:"avatar"` + } `json:"_links"` + ID string `json:"id"` + UniqueName string `json:"uniqueName"` + ImageURL string `json:"imageUrl"` + Descriptor string `json:"descriptor"` + } `json:"creator"` + URL string `json:"url"` +} + func convertBranchList(from []*branch) []*scm.Reference { to := []*scm.Reference{} for _, v := range from { @@ -269,3 +303,15 @@ func convertChange(from *file) *scm.Change { return returnVal } + +func convertTags(from []*tag) []*scm.Reference { + var to []*scm.Reference + for _, v := range from { + to = append(to, &scm.Reference{ + Name: scm.TrimRef(v.Name), + Path: scm.ExpandRef(v.Name, "refs/tags/"), + Sha: v.ObjectID, + }) + } + return to +} diff --git a/scm/driver/azure/git_test.go b/scm/driver/azure/git_test.go index f150dc38e..4f79b78eb 100644 --- a/scm/driver/azure/git_test.go +++ b/scm/driver/azure/git_test.go @@ -175,3 +175,62 @@ func TestGitCompareChanges(t *testing.T) { } } + +func TestGitListTags(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/tags.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Git.ListTags(context.Background(), "REPOID", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/tags.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestConvertTags(t *testing.T) { + from := []*tag{ + { + Name: "refs/tags/v1.0.0", + ObjectID: "23d9c1d0d6c41f1c8e08ab98a6a79c2d5ada649d", + }, + { + Name: "refs/tags/v1.1.0", + ObjectID: "8a9db19b5e19613c18e9059d7b9fa5d6d6a3785f", + }, + } + + got := convertTags(from) + + want := []*scm.Reference{ + { + Name: "v1.0.0", + Path: "refs/tags/v1.0.0", + Sha: "23d9c1d0d6c41f1c8e08ab98a6a79c2d5ada649d", + }, + { + Name: "v1.1.0", + Path: "refs/tags/v1.1.0", + Sha: "8a9db19b5e19613c18e9059d7b9fa5d6d6a3785f", + }, + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/azure/testdata/tags.json b/scm/driver/azure/testdata/tags.json new file mode 100644 index 000000000..090690921 --- /dev/null +++ b/scm/driver/azure/testdata/tags.json @@ -0,0 +1,41 @@ +{ + "value": [ + { + "name": "refs/tags/v1.0.0", + "objectId": "23d9c1d0d6c41f1c8e08ab98a6a79c2d5ada649d", + "creator": { + "displayName": "Test User", + "url": "https://dev.azure.com/fabrikam/_apis/Identities/d6245f20-2af8-44f4-9451-8107cb2767db", + "_links": { + "avatar": { + "href": "https://dev.azure.com/fabrikam/_apis/GraphProfile/MemberAvatars/aad.YTYyNDVmMjAtMmFmOC00NGY0LTk0NTEtODEwN2NiMjc2N2Ri" + } + }, + "id": "d6245f20-2af8-44f4-9451-8107cb2767db", + "uniqueName": "test@example.com", + "imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=d6245f20-2af8-44f4-9451-8107cb2767db", + "descriptor": "aad.YTYyNDVmMjAtMmFmOC00NGY0LTk0NTEtODEwN2NiMjc2N2Ri" + }, + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/refs/tags/v1.0.0" + }, + { + "name": "refs/tags/v1.1.0", + "objectId": "8a9db19b5e19613c18e9059d7b9fa5d6d6a3785f", + "creator": { + "displayName": "Test User", + "url": "https://dev.azure.com/fabrikam/_apis/Identities/d6245f20-2af8-44f4-9451-8107cb2767db", + "_links": { + "avatar": { + "href": "https://dev.azure.com/fabrikam/_apis/GraphProfile/MemberAvatars/aad.YTYyNDVmMjAtMmFmOC00NGY0LTk0NTEtODEwN2NiMjc2N2Ri" + } + }, + "id": "d6245f20-2af8-44f4-9451-8107cb2767db", + "uniqueName": "test@example.com", + "imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=d6245f20-2af8-44f4-9451-8107cb2767db", + "descriptor": "aad.YTYyNDVmMjAtMmFmOC00NGY0LTk0NTEtODEwN2NiMjc2N2Ri" + }, + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/refs/tags/v1.1.0" + } + ], + "count": 2 +} diff --git a/scm/driver/azure/testdata/tags.json.golden b/scm/driver/azure/testdata/tags.json.golden new file mode 100644 index 000000000..28ef8bbf3 --- /dev/null +++ b/scm/driver/azure/testdata/tags.json.golden @@ -0,0 +1,12 @@ +[ + { + "Name": "v1.0.0", + "Path": "refs/tags/v1.0.0", + "Sha": "23d9c1d0d6c41f1c8e08ab98a6a79c2d5ada649d" + }, + { + "Name": "v1.1.0", + "Path": "refs/tags/v1.1.0", + "Sha": "8a9db19b5e19613c18e9059d7b9fa5d6d6a3785f" + } +]