-
Notifications
You must be signed in to change notification settings - Fork 37
Upload generated provisioning profiles to Bitrise #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
a72d65a to
1770629
Compare
1770629 to
a76b279
Compare
- uploaders/common.go: error handling for io.Copy() - uploaders/requestResponse: Doc fix
uploaders/common.go
Outdated
| @@ -0,0 +1,322 @@ | |||
| package uploaders | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the main file's name of a package .go should be the package name: uploaders.go
uploaders/common.go
Outdated
|
|
||
| // AskAccessToken ... | ||
| func AskAccessToken() (token string, err error) { | ||
| messageToAsk := "Please copy your personal access token to Bitrise.\n" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use '`' syntax to define multi line string:
uploaders/common.go
Outdated
| func createRequestURLForMyApps() string { | ||
| requestURL, err := urlutil.Join(baseURL, myAppsEndPoint) | ||
| if err != nil { | ||
| failWithMessage("failed to create request URL, error: %s", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- do not call os exit int this kind of small units (its i ok in main())
- do not separate this to a new function: it is only used by one other function and has only one fn call
uploaders/common.go
Outdated
| return req | ||
| } | ||
|
|
||
| func createRequest(url string, fields map[string]interface{}, requestMethod httpMethod, headers map[string]string) (*http.Request, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- recommended input order: method, url, headers, body
- no need to define httpMethod struct (we use only two method: "GET" and "POST" + they are short and well known)
uploaders/common.go
Outdated
| } | ||
|
|
||
| func createRequest(url string, fields map[string]interface{}, requestMethod httpMethod, headers map[string]string) (*http.Request, error) { | ||
| b := new(bytes.Buffer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to explicit initialize b: var b bytes.Buffer works great and shows, that we do not care about its initial value.
uploaders/common.go
Outdated
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if _, err := io.Copy(os.Stdout, req.Body); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we copy the body to stdout?
uploaders/common.go
Outdated
| return requestURL | ||
| } | ||
|
|
||
| func createRequestURLForProvProfSlug(appSlug string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not separate this logic into a new function
uploaders/common.go
Outdated
| return requestURL | ||
| } | ||
|
|
||
| func failWithMessage(format string, v ...interface{}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid os exiting in package!
uploaders/httpMethod.go
Outdated
| @@ -0,0 +1,25 @@ | |||
| package uploaders | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use snake_case go file names: http_method.go
based on my previous comment: remove this file!
uploaders/requestResponse.go
Outdated
| } | ||
|
|
||
| // Appliocation ... | ||
| type Appliocation struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type Appliocation
uploaders/requestResponse.go
Outdated
| @@ -0,0 +1,45 @@ | |||
| package uploaders | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may call this file: models.go
uploaders/common.go
Outdated
| return nil | ||
| } | ||
|
|
||
| func createUploadRequest(url string, files map[string]string, requestMethod httpMethod, headers map[string]string) *http.Request { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there are several 'commonly' used functions you can move them into: common.go file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure about this?
I think it would be better if every "network type" function will be under the uploaders package and not the cmd package.
cmd/common.go
Outdated
| // ---------------------------------------------------------------- | ||
| // --- Upload methods | ||
|
|
||
| // TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid leaving TODO comment in your code!
cmd/common.go
Outdated
|
|
||
| // TODO | ||
| func uploadProvisioningProfiles(profilesToUpload []profileutil.ProvisioningProfileInfoModel, outputDirPath string) error { | ||
| // Get accesToken from stdin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this comment AskAccessToken is a descriptive name
cmd/common.go
Outdated
| // TODO | ||
| func uploadProvisioningProfiles(profilesToUpload []profileutil.ProvisioningProfileInfoModel, outputDirPath string) error { | ||
| // Get accesToken from stdin | ||
| accessToken, err := uploaders.AskAccessToken() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AskAccessToken does not belong to uploaders, do it here in common.go
cmd/common.go
Outdated
| // Get accesToken from stdin | ||
| accessToken, err := uploaders.AskAccessToken() | ||
|
|
||
| appList, err := uploaders.FetchMyApps(accessToken) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uploaders.FetchMyApps() is a strange function name.
may the uploaders package should be: bitriseclient, this way:
client := bitriseclient.New(AccessToken)
client.FetchMyApps()
client.UploadProfiles()
entc...
creating a Client model may worth, since you need to use AccessToken at every request.
|
|
||
| // Upload provisioning profiles | ||
| for _, profile := range profilesToUpload { | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid unnecessary empty lines!
|
|
||
| exportFileName := provProfileExportFileName(profile, outputDirPath) | ||
|
|
||
| provProfile, err := os.Open(outputDirPath + "/" + exportFileName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do this size calculation in RegisterProvisioningProfile
cmd/common.go
Outdated
| } | ||
|
|
||
| err = uploaders.UploadProvisioningProfile(provProfSlugResponseData, outputDirPath, exportFileName) | ||
| if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if function returns only a single error, define and check the error in if statement:
if err := uploaders.UploadProvisioningProfile(provProfSlugResponseData, outputDirPath, exportFileName); err != nil {
}
avoid using err = xyz() this can easily lead to a shadowed error! always try to define the error like: err := xyz()
cmd/common.go
Outdated
| bytes := info.Size() | ||
| log.Debugf("\n%s size: %d", exportFileName, bytes) | ||
|
|
||
| provProfSlugResponseData, err := uploaders.RegisterProvisioningProfile(accessToken, selectedApp.Slug, bytes, profile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems we only use RegisterProvisioningProfileResponseData's UploadURL and UploadFileName, return this values in RegisterProvisioningProfile instead of a new model with unused fields
cmd/common.go
Outdated
| return nil | ||
| } | ||
|
|
||
| func selectApp(appList []uploaders.Appliocation) (seledtedApp uploaders.Appliocation, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please check which fields of the app is used if there is no more then 2 fields may we do not need a struct.
cmd/common.go
Outdated
| } | ||
|
|
||
| func selectApp(appList []uploaders.Appliocation) (seledtedApp uploaders.Appliocation, err error) { | ||
| selectionList := []string{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we do not care about initial value, use: var selectionList []string
cmd/common.go
Outdated
|
|
||
| log.Debugf("selected app: %v", userSelection) | ||
|
|
||
| selectedApp, err := getAppFromUserSelection(userSelection, appList) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this function:
- sort the selectionList
- then find the selected index by: sort.Search...
- then appList[i] is the app
also you can return this function: return getAppFromUserSelection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed to the sort.Search() method as you advised, but I have not removed the getAppFromUserSelection() because it has tests.
godrei
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please have a look on my comments
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;
bitriseclient/bitriseclient.go
Outdated
|
|
||
| // Response struct | ||
| var appListResponse FetchMyAppsResponse | ||
| responseStatusCode := -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we use it?
bitriseclient/certificate.go
Outdated
|
|
||
| // Response struct | ||
| requestResponse := FetchUploadedIdentityListResponse{} | ||
| responseStatusCode := -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we use it?
bitriseclient/certificate.go
Outdated
| log.Debugf("\nRequest URL: %s", requestURL) | ||
|
|
||
| // Response struct | ||
| requestResponse := FetchUploadedIdentityListResponse{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var
bitriseclient/certificate.go
Outdated
| } | ||
|
|
||
| // Response struct | ||
| responseStatusCode := -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we use it?
| return "", err | ||
| } | ||
|
|
||
| data, err := profileutil.NewProvisioningProfileInfo(*plistData, profileutil.ProfileTypeIos) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return profileutil.NewProvisioningProfileInfo(*plistData, profileutil.ProfileTypeIos)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only need the UUID
bitriseclient/certificate.go
Outdated
| // Perform request | ||
| if err := retry.Times(1).Wait(5 * time.Second).Try(func(attempt uint) error { | ||
| body, statusCode, err := performRequest(request) | ||
| if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing is: if the request returns non success status code, the erro will be nil.
later you do not check the status code, probably the json marshal would fail, since in case of error the response is something else then the success model, but fail fast!
please check the status code and retry if non success received
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, but the performRequest do this already. If the status code != statusOK it will return an error.
cmd/common.go
Outdated
| return nil | ||
| } | ||
|
|
||
| func uploadExportedFiles(profilesToExport []profileutil.ProvisioningProfileInfoModel, certificatesToExport []certificateutil.CertificateInfoModel, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not use named returns values in this long func
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need it here because this func returns 2 bool attr. and it can cause a misconception.
And if the provisioning profiles are uploaded successfully but the certs. are not, only the first bool (provProfilesUploaded) will be true.
cmd/common.go
Outdated
| fmt.Println() | ||
| log.Infof("Looking for certificate duplicates on Bitrise...") | ||
|
|
||
| uploadedCertificatesSerialList := []string{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var
cmd/common.go
Outdated
|
|
||
| // Get uploaded certificates' serials | ||
| for _, uploadedIdentity := range uploadedItentityList { | ||
| serialListAsString := []string{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var
cmd/common.go
Outdated
| return err | ||
| } | ||
|
|
||
| bytes := info.Size() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this new var
cmd/common.go
Outdated
| return err | ||
| } | ||
|
|
||
| if err := bitriseClient.ConfirmIdentityUpload(certificateResponseData.Slug, certificateResponseData.UploadFileName); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return bitriseClient.ConfirmIdentityUpload(certificateResponseData.Slug, certificateResponseData.UploadFileName)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do that but I think it will break the code's continuity. (The previous func call looks the same).
That's why I would not change the return statement.
| } | ||
|
|
||
| userSelection, err := goinp.SelectFromStringsWithDefault("Select the app which you want to upload the privisioning profiles", 1, selectionList) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this empty line
cmd/common.go
Outdated
| return err | ||
| } | ||
|
|
||
| bytes := info.Size() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for new var
cmd/common.go
Outdated
| func askUploadGeneratedFiles() (bool, error) { | ||
| messageToAsk := "Do you want to upload the provisioning profiles and certificates to Bitrise?" | ||
|
|
||
| answer, err := goinp.AskForBoolFromReader(messageToAsk, os.Stdin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return goinp.AskForBoolFromReader(messageToAsk, os.Stdin)
cmd/common.go
Outdated
| func askUploadIdentities() (bool, error) { | ||
| messageToAsk := "Do you want to upload the certificates to Bitrise?" | ||
|
|
||
| answer, err := goinp.AskForBoolFromReader(messageToAsk, os.Stdin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return goinp.AskForBoolFromReader(messageToAsk, os.Stdin)
cmd/common.go
Outdated
| fmt.Println() | ||
| log.Infof("Looking for provisioning profile duplicates on Bitrise...") | ||
|
|
||
| uploadedProfileUUIDList := []string{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
map would be much better for this purpose, no need for IsStringInSlice:
uploadedProfileUUIDList := map[string]bool{}
bitriseclient/bitriseclient.go
Outdated
| client := &BitriseClient{accessToken, "", map[string]string{"Authorization": "token " + accessToken}} | ||
| var apps []Application | ||
|
|
||
| log.Infof("Asking your application list from Bitrise...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asking -> fetching
bitriseclient/bitriseclient.go
Outdated
|
|
||
| for key, value := range headers { | ||
| req.Header.Add(key, value) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please remove unused newlines
bitriseclient/certificate.go
Outdated
|
|
||
| // | ||
| // Perform request | ||
| if err := retry.Times(1).Wait(5 * time.Second).Try(func(attempt uint) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please shorten these long logics.
bitriseclient/certificate.go
Outdated
| } | ||
|
|
||
| // FetchIdentityResponseData ... | ||
| type FetchIdentityResponseData struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please shorten model names and also remove un-relevant part of the names
| } | ||
|
|
||
| // NewBitriseClient ... | ||
| func NewBitriseClient(accessToken string) (*BitriseClient, []Application, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please try to create an authenticated httpClient so you won't need to create it all the time and set the auth header for that.
Squashed commits: [e108a55] BitriseClient: RunRequest method (+2 squashed commits) Squashed commits: [53c1dba] Renames [181bf12] FetchIdentityListResponse rename
cmd/common.go
Outdated
| } | ||
|
|
||
| func uploadExportedFiles(profilesToExport []profileutil.ProvisioningProfileInfoModel, certificatesToExport []certificateutil.CertificateInfoModel, | ||
| outputDirPath string) (provProfilesUploaded bool, certsUploaded bool, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please separate the functionality into two functions rather than merging the return values together.
… and to uploadIdentity;
Only the prov. profiles.
The certificates will come on the next round.