Skip to content

Commit

Permalink
Exported functions (#105)
Browse files Browse the repository at this point in the history
* Create exported functions to use codesigndoc from package

* Move to function ExportCodesigningFiles export logic

* Improve logging

* Move log file writing to a closure

* Rename GenerateXcodeArchive to BuildXcodeArchive
  • Loading branch information
lpusok authored Jun 11, 2019
1 parent c82fde6 commit 55553b0
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 97 deletions.
38 changes: 20 additions & 18 deletions cmd/xamarin.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,34 +161,31 @@ func scanXamarinProject(cmd *cobra.Command, args []string) error {
fmt.Println()
fmt.Println()
log.Printf(`🔦 Running a Build, to get all the required code signing settings...`)
var isLogFileWritten bool
logOutputFilePath := filepath.Join(absExportOutputDirPath, "xamarin-build-output.log")

archivePath, logOutput, err := xamarinCmd.GenerateArchive()
if writeFiles == codesign.WriteFilesAlways ||
writeFiles == codesign.WriteFilesFallback && err != nil { // save the xamarin output into a debug log file
if writeFiles == codesign.WriteFilesAlways || writeFiles == codesign.WriteFilesFallback && err != nil { // save the xamarin output into a debug log file
if err := os.MkdirAll(absExportOutputDirPath, 0700); err != nil {
return fmt.Errorf("failed to create output directory, error: %s", err)
}

log.Infof("💡 "+colorstring.Yellow("Saving xamarin output into file")+": %s", logOutputFilePath)
if err := fileutil.WriteStringToFile(logOutputFilePath, logOutput); err != nil {
log.Errorf("Failed to save xamarin build output into file (%s), error: %s", logOutputFilePath, err)
} else {
isLogFileWritten = true
}
}
if err != nil {
log.Warnf("Last lines of build log:")
log.Warnf("Last lines of the build log:")
fmt.Println(stringutil.LastNLines(logOutput, 15))

log.Infof(colorstring.Yellow("Please check the build log to see what caused the error."))
fmt.Println()
if isLogFileWritten {
log.Warnf("Please check the logfile (%s) to see what caused the error", logOutputFilePath)
log.Warnf(`and make sure that you can "Archive for Publishing" this project from Xamarin!`)
fmt.Println()
log.Infof("Open the project: %s", xamarinCmd.SolutionFilePath)
log.Infof(`And do "Archive for Publishing", after selecting the Configuration+Platform: %s|%s`, xamarinCmd.Configuration, xamarinCmd.Platform)
fmt.Println()
}

log.Errorf("Build failed.")
log.Infof(colorstring.Yellow("Open the project: ")+"%s", xamarinCmd.SolutionFilePath)
log.Infof(colorstring.Yellow(`And do "Archive for Publishing", after selecting the Configuration+Platform: `)+"%s|%s", xamarinCmd.Configuration, xamarinCmd.Platform)
fmt.Println()

return ArchiveError{toolXamarin, "failed to run xamarin build command: " + err.Error()}
}

Expand All @@ -197,9 +194,14 @@ func scanXamarinProject(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
exoprtResult, err := codesign.UploadAndWriteCodesignFiles(certificatesToExport,
profilesToExport,
isAskForPassword,

certificates, profiles, err := codesign.ExportCodesigningFiles(certificatesToExport, profilesToExport, isAskForPassword)
if err != nil {
return err
}

exportResult, err := codesign.UploadAndWriteCodesignFiles(certificates,
profiles,
codesign.WriteFilesConfig{
WriteFiles: writeFiles,
AbsOutputDirPath: absExportOutputDirPath,
Expand All @@ -212,6 +214,6 @@ func scanXamarinProject(cmd *cobra.Command, args []string) error {
return err
}

printFinished(exoprtResult, absExportOutputDirPath)
printFinished(exportResult, absExportOutputDirPath)
return nil
}
64 changes: 19 additions & 45 deletions cmd/xcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import (
"github.com/bitrise-io/go-utils/fileutil"
"github.com/bitrise-io/go-utils/log"
"github.com/bitrise-io/go-utils/pathutil"
"github.com/bitrise-io/go-utils/stringutil"
"github.com/bitrise-io/go-xcode/utility"
"github.com/bitrise-io/goinp/goinp"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -54,29 +52,19 @@ func absOutputDir() (string, error) {
return absExportOutputDirPath, nil
}

func scanXcodeProject(cmd *cobra.Command, args []string) error {
func scanXcodeProject(_ *cobra.Command, _ []string) error {
absExportOutputDirPath, err := absOutputDir()
if err != nil {
return err
}

// Output tools versions
xcodebuildVersion, err := utility.GetXcodeVersion()
if err != nil {
return fmt.Errorf("failed to get Xcode (xcodebuild) version, error: %s", err)
}
fmt.Println()
log.Infof("%s: %s (%s)", colorstring.Green("Xcode (xcodebuild) version"), xcodebuildVersion.Version, xcodebuildVersion.BuildVersion)
fmt.Println()

xcodeCmd := xcode.CommandModel{}

projectPath := paramXcodeProjectFilePath
if projectPath == "" {
log.Infof("Scan the directory for project files")
log.Warnf("You can specify the Xcode project/workscape file to scan with the --file flag.")

//
// Scan the directory for Xcode Project (.xcworkspace / .xcodeproject) file first
// If can't find any, ask the user to drag-and-drop the file
projpth, err := findXcodeProject()
Expand Down Expand Up @@ -120,47 +108,33 @@ func scanXcodeProject(cmd *cobra.Command, args []string) error {
xcodeCmd.SDK = paramXcodebuildSDK
}

fmt.Println()
log.Printf("🔦 Running an Xcode Archive, to get all the required code signing settings...")
var isLogFileWritten bool
xcodebuildOutputFilePath := filepath.Join(absExportOutputDirPath, "xcodebuild-output.log")
archivePath, xcodebuildOutput, err := xcodeCmd.GenerateArchive()
writeBuildLogs := func(xcodebuildOutput string) error {
if writeFiles == codesign.WriteFilesAlways || writeFiles == codesign.WriteFilesFallback && err != nil { // save the xcodebuild output into a debug log file
xcodebuildOutputFilePath := filepath.Join(absExportOutputDirPath, "xcodebuild-output.log")
if err := os.MkdirAll(absExportOutputDirPath, 0700); err != nil {
return fmt.Errorf("failed to create output directory, error: %s", err)
}

if writeFiles == codesign.WriteFilesAlways ||
writeFiles == codesign.WriteFilesFallback && err != nil { // save the xcodebuild output into a debug log file
if err := os.MkdirAll(absExportOutputDirPath, 0700); err != nil {
return fmt.Errorf("failed to create output directory, error: %s", err)
}
log.Infof("💡 "+colorstring.Yellow("Saving xcodebuild output into file")+": %s", xcodebuildOutputFilePath)
if err := fileutil.WriteStringToFile(xcodebuildOutputFilePath, xcodebuildOutput); err != nil {
log.Errorf("Failed to save xcodebuild output into file (%s), error: %s", xcodebuildOutputFilePath, err)
} else {
isLogFileWritten = true
log.Infof("💡 "+colorstring.Yellow("Saving xcodebuild output into file")+": %s", xcodebuildOutputFilePath)
if err := fileutil.WriteStringToFile(xcodebuildOutputFilePath, xcodebuildOutput); err != nil {
return fmt.Errorf("Failed to save xcodebuild output into file (%s), error: %s", xcodebuildOutputFilePath, err)
}
}
return nil
}

archivePath, err := codesigndoc.BuildXcodeArchive(xcodeCmd, writeBuildLogs)
if err != nil {
log.Warnf("Last lines of build log:")
fmt.Println(stringutil.LastNLines(xcodebuildOutput, 15))
fmt.Println()
if isLogFileWritten {
log.Warnf("Please check the logfile (%s) to see what caused the error", xcodebuildOutputFilePath)
log.Warnf("and make sure that you can Archive this project from Xcode!")
fmt.Println()
log.Printf("Open the project: %s", xcodeCmd.ProjectFilePath)
log.Printf("and Archive, using the Scheme: %s", xcodeCmd.Scheme)
fmt.Println()
}
return ArchiveError{toolXcode, err.Error()}
}

// If certificatesOnly is set, CollectCodesignFiles returns an empty slice for profiles
certificatesToExport, profilesToExport, err := codesigndoc.CollectCodesignFiles(archivePath, certificatesOnly)
certificates, profiles, err := codesigndoc.CodesigningFilesForXCodeProject(archivePath, certificatesOnly, isAskForPassword)
if err != nil {
return err
}
exoprtResult, err := codesign.UploadAndWriteCodesignFiles(certificatesToExport,
profilesToExport,
isAskForPassword,

exportResult, err := codesign.UploadAndWriteCodesignFiles(certificates,
profiles,
codesign.WriteFilesConfig{
WriteFiles: writeFiles,
AbsOutputDirPath: absExportOutputDirPath,
Expand All @@ -173,6 +147,6 @@ func scanXcodeProject(cmd *cobra.Command, args []string) error {
return err
}

printFinished(exoprtResult, absExportOutputDirPath)
printFinished(exportResult, absExportOutputDirPath)
return nil
}
36 changes: 20 additions & 16 deletions cmd/xcodeUITests.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,35 +114,34 @@ func scanXcodeUITestsProject(cmd *cobra.Command, args []string) error {
xcodeUITestsCmd.SDK = paramXcodebuildSDK
}

fmt.Println()
fmt.Println()
log.Printf("🔦 Running an Xcode build-for-testing, to get all the required code signing settings...")
var isLogFileWritten bool
xcodebuildOutputFilePath := filepath.Join(absExportOutputDirPath, "xcodebuild-output.log")

buildForTestingPath, xcodebuildOutput, err := xcodeUITestsCmd.RunBuildForTesting()
if writeFiles == codesign.WriteFilesAlways ||
writeFiles == codesign.WriteFilesFallback && err != nil { // save the xcodebuild output into a debug log file
if writeFiles == codesign.WriteFilesAlways || writeFiles == codesign.WriteFilesFallback && err != nil { // save the xcodebuild output into a debug log file
if err := os.MkdirAll(absExportOutputDirPath, 0700); err != nil {
return fmt.Errorf("failed to create output directory, error: %s", err)
}

log.Infof("💡 "+colorstring.Yellow("Saving xcodebuild output into file")+": %s", xcodebuildOutputFilePath)
if err := fileutil.WriteStringToFile(xcodebuildOutputFilePath, xcodebuildOutput); err != nil {
log.Errorf("Failed to save xcodebuild output into file (%s), error: %s", xcodebuildOutputFilePath, err)
} else {
isLogFileWritten = true
}
}
if err != nil {
log.Warnf("Last lines of build log:")
log.Warnf("Last lines of the build log:")
fmt.Println(stringutil.LastNLines(xcodebuildOutput, 15))

log.Infof(colorstring.Yellow("Please check the build log to see what caused the error."))
fmt.Println()
if isLogFileWritten {
log.Warnf("Please check the logfile (%s) to see what caused the error", xcodebuildOutputFilePath)
log.Warnf("and make sure that you can run Build for testing against the project from Xcode!")
fmt.Println()
log.Printf("Open the project: %s", xcodeUITestsCmd.ProjectFilePath)
fmt.Println()
}

log.Errorf("Xcode Build For Testing failed.")
log.Infof(colorstring.Yellow("Open the project: ")+"%s", xcodeUITestsCmd.ProjectFilePath)
log.Infof(colorstring.Yellow("and make sure that you can run Build For Testing, with the scheme: ")+"%s", xcodeUITestsCmd.Scheme)
fmt.Println()

return BuildForTestingError{toolXcode, err.Error()}
}

Expand All @@ -151,9 +150,14 @@ func scanXcodeUITestsProject(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
exportResult, err := codesign.UploadAndWriteCodesignFiles(certificatesToExport,
profilesToExport,
isAskForPassword,

certificates, profiles, err := codesign.ExportCodesigningFiles(certificatesToExport, profilesToExport, isAskForPassword)
if err != nil {
return err
}

exportResult, err := codesign.UploadAndWriteCodesignFiles(certificates,
profiles,
codesign.WriteFilesConfig{
WriteFiles: writeFiles,
AbsOutputDirPath: absExportOutputDirPath,
Expand Down
43 changes: 25 additions & 18 deletions codesign/export.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package codesign

import (
"bytes"
"errors"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -53,38 +52,49 @@ type ExportReport struct {
CodesignFilesWritten bool
}

// UploadAndWriteCodesignFiles exports then uploads codesign files to bitrise.io and saves them to output folder
func UploadAndWriteCodesignFiles(certificates []certificateutil.CertificateInfoModel, profiles []profileutil.ProvisioningProfileInfoModel, askForPassword bool, writeFilesConfig WriteFilesConfig, uploadConfig UploadConfig) (ExportReport, error) {
identities, err := collectAndExportIdentities(certificates, askForPassword)
// ExportCodesigningFiles exports certificates from the Keychain and provisoining profiles from their directory
func ExportCodesigningFiles(certificatesRequired []certificateutil.CertificateInfoModel, profilesRequired []profileutil.ProvisioningProfileInfoModel, askForPassword bool) (models.Certificates, []models.ProvisioningProfile, error) {
certificates, err := exportIdentities(certificatesRequired, askForPassword)
if err != nil {
return ExportReport{}, err
return models.Certificates{}, nil, err
}
provisioningProfiles, err := collectAndExportProvisioningProfiles(profiles)

profiles, err := exportProvisioningProfiles(profilesRequired)
if err != nil {
return ExportReport{}, err
return models.Certificates{}, nil, err
}

return certificates, profiles, nil
}

// UploadAndWriteCodesignFiles exports then uploads codesign files to bitrise.io and saves them to output folder
func UploadAndWriteCodesignFiles(certificates models.Certificates, provisioningProfiles []models.ProvisioningProfile, writeFilesConfig WriteFilesConfig, uploadConfig UploadConfig) (ExportReport, error) {
var client *bitrise.Client
// both or none CLI flags are required
if uploadConfig.PersonalAccessToken != "" && uploadConfig.AppSlug != "" {
// Upload automatically if token is provided as CLI paramter, do not export to filesystem
// Used to upload artifacts as part of an other CLI tool
var err error
client, err = bitrise.NewClient(uploadConfig.PersonalAccessToken)
if err != nil {
return ExportReport{}, err
}

client.SetSelectedAppSlug(uploadConfig.AppSlug)
}

if client == nil {
uploadConfirmMsg := "Do you want to upload the provisioning profiles and certificates to Bitrise?"
if len(provisioningProfiles) == 0 {
uploadConfirmMsg = "Do you want to upload the certificates to Bitrise?"
}
fmt.Println()

shouldUpload, err := goinp.AskForBoolFromReader(uploadConfirmMsg, os.Stdin)
if err != nil {
return ExportReport{}, err
}

if shouldUpload {
if client, err = bitriseio.GetInteractiveConfigClient(); err != nil {
return ExportReport{}, err
Expand All @@ -95,21 +105,21 @@ func UploadAndWriteCodesignFiles(certificates []certificateutil.CertificateInfoM
var filesWritten bool
if writeFilesConfig.WriteFiles == WriteFilesAlways ||
writeFilesConfig.WriteFiles == WriteFilesFallback && client == nil {
if err := writeFiles(identities, provisioningProfiles, writeFilesConfig); err != nil {
if err := writeFiles(certificates, provisioningProfiles, writeFilesConfig); err != nil {
return ExportReport{}, err
}
filesWritten = true
}

if client == nil {
return ExportReport{
CertificatesUploaded: len(certificates) == 0,
ProvisioningProfilesUploaded: len(profiles) == 0,
CertificatesUploaded: len(certificates.Info) == 0,
ProvisioningProfilesUploaded: len(provisioningProfiles) == 0,
CodesignFilesWritten: filesWritten,
}, nil
}

certificatesUploaded, profilesUploaded, err := bitriseio.UploadCodesigningFiles(client, identities, provisioningProfiles)
certificatesUploaded, profilesUploaded, err := bitriseio.UploadCodesigningFiles(client, certificates, provisioningProfiles)
return ExportReport{
CertificatesUploaded: certificatesUploaded,
ProvisioningProfilesUploaded: profilesUploaded,
Expand Down Expand Up @@ -147,8 +157,8 @@ func writeFiles(identities models.Certificates, provisioningProfiles []models.Pr
return nil
}

// collectAndExportIdentities exports the given certificates merged in a single .p12 file
func collectAndExportIdentities(certificates []certificateutil.CertificateInfoModel, isAskForPassword bool) (models.Certificates, error) {
// exportIdentities exports the given certificates merged in a single .p12 file
func exportIdentities(certificates []certificateutil.CertificateInfoModel, isAskForPassword bool) (models.Certificates, error) {
if len(certificates) == 0 {
return models.Certificates{}, nil
}
Expand Down Expand Up @@ -215,8 +225,8 @@ func writeIdentities(identites []byte, absExportOutputDirPath string) error {
return ioutil.WriteFile(filepath.Join(absExportOutputDirPath, "Identities.p12"), identites, 0600)
}

// collectAndExportProvisioningProfiles returns provisioning profies
func collectAndExportProvisioningProfiles(profiles []profileutil.ProvisioningProfileInfoModel) ([]models.ProvisioningProfile, error) {
// exportProvisioningProfiles returns provisioning profies
func exportProvisioningProfiles(profiles []profileutil.ProvisioningProfileInfoModel) ([]models.ProvisioningProfile, error) {
if len(profiles) == 0 {
return nil, nil
}
Expand All @@ -242,9 +252,6 @@ func collectAndExportProvisioningProfiles(profiles []profileutil.ProvisioningPro
if err != nil {
return nil, fmt.Errorf("failed to parse exported profile, error: %s", err)
}
if bytes.Compare(profile.Content(), exportedProfile.Content()) != 0 {
return nil, fmt.Errorf("Profile found in the archive does not match found profile")
}

contents, err := ioutil.ReadFile(pth)
if err != nil {
Expand Down
Loading

0 comments on commit 55553b0

Please sign in to comment.