Skip to content

Commit 3710411

Browse files
authored
Feature: Organization repository code mapping (#64)
* Implement OrganizationIntegrationsService with List method * Implement OrganizationRepositoriesService with List method * Add Create and Delete to OrganizationRepositoriesService * Implement OrganizationCodeMappingsService with List method * Add Create, Update and Delete to OrganizationCodeMappingsService
1 parent ddbf69c commit 3710411

7 files changed

+777
-12
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package sentry
2+
3+
import (
4+
"context"
5+
"fmt"
6+
)
7+
8+
// OrganizationCodeMapping represents a code mapping added for the organization.
9+
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/serializers/models/repository_project_path_config.py
10+
type OrganizationCodeMapping struct {
11+
ID string `json:"id"`
12+
ProjectId string `json:"projectId"`
13+
ProjectSlug string `json:"projectSlug"`
14+
RepoId string `json:"repoId"`
15+
RepoName string `json:"repoName"`
16+
IntegrationId string `json:"integrationId"`
17+
Provider *OrganizationIntegrationProvider `json:"provider"`
18+
StackRoot string `json:"stackRoot"`
19+
SourceRoot string `json:"sourceRoot"`
20+
DefaultBranch string `json:"defaultBranch"`
21+
}
22+
23+
// OrganizationCodeMappingsService provides methods for accessing Sentry organization code mappings API endpoints.
24+
// Paths: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/urls.py#L929-L938
25+
// Endpoints: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/organization_code_mappings.py
26+
// Endpoints: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/organization_code_mapping_details.py
27+
type OrganizationCodeMappingsService service
28+
29+
type ListOrganizationCodeMappingsParams struct {
30+
ListCursorParams
31+
IntegrationId string `url:"integrationId,omitempty"`
32+
}
33+
34+
// List organization integrations.
35+
func (s *OrganizationCodeMappingsService) List(ctx context.Context, organizationSlug string, params *ListOrganizationCodeMappingsParams) ([]*OrganizationCodeMapping, *Response, error) {
36+
u := fmt.Sprintf("0/organizations/%v/code-mappings/", organizationSlug)
37+
u, err := addQuery(u, params)
38+
if err != nil {
39+
return nil, nil, err
40+
}
41+
42+
req, err := s.client.NewRequest("GET", u, nil)
43+
if err != nil {
44+
return nil, nil, err
45+
}
46+
47+
integrations := []*OrganizationCodeMapping{}
48+
resp, err := s.client.Do(ctx, req, &integrations)
49+
if err != nil {
50+
return nil, resp, err
51+
}
52+
return integrations, resp, nil
53+
}
54+
55+
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/organization_code_mappings.py#L26-L35
56+
type CreateOrganizationCodeMappingParams struct {
57+
DefaultBranch string `json:"defaultBranch"`
58+
StackRoot string `json:"stackRoot"`
59+
SourceRoot string `json:"sourceRoot"`
60+
RepositoryId string `json:"repositoryId"`
61+
IntegrationId string `json:"integrationId"`
62+
ProjectId string `json:"projectId"`
63+
}
64+
65+
func (s *OrganizationCodeMappingsService) Create(ctx context.Context, organizationSlug string, params CreateOrganizationCodeMappingParams) (*OrganizationCodeMapping, *Response, error) {
66+
u := fmt.Sprintf("0/organizations/%v/code-mappings/", organizationSlug)
67+
req, err := s.client.NewRequest("POST", u, params)
68+
if err != nil {
69+
return nil, nil, err
70+
}
71+
72+
repo := new(OrganizationCodeMapping)
73+
resp, err := s.client.Do(ctx, req, repo)
74+
if err != nil {
75+
return nil, resp, err
76+
}
77+
return repo, resp, nil
78+
}
79+
80+
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/organization_code_mappings.py#L26-L35
81+
type UpdateOrganizationCodeMappingParams CreateOrganizationCodeMappingParams
82+
83+
func (s *OrganizationCodeMappingsService) Update(ctx context.Context, organizationSlug string, codeMappingId string, params UpdateOrganizationCodeMappingParams) (*OrganizationCodeMapping, *Response, error) {
84+
u := fmt.Sprintf("0/organizations/%v/code-mappings/%v/", organizationSlug, codeMappingId)
85+
req, err := s.client.NewRequest("PUT", u, params)
86+
if err != nil {
87+
return nil, nil, err
88+
}
89+
90+
repo := new(OrganizationCodeMapping)
91+
resp, err := s.client.Do(ctx, req, repo)
92+
if err != nil {
93+
return nil, resp, err
94+
}
95+
return repo, resp, nil
96+
}
97+
98+
func (s *OrganizationCodeMappingsService) Delete(ctx context.Context, organizationSlug string, codeMappingId string) (*Response, error) {
99+
u := fmt.Sprintf("0/organizations/%v/code-mappings/%v/", organizationSlug, codeMappingId)
100+
req, err := s.client.NewRequest("DELETE", u, nil)
101+
if err != nil {
102+
return nil, err
103+
}
104+
105+
return s.client.Do(ctx, req, nil)
106+
}
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
package sentry
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestOrganizationCodeMappingsService_List(t *testing.T) {
13+
client, mux, _, teardown := setup()
14+
defer teardown()
15+
16+
mux.HandleFunc("/api/0/organizations/the-interstellar-jurisdiction/code-mappings/", func(w http.ResponseWriter, r *http.Request) {
17+
assertMethod(t, "GET", r)
18+
assertQuery(t, map[string]string{"cursor": "100:-1:1", "integrationId": "123456"}, r)
19+
w.Header().Set("Content-Type", "application/json")
20+
fmt.Fprint(w, `[
21+
{
22+
"id": "54321",
23+
"projectId": "7654321",
24+
"projectSlug": "spoon-knife",
25+
"repoId": "456123",
26+
"repoName": "octocat/Spoon-Knife",
27+
"integrationId": "123456",
28+
"provider": {
29+
"key": "github",
30+
"slug": "github",
31+
"name": "GitHub",
32+
"canAdd": true,
33+
"canDisable": false,
34+
"features": [
35+
"codeowners",
36+
"commits",
37+
"issue-basic",
38+
"stacktrace-link"
39+
],
40+
"aspects": {}
41+
},
42+
"stackRoot": "/",
43+
"sourceRoot": "src/",
44+
"defaultBranch": "main"
45+
}
46+
]`)
47+
})
48+
49+
ctx := context.Background()
50+
integrations, _, err := client.OrganizationCodeMappings.List(ctx, "the-interstellar-jurisdiction", &ListOrganizationCodeMappingsParams{
51+
ListCursorParams: ListCursorParams{
52+
Cursor: "100:-1:1",
53+
},
54+
IntegrationId: "123456",
55+
})
56+
assert.NoError(t, err)
57+
expected := []*OrganizationCodeMapping{
58+
{
59+
ID: "54321",
60+
ProjectId: "7654321",
61+
ProjectSlug: "spoon-knife",
62+
RepoId: "456123",
63+
RepoName: "octocat/Spoon-Knife",
64+
IntegrationId: "123456",
65+
Provider: &OrganizationIntegrationProvider{
66+
Key: "github",
67+
Slug: "github",
68+
Name: "GitHub",
69+
CanAdd: true,
70+
CanDisable: false,
71+
Features: []string{
72+
"codeowners",
73+
"commits",
74+
"issue-basic",
75+
"stacktrace-link",
76+
},
77+
},
78+
StackRoot: "/",
79+
SourceRoot: "src/",
80+
DefaultBranch: "main",
81+
},
82+
}
83+
assert.Equal(t, expected, integrations)
84+
}
85+
86+
func TestOrganizationCodeMappingsService_Create(t *testing.T) {
87+
client, mux, _, teardown := setup()
88+
defer teardown()
89+
90+
mux.HandleFunc("/api/0/organizations/the-interstellar-jurisdiction/code-mappings/", func(w http.ResponseWriter, r *http.Request) {
91+
assertMethod(t, "POST", r)
92+
w.WriteHeader(http.StatusCreated)
93+
w.Header().Set("Content-Type", "application/json")
94+
fmt.Fprint(w, `{
95+
"id": "54321",
96+
"projectId": "7654321",
97+
"projectSlug": "spoon-knife",
98+
"repoId": "456123",
99+
"repoName": "octocat/Spoon-Knife",
100+
"integrationId": "123456",
101+
"provider": {
102+
"key": "github",
103+
"slug": "github",
104+
"name": "GitHub",
105+
"canAdd": true,
106+
"canDisable": false,
107+
"features": [
108+
"codeowners",
109+
"commits",
110+
"issue-basic",
111+
"stacktrace-link"
112+
],
113+
"aspects": {}
114+
},
115+
"stackRoot": "/",
116+
"sourceRoot": "src/",
117+
"defaultBranch": "main"
118+
}`)
119+
})
120+
121+
ctx := context.Background()
122+
createOrganizationCodeMappingParams := CreateOrganizationCodeMappingParams{
123+
DefaultBranch: "main",
124+
StackRoot: "/",
125+
SourceRoot: "src/",
126+
RepositoryId: "456123",
127+
IntegrationId: "123456",
128+
ProjectId: "7654321",
129+
}
130+
codeMapping, _, err := client.OrganizationCodeMappings.Create(ctx, "the-interstellar-jurisdiction", createOrganizationCodeMappingParams)
131+
assert.NoError(t, err)
132+
expected := &OrganizationCodeMapping{
133+
ID: "54321",
134+
ProjectId: "7654321",
135+
ProjectSlug: "spoon-knife",
136+
RepoId: "456123",
137+
RepoName: "octocat/Spoon-Knife",
138+
IntegrationId: "123456",
139+
Provider: &OrganizationIntegrationProvider{
140+
Key: "github",
141+
Slug: "github",
142+
Name: "GitHub",
143+
CanAdd: true,
144+
CanDisable: false,
145+
Features: []string{
146+
"codeowners",
147+
"commits",
148+
"issue-basic",
149+
"stacktrace-link",
150+
},
151+
},
152+
StackRoot: "/",
153+
SourceRoot: "src/",
154+
DefaultBranch: "main",
155+
}
156+
assert.Equal(t, expected, codeMapping)
157+
}
158+
159+
func TestOrganizationCodeMappingsService_Update(t *testing.T) {
160+
client, mux, _, teardown := setup()
161+
defer teardown()
162+
163+
codeMappingId := "54321"
164+
165+
mux.HandleFunc(fmt.Sprintf("/api/0/organizations/the-interstellar-jurisdiction/code-mappings/%s/", codeMappingId), func(w http.ResponseWriter, r *http.Request) {
166+
assertMethod(t, "PUT", r)
167+
w.WriteHeader(http.StatusOK)
168+
w.Header().Set("Content-Type", "application/json")
169+
fmt.Fprintf(w, `{
170+
"id": "%s",
171+
"projectId": "7654321",
172+
"projectSlug": "spoon-knife",
173+
"repoId": "456123",
174+
"repoName": "octocat/Spoon-Knife",
175+
"integrationId": "123456",
176+
"provider": {
177+
"key": "github",
178+
"slug": "github",
179+
"name": "GitHub",
180+
"canAdd": true,
181+
"canDisable": false,
182+
"features": [
183+
"codeowners",
184+
"commits",
185+
"issue-basic",
186+
"stacktrace-link"
187+
],
188+
"aspects": {}
189+
},
190+
"stackRoot": "/",
191+
"sourceRoot": "src/",
192+
"defaultBranch": "main"
193+
}`, codeMappingId)
194+
})
195+
196+
ctx := context.Background()
197+
updateOrganizationCodeMappingParams := UpdateOrganizationCodeMappingParams{
198+
DefaultBranch: "main",
199+
StackRoot: "/",
200+
SourceRoot: "src/",
201+
RepositoryId: "456123",
202+
IntegrationId: "123456",
203+
ProjectId: "7654321",
204+
}
205+
codeMapping, _, err := client.OrganizationCodeMappings.Update(ctx, "the-interstellar-jurisdiction", codeMappingId, updateOrganizationCodeMappingParams)
206+
assert.NoError(t, err)
207+
expected := &OrganizationCodeMapping{
208+
ID: codeMappingId,
209+
ProjectId: "7654321",
210+
ProjectSlug: "spoon-knife",
211+
RepoId: "456123",
212+
RepoName: "octocat/Spoon-Knife",
213+
IntegrationId: "123456",
214+
Provider: &OrganizationIntegrationProvider{
215+
Key: "github",
216+
Slug: "github",
217+
Name: "GitHub",
218+
CanAdd: true,
219+
CanDisable: false,
220+
Features: []string{
221+
"codeowners",
222+
"commits",
223+
"issue-basic",
224+
"stacktrace-link",
225+
},
226+
},
227+
StackRoot: "/",
228+
SourceRoot: "src/",
229+
DefaultBranch: "main",
230+
}
231+
assert.Equal(t, expected, codeMapping)
232+
}
233+
234+
func TestOrganizationCodeMappingsService_Delete(t *testing.T) {
235+
client, mux, _, teardown := setup()
236+
defer teardown()
237+
238+
codeMappingId := "54321"
239+
240+
mux.HandleFunc(fmt.Sprintf("/api/0/organizations/the-interstellar-jurisdiction/code-mappings/%s/", codeMappingId), func(w http.ResponseWriter, r *http.Request) {
241+
assertMethod(t, "DELETE", r)
242+
w.WriteHeader(http.StatusNoContent)
243+
w.Header().Set("Content-Type", "application/json")
244+
})
245+
246+
ctx := context.Background()
247+
_, err := client.OrganizationCodeMappings.Delete(ctx, "the-interstellar-jurisdiction", codeMappingId)
248+
assert.NoError(t, err)
249+
}

0 commit comments

Comments
 (0)