Skip to content

Commit d944d81

Browse files
committed
support for github deployment API
1 parent 16026ee commit d944d81

File tree

6 files changed

+140
-11
lines changed

6 files changed

+140
-11
lines changed

scm/driver/github/github.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func New(uri string) (*scm.Client, error) {
3434
client.Issues = &issueService{client}
3535
client.Organizations = &organizationService{client}
3636
client.PullRequests = &pullService{&issueService{client}}
37-
client.Repositories = &repositoryService{client}
37+
client.Repositories = &RepositoryService{client}
3838
client.Reviews = &reviewService{client}
3939
client.Users = &userService{client}
4040
client.Webhooks = &webhookService{client}

scm/driver/github/repo.go

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,60 +49,62 @@ type hook struct {
4949
} `json:"config"`
5050
}
5151

52-
type repositoryService struct {
52+
// RepositoryService implements the repository service for
53+
// the GitHub driver.
54+
type RepositoryService struct {
5355
client *wrapper
5456
}
5557

5658
// Find returns the repository by name.
57-
func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) {
59+
func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) {
5860
path := fmt.Sprintf("repos/%s", repo)
5961
out := new(repository)
6062
res, err := s.client.do(ctx, "GET", path, nil, out)
6163
return convertRepository(out), res, err
6264
}
6365

6466
// FindHook returns a repository hook.
65-
func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) {
67+
func (s *RepositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) {
6668
path := fmt.Sprintf("repos/%s/hooks/%s", repo, id)
6769
out := new(hook)
6870
res, err := s.client.do(ctx, "GET", path, nil, out)
6971
return convertHook(out), res, err
7072
}
7173

7274
// FindPerms returns the repository permissions.
73-
func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) {
75+
func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) {
7476
path := fmt.Sprintf("repos/%s", repo)
7577
out := new(repository)
7678
res, err := s.client.do(ctx, "GET", path, nil, out)
7779
return convertRepository(out).Perm, res, err
7880
}
7981

8082
// List returns the user repository list.
81-
func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
83+
func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
8284
path := fmt.Sprintf("user/repos?%s", encodeListOptions(opts))
8385
out := []*repository{}
8486
res, err := s.client.do(ctx, "GET", path, nil, &out)
8587
return convertRepositoryList(out), res, err
8688
}
8789

8890
// ListHooks returns a list or repository hooks.
89-
func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) {
91+
func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) {
9092
path := fmt.Sprintf("repos/%s/hooks?%s", repo, encodeListOptions(opts))
9193
out := []*hook{}
9294
res, err := s.client.do(ctx, "GET", path, nil, &out)
9395
return convertHookList(out), res, err
9496
}
9597

9698
// ListStatus returns a list of commit statuses.
97-
func (s *repositoryService) ListStatus(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) {
99+
func (s *RepositoryService) ListStatus(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) {
98100
path := fmt.Sprintf("repos/%s/statuses/%s?%s", repo, ref, encodeListOptions(opts))
99101
out := []*status{}
100102
res, err := s.client.do(ctx, "GET", path, nil, &out)
101103
return convertStatusList(out), res, err
102104
}
103105

104106
// CreateHook creates a new repository webhook.
105-
func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
107+
func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
106108
path := fmt.Sprintf("repos/%s/hooks", repo)
107109
in := new(hook)
108110
in.Active = true
@@ -120,7 +122,7 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *
120122
}
121123

