Skip to content

Commit 7045fd3

Browse files
BirmacherAkostrapacska
authored andcommitted
Upload generated provisioning profiles to Bitrise (#70)
* codesign files upload * - cmd/common.go: Merge fix - uploaders/common.go: error handling for io.Copy() - uploaders/requestResponse: Doc fix * uploaders/common.go renamed to uploaders/uploaders.go * uploaders renamed to bitriseclient (+1 squashed commit) Squashed commits: [6a9bc13] PR fix (+3 squashed commits) Squashed commits: [a22d42c] uploaders/requestResponse.go renamed to uploaders/model.go [be88ad1] Application type fix; uploaders.go: failWithMessage removed, Instead every func return with an error if needed; [1da5d56] httpMethod removed; * cmd/common.go: getAppFromUserSelection() changed with sor.Search() * BitriseClient's functions changed to recievers. * bitriseClient: ConfirmProvProfileUpload() * Certificate upload with confirm api call - ✅; * clean (+3 squashed commits) Squashed commits: [0a7fe57] Certificate duplicate check before upload [6077d20] Rename [548f4ae] clean (+1 squashed commit) Squashed commits: [5497f05] BitriseClient: Provisioning profile duplicate check. * PR fix - clean * PR fix - clean * PR fix - clean * bitriseclient separated to certificate and to profile; * FeetchApplist - Paging * bittriseClient: Protocol removed * PR fix - clean * BitriseClient: get a http.Client{} (+1 squashed commit) Squashed commits: [e108a55] BitriseClient: RunRequest method (+2 squashed commits) Squashed commits: [53c1dba] Renames [181bf12] FetchIdentityListResponse rename * - cmd/common.go: uploadExportedFiles() splitted to uploarProvProfiles and to uploadIdentity; * - * Clean: newlines removed * clean
1 parent ce66a50 commit 7045fd3

File tree

5 files changed

+1081
-7
lines changed

5 files changed

+1081
-7
lines changed

bitriseclient/bitriseclient.go

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
package bitriseclient
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
8+
"io/ioutil"
9+
"net/http"
10+
"os"
11+
"strings"
12+
"time"
13+
14+
"github.com/bitrise-io/go-utils/log"
15+
"github.com/bitrise-io/go-utils/retry"
16+
"github.com/bitrise-io/go-utils/urlutil"
17+
)
18+
19+
const (
20+
baseURL = "https://api.bitrise.io/v0.1/"
21+
appsEndPoint = "/apps"
22+
provisioningProfilesEndPoint = "/provisioning-profiles"
23+
certificatesEndPoint = "/build-certificates"
24+
)
25+
26+
// Paging ...
27+
type Paging struct {
28+
TotalItemCount int `json:"total_item_count"`
29+
PageItemLimit int `json:"page_item_limit"`
30+
Next string `json:"next"`
31+
}
32+
33+
// Owner ...
34+
type Owner struct {
35+
AccountType string `json:"account_type"`
36+
Name string `json:"name"`
37+
Slug string `json:"slug"`
38+
}
39+
40+
// Application ...
41+
type Application struct {
42+
Slug string `json:"slug"`
43+
Title string `json:"title"`
44+
ProjectType string `json:"project_type"`
45+
Provider string `json:"provider"`
46+
RepoOwner string `json:"repo_owner"`
47+
RepoURL string `json:"repo_url"`
48+
RepoSlug string `json:"repo_slug"`
49+
IsDisabled bool `json:"is_disabled"`
50+
Status int `json:"status"`
51+
IsPublic bool `json:"is_public"`
52+
Owner Owner `json:"owner"`
53+
}
54+
55+
// MyAppsResponse ...
56+
type MyAppsResponse struct {
57+
Data []Application `json:"data"`
58+
Paging Paging `json:"paging"`
59+
}
60+
61+
// BitriseClient ...
62+
type BitriseClient struct {
63+
accessToken string
64+
selectedAppSlug string
65+
headers map[string]string
66+
client http.Client
67+
}
68+
69+
// NewBitriseClient ...
70+
func NewBitriseClient(accessToken string) (*BitriseClient, []Application, error) {
71+
client := &BitriseClient{accessToken, "", map[string]string{"Authorization": "token " + accessToken}, http.Client{}}
72+
var apps []Application
73+
74+
log.Infof("Fetching your application list from Bitrise...")
75+
76+
requestURL, err := urlutil.Join(baseURL, appsEndPoint)
77+
if err != nil {
78+
return nil, nil, err
79+
}
80+
81+
log.Debugf("\nRequest URL: %s", requestURL)
82+
83+
// Response struct
84+
var appListResponse MyAppsResponse
85+
stillPaging := true
86+
var next string
87+
88+
for stillPaging {
89+
headers := client.headers
90+
91+
request, err := createRequest(http.MethodGet, requestURL, headers, nil)
92+
if err != nil {
93+
return nil, nil, err
94+
}
95+
96+
if len(next) > 0 {
97+
quearryValues := request.URL.Query()
98+
quearryValues.Add("next", next)
99+
request.URL.RawQuery = quearryValues.Encode()
100+
}
101+
102+
// Perform request
103+
response, _, err := RunRequest(client, request, &appListResponse)
104+
if err != nil {
105+
return nil, nil, err
106+
}
107+
108+
appListResponse = *response.(*MyAppsResponse)
109+
apps = append(apps, appListResponse.Data...)
110+
111+
if len(appListResponse.Paging.Next) > 0 {
112+
next = appListResponse.Paging.Next
113+
appListResponse = MyAppsResponse{}
114+
} else {
115+
stillPaging = false
116+
}
117+
}
118+
119+
return client, apps, nil
120+
}
121+
122+
// SetSelectedAppSlug ...
123+
func (client *BitriseClient) SetSelectedAppSlug(slug string) {
124+
client.selectedAppSlug = slug
125+
}
126+
127+
// RunRequest ...
128+
func RunRequest(client *BitriseClient, req *http.Request, requestResponse interface{}) (interface{}, []byte, error) {
129+
var responseBody []byte
130+
131+
if err := retry.Times(1).Wait(5 * time.Second).Try(func(attempt uint) error {
132+
body, statusCode, err := performRequest(client, req)
133+
if err != nil {
134+
log.Warnf("Attempt (%d) failed, error: %s", attempt+1, err)
135+
if !strings.Contains(err.Error(), "failed to perform request") {
136+
log.Warnf("Response status: %d", statusCode)
137+
log.Warnf("Body: %s", string(body))
138+
}
139+
return err
140+
}
141+
142+
// Parse JSON body
143+
if requestResponse != nil {
144+
if err := json.Unmarshal([]byte(body), &requestResponse); err != nil {
145+
return fmt.Errorf("failed to unmarshal response (%s), error: %s", body, err)
146+
}
147+
148+
logDebugPretty(&requestResponse)
149+
}
150+
responseBody = body
151+
152+
return nil
153+
}); err != nil {
154+
return nil, nil, err
155+
}
156+
157+
return requestResponse, responseBody, nil
158+
}
159+
160+
func createUploadRequest(requestMethod string, url string, headers map[string]string, filePth string) (*http.Request, error) {
161+
var content []byte
162+
163+
f, err := os.Open(filePth)
164+
if err != nil {
165+
return nil, err
166+
167+
}
168+
169+
content, err = ioutil.ReadAll(f)
170+
if err != nil {
171+
return nil, err
172+
}
173+
174+
req, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(content))
175+
if err != nil {
176+
return nil, err
177+
}
178+
addHeaders(req, headers)
179+
180+
return req, nil
181+
}
182+
183+
func createRequest(requestMethod string, url string, headers map[string]string, fields map[string]interface{}) (*http.Request, error) {
184+
var b bytes.Buffer
185+
186+
if len(fields) > 0 {
187+
err := json.NewEncoder(&b).Encode(fields)
188+
if err != nil {
189+
return nil, err
190+
}
191+
}
192+
193+
log.Debugf("Request body: %s", string(b.Bytes()))
194+
195+
req, err := http.NewRequest(requestMethod, url, bytes.NewReader(b.Bytes()))
196+
if err != nil {
197+
return nil, err
198+
}
199+
addHeaders(req, headers)
200+
201+
return req, nil
202+
}
203+
204+
func performRequest(bitriseClient *BitriseClient, request *http.Request) (body []byte, statusCode int, err error) {
205+
response, err := bitriseClient.client.Do(request)
206+
if err != nil {
207+
// On error, any Response can be ignored
208+
return nil, -1, fmt.Errorf("failed to perform request, error: %s", err)
209+
}
210+
211+
// The client must close the response body when finished with it
212+
defer func() {
213+
if cerr := response.Body.Close(); err != nil {
214+
cerr = fmt.Errorf("Failed to close response body, error: %s", cerr)
215+
}
216+
}()
217+
218+
body, err = ioutil.ReadAll(response.Body)
219+
if err != nil {
220+
return []byte{}, response.StatusCode, fmt.Errorf("failed to read response body, error: %s", err)
221+
}
222+
223+
if response.StatusCode < http.StatusOK || response.StatusCode > http.StatusMultipleChoices {
224+
return body, response.StatusCode, errors.New("non success status code")
225+
}
226+
227+
return body, response.StatusCode, nil
228+
}
229+
230+
func addHeaders(req *http.Request, headers map[string]string) {
231+
for key, value := range headers {
232+
req.Header.Add(key, value)
233+
}
234+
}
235+
236+
func logDebugPretty(v interface{}) {
237+
indentedBytes, err := json.MarshalIndent(v, "", " ")
238+
if err != nil {
239+
fmt.Println("error:", err)
240+
}
241+
242+
log.Debugf("Response: %+v\n", string(indentedBytes))
243+
}

0 commit comments

Comments
 (0)