1// Copyright 2014 The go-github AUTHORS. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package github
7
8import (
9	"context"
10	"encoding/json"
11	"fmt"
12)
13
14// Deployment represents a deployment in a repo
15type Deployment struct {
16	URL           *string         `json:"url,omitempty"`
17	ID            *int64          `json:"id,omitempty"`
18	SHA           *string         `json:"sha,omitempty"`
19	Ref           *string         `json:"ref,omitempty"`
20	Task          *string         `json:"task,omitempty"`
21	Payload       json.RawMessage `json:"payload,omitempty"`
22	Environment   *string         `json:"environment,omitempty"`
23	Description   *string         `json:"description,omitempty"`
24	Creator       *User           `json:"creator,omitempty"`
25	CreatedAt     *Timestamp      `json:"created_at,omitempty"`
26	UpdatedAt     *Timestamp      `json:"updated_at,omitempty"`
27	StatusesURL   *string         `json:"statuses_url,omitempty"`
28	RepositoryURL *string         `json:"repository_url,omitempty"`
29	NodeID        *string         `json:"node_id,omitempty"`
30}
31
32// DeploymentRequest represents a deployment request
33type DeploymentRequest struct {
34	Ref                   *string   `json:"ref,omitempty"`
35	Task                  *string   `json:"task,omitempty"`
36	AutoMerge             *bool     `json:"auto_merge,omitempty"`
37	RequiredContexts      *[]string `json:"required_contexts,omitempty"`
38	Payload               *string   `json:"payload,omitempty"`
39	Environment           *string   `json:"environment,omitempty"`
40	Description           *string   `json:"description,omitempty"`
41	TransientEnvironment  *bool     `json:"transient_environment,omitempty"`
42	ProductionEnvironment *bool     `json:"production_environment,omitempty"`
43}
44
45// DeploymentsListOptions specifies the optional parameters to the
46// RepositoriesService.ListDeployments method.
47type DeploymentsListOptions struct {
48	// SHA of the Deployment.
49	SHA string `url:"sha,omitempty"`
50
51	// List deployments for a given ref.
52	Ref string `url:"ref,omitempty"`
53
54	// List deployments for a given task.
55	Task string `url:"task,omitempty"`
56
57	// List deployments for a given environment.
58	Environment string `url:"environment,omitempty"`
59
60	ListOptions
61}
62
63// ListDeployments lists the deployments of a repository.
64//
65// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments
66func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opt *DeploymentsListOptions) ([]*Deployment, *Response, error) {
67	u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
68	u, err := addOptions(u, opt)
69	if err != nil {
70		return nil, nil, err
71	}
72
73	req, err := s.client.NewRequest("GET", u, nil)
74	if err != nil {
75		return nil, nil, err
76	}
77
78	var deployments []*Deployment
79	resp, err := s.client.Do(ctx, req, &deployments)
80	if err != nil {
81		return nil, resp, err
82	}
83
84	return deployments, resp, nil
85}
86
87// GetDeployment returns a single deployment of a repository.
88//
89// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment
90func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) {
91	u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID)
92
93	req, err := s.client.NewRequest("GET", u, nil)
94	if err != nil {
95		return nil, nil, err
96	}
97
98	deployment := new(Deployment)
99	resp, err := s.client.Do(ctx, req, deployment)
100	if err != nil {
101		return nil, resp, err
102	}
103
104	return deployment, resp, nil
105}
106
107// CreateDeployment creates a new deployment for a repository.
108//
109// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment
110func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) {
111	u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
112
113	req, err := s.client.NewRequest("POST", u, request)
114	if err != nil {
115		return nil, nil, err
116	}
117
118	// TODO: remove custom Accept headers when APIs fully launch.
119	req.Header.Set("Accept", mediaTypeDeploymentStatusPreview)
120
121	d := new(Deployment)
122	resp, err := s.client.Do(ctx, req, d)
123	if err != nil {
124		return nil, resp, err
125	}
126
127	return d, resp, nil
128}
129
130// DeploymentStatus represents the status of a
131// particular deployment.
132type DeploymentStatus struct {
133	ID *int64 `json:"id,omitempty"`
134	// State is the deployment state.
135	// Possible values are: "pending", "success", "failure", "error", "inactive".
136	State         *string    `json:"state,omitempty"`
137	Creator       *User      `json:"creator,omitempty"`
138	Description   *string    `json:"description,omitempty"`
139	TargetURL     *string    `json:"target_url,omitempty"`
140	CreatedAt     *Timestamp `json:"created_at,omitempty"`
141	UpdatedAt     *Timestamp `json:"updated_at,omitempty"`
142	DeploymentURL *string    `json:"deployment_url,omitempty"`
143	RepositoryURL *string    `json:"repository_url,omitempty"`
144	NodeID        *string    `json:"node_id,omitempty"`
145}
146
147// DeploymentStatusRequest represents a deployment request
148type DeploymentStatusRequest struct {
149	State          *string `json:"state,omitempty"`
150	LogURL         *string `json:"log_url,omitempty"`
151	Description    *string `json:"description,omitempty"`
152	EnvironmentURL *string `json:"environment_url,omitempty"`
153	AutoInactive   *bool   `json:"auto_inactive,omitempty"`
154}
155
156// ListDeploymentStatuses lists the statuses of a given deployment of a repository.
157//
158// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses
159func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opt *ListOptions) ([]*DeploymentStatus, *Response, error) {
160	u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
161	u, err := addOptions(u, opt)
162	if err != nil {
163		return nil, nil, err
164	}
165
166	req, err := s.client.NewRequest("GET", u, nil)
167	if err != nil {
168		return nil, nil, err
169	}
170
171	var statuses []*DeploymentStatus
172	resp, err := s.client.Do(ctx, req, &statuses)
173	if err != nil {
174		return nil, resp, err
175	}
176
177	return statuses, resp, nil
178}
179
180// GetDeploymentStatus returns a single deployment status of a repository.
181//
182// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status
183func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) {
184	u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID)
185
186	req, err := s.client.NewRequest("GET", u, nil)
187	if err != nil {
188		return nil, nil, err
189	}
190
191	// TODO: remove custom Accept headers when APIs fully launch.
192	req.Header.Set("Accept", mediaTypeDeploymentStatusPreview)
193
194	d := new(DeploymentStatus)
195	resp, err := s.client.Do(ctx, req, d)
196	if err != nil {
197		return nil, resp, err
198	}
199
200	return d, resp, nil
201}
202
203// CreateDeploymentStatus creates a new status for a deployment.
204//
205// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment-status
206func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) {
207	u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
208
209	req, err := s.client.NewRequest("POST", u, request)
210	if err != nil {
211		return nil, nil, err
212	}
213
214	// TODO: remove custom Accept headers when APIs fully launch.
215	req.Header.Set("Accept", mediaTypeDeploymentStatusPreview)
216
217	d := new(DeploymentStatus)
218	resp, err := s.client.Do(ctx, req, d)
219	if err != nil {
220		return nil, resp, err
221	}
222
223	return d, resp, nil
224}
225