122124
// CreateStatus creates a new commit status.
123-
func (s *repositoryService) CreateStatus(ctx context.Context, repo, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) {
125+
func (s *RepositoryService) CreateStatus(ctx context.Context, repo, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) {
124126
path := fmt.Sprintf("repos/%s/statuses/%s", repo, ref)
125127
in := &status{
126128
State: convertFromState(input.State),
@@ -133,8 +135,23 @@ func (s *repositoryService) CreateStatus(ctx context.Context, repo, ref string,
133135
return convertStatus(out), res, err
134136
}
135137

138+
// CreateDeployStatus creates a new deployment status.
139+
func (s *RepositoryService) CreateDeployStatus(ctx context.Context, repo string, input *scm.DeployStatus) (*scm.DeployStatus, *scm.Response, error) {
140+
path := fmt.Sprintf("repos/%s/deployments/%d/statuses", repo, input.Number)
141+
in := &deployStatus{
142+
State: convertFromState(input.State),
143+
Environment: input.Environment,
144+
EnvironmentURL: input.EnvironmentURL,
145+
Description: input.Desc,
146+
TargetURL: input.Target,
147+
}
148+
out := new(deployStatus)
149+
res, err := s.client.do(ctx, "POST", path, in, out)
150+
return convertDeployStatus(out), res, err
151+
}
152+
136153
// DeleteHook deletes a repository webhook.
137-
func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) {
154+
func (s *RepositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) {
138155
path := fmt.Sprintf("repos/%s/hooks/%s", repo, id)
139156
return s.client.do(ctx, "DELETE", path, nil, nil)
140157
}
@@ -224,6 +241,15 @@ type status struct {
224241
Context string `json:"context"`
225242
}
226243

244+
type deployStatus struct {
245+
ID int `json:"id"`
246+
Environment string `json:"environment"`
247+
EnvironmentURL string `json:"environment_url"`
248+
State string `json:"state"`
249+
TargetURL string `json:"log_url"`
250+
Description string `json:"description"`
251+
}
252+
227253
func convertStatusList(from []*status) []*scm.Status {
228254
to := []*scm.Status{}
229255
for _, v := range from {
@@ -241,6 +267,17 @@ func convertStatus(from *status) *scm.Status {
241267
}
242268
}
243269

270+
func convertDeployStatus(from *deployStatus) *scm.DeployStatus {
271+
return &scm.DeployStatus{
272+
Number: from.ID,
273+
State: convertState(from.State),
274+
Desc: from.Description,
275+
Target: from.TargetURL,
276+
Environment: from.Environment,
277+
EnvironmentURL: from.EnvironmentURL,
278+
}
279+
}
280+
244281
func convertState(from string) scm.State {
245282
switch from {
246283
case "error":

scm/driver/github/repo_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,45 @@ func TestStatusCreate(t *testing.T) {
201201
t.Run("Rate", testRate(res))
202202
}
203203

204+
func TestDeployStatusCreate(t *testing.T) {
205+
defer gock.Off()
206+
207+
gock.New("https://api.github.com").
208+
Post("/repos/octocat/hello-world/deployments/1/status").
209+
Reply(201).
210+
Type("application/json").
211+
SetHeaders(mockHeaders).
212+
File("testdata/deployment.json")
213+
214+
in := &scm.DeployStatus{
215+
Number: 1,
216+
Desc: "Build has completed successfully",
217+
State: scm.StateSuccess,
218+
Target: "https://ci.example.com/1000/output",
219+
Environment: "production",
220+
EnvironmentURL: "https://example.netlify.com",
221+
}
222+
223+
client := NewDefault()
224+
got, res, err := client.Repositories.(*RepositoryService).CreateDeployStatus(context.Background(), "octocat/hello-world", in)
225+
if err != nil {
226+
t.Error(err)
227+
return
228+
}
229+
230+
want := new(scm.DeployStatus)
231+
raw, _ := ioutil.ReadFile("testdata/deployment.json.golden")
232+
json.Unmarshal(raw, want)
233+
234+
if diff := cmp.Diff(got, want); diff != "" {
235+
t.Errorf("Unexpected Results")
236+
t.Log(diff)
237+
}
238+
239+
t.Run("Request", testRequest(res))
240+
t.Run("Rate", testRate(res))
241+
}
242+
204243
func TestRepositoryHookFind(t *testing.T) {
205244
defer gock.Off()
206245

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"url": "https://api.github.com/repos/octocat/example/deployments/42/statuses/1",
3+
"id": 1,
4+
"node_id": "MDE2OkRlcGxveW1lbnRTdGF0dXMx",
5+
"state": "success",
6+
"creator": {
7+
"login": "octocat",
8+
"id": 1,
9+
"node_id": "MDQ6VXNlcjE=",
10+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
11+
"gravatar_id": "",
12+
"url": "https://api.github.com/users/octocat",
13+
"html_url": "https://github.com/octocat",
14+
"followers_url": "https://api.github.com/users/octocat/followers",
15+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
16+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
17+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
18+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
19+
"organizations_url": "https://api.github.com/users/octocat/orgs",
20+
"repos_url": "https://api.github.com/users/octocat/repos",
21+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
22+
"received_events_url": "https://api.github.com/users/octocat/received_events",
23+
"type": "User",
24+
"site_admin": false
25+
},
26+
"description": "Deployment finished successfully.",
27+
"environment": "production",
28+
"target_url": "https://example.com/deployment/42/output",
29+
"created_at": "2012-07-20T01:19:13Z",
30+
"updated_at": "2012-07-20T01:19:13Z",
31+
"deployment_url": "https://api.github.com/repos/octocat/example/deployments/42",
32+
"repository_url": "https://api.github.com/repos/octocat/example",
33+
"environment_url": "",
34+
"log_url": "https://example.com/deployment/42/output"
35+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Number": 1,
3+
"State": 3,
4+
"Environment": "production",
5+
"EnvironmentURL": "",
6+
"Desc": "Deployment finished successfully.",
7+
"Target": "https://example.com/deployment/42/output"
8+
}

scm/repo.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ type (
8787
Target string
8888
}
8989

90+
// DeployStatus represents a deployment status.
91+
DeployStatus struct {
92+
Number int
93+
State State
94+
Desc string
95+
Target string
96+
Environment string
97+
EnvironmentURL string
98+
}
99+
90100
// RepositoryService provides access to repository resources.
91101
RepositoryService interface {
92102
// Find returns a repository by name.

0 commit comments

Comments
 (0)