Skip to content

Commit

Permalink
Add fallback zip reader to the ipa uploader (#199)
Browse files Browse the repository at this point in the history
* Add flabck zip reader to the ipa uploader

* Code cleanup

* Wire in new zip reader to the xcarchive uploader

* Update go-xcode

* Pull lates go-xcode and code cleanup

* Pull latest go-xcode

* Pull latest go-xcode

* Pull [email protected]
  • Loading branch information
godrei authored Apr 18, 2024
1 parent 03ba0ca commit 5ae9364
Show file tree
Hide file tree
Showing 16 changed files with 418 additions and 277 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ require (
github.com/bitrise-io/go-android v0.0.0-20210517091621-72f0eb7a5197
github.com/bitrise-io/go-steputils v1.0.5
github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.20
github.com/bitrise-io/go-utils v1.0.11
github.com/bitrise-io/go-utils v1.0.12
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.20
github.com/bitrise-io/go-xcode v1.0.18
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.41
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.44
github.com/google/go-cmp v0.5.9
github.com/gorilla/mux v1.8.0
github.com/pkg/errors v0.9.1
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ github.com/bitrise-io/go-utils v0.0.0-20210505121718-07411d72e36e/go.mod h1:nhda
github.com/bitrise-io/go-utils v0.0.0-20210507100250-37de47dfa6ce/go.mod h1:15EZZf02noI5nWFqXMZEoyb1CyqYRXTMz5Fyu4CWFzI=
github.com/bitrise-io/go-utils v1.0.1/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY=
github.com/bitrise-io/go-utils v1.0.2/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY=
github.com/bitrise-io/go-utils v1.0.11 h1:NJ9rRWif4C6nhdh/v6Y/sJZU1UJ+yj0mDgnxsDr71ho=
github.com/bitrise-io/go-utils v1.0.11/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY=
github.com/bitrise-io/go-utils v1.0.12 h1:iJV1ZpyvSA0NCte/N6x+aIQ9TrNr5sIBlcJBf0dn1dE=
github.com/bitrise-io/go-utils v1.0.12/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY=
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.10/go.mod h1:Ta/ards3Ih/3Q6X8tBtcj6zTHcNf1hRSXv1E8lPgIYk=
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.20 h1:R+xJRWsuHhF/Pnx0gjI1+HH4Y0YSFVI+U/CbLpSx4sU=
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.20/go.mod h1:Laih4ji980SQkRgdnMCH0g4u2GZI/5nnbqmYT9UfKFQ=
github.com/bitrise-io/go-xcode v1.0.18 h1:guFywV/AwcZuexqIQkL1ixc3QThpbJvA4voa9MqvPto=
github.com/bitrise-io/go-xcode v1.0.18/go.mod h1:9OwsvrhZ4A2JxHVoEY7CPcABAKA+OE7FQqFfBfvbFuY=
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.41 h1:c2+CAi77gqQzs7IfXXeN1zzM2kgl+xxkaDmD68rci9c=
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.41/go.mod h1:Y3K7ay6Q+znVKFmGGvr4jijnN8QmTBxB5+CatRtBl30=
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.44 h1:TTPF1W/9RcwIXdT2GY3xRj8f4h22JZUwJNLpqQYJHoQ=
github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.44/go.mod h1:BFDhHF1ftPWpnZt4sjpPQ+H6QaQLkRoNwQZC2/xdcgg=
github.com/bitrise-io/goinp v0.0.0-20210504152833-8559b0680ab1/go.mod h1:iRbd8zAXLeNy+0gic0eqNCxXvDGe8ZEY/uYX2CCeAoo=
github.com/bitrise-io/goinp v0.0.0-20211005113137-305e91b481f4 h1:ytUxnO7iSGHlNpbdjhDUefEM5WRy1kD2ElGfBA7r1PE=
github.com/bitrise-io/goinp v0.0.0-20211005113137-305e91b481f4/go.mod h1:iRbd8zAXLeNy+0gic0eqNCxXvDGe8ZEY/uYX2CCeAoo=
Expand Down
117 changes: 61 additions & 56 deletions uploaders/ipauploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,82 @@ package uploaders
import (
"fmt"

"github.com/bitrise-io/go-utils/log"
logV2 "github.com/bitrise-io/go-utils/v2/log"
"github.com/bitrise-io/go-xcode/exportoptions"
"github.com/bitrise-io/go-xcode/v2/artifacts"
"github.com/bitrise-io/go-xcode/v2/zip"
"github.com/bitrise-steplib/steps-deploy-to-bitrise-io/deployment"
)

// DeployIPA ...
func DeployIPA(item deployment.DeployableItem, buildURL, token, notifyUserGroups, notifyEmails string, isEnablePublicPage bool) (ArtifactURLs, error) {
logger := logV2.NewLogger()
pth := item.Path

reader, err := zip.NewReader(pth, logV2.NewLogger())
appInfo, provisioningInfo, err := readIPADeploymentMeta(pth, logger)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to open ipa file %s, error: %s", pth, err)
return ArtifactURLs{}, fmt.Errorf("failed to parse deployment info for %s: %w", pth, err)
}

if provisioningInfo["ipa_export_method"] == exportoptions.MethodAppStore {
logger.Warnf("is_enable_public_page is set, but public download isn't allowed for app-store distributions")
logger.Warnf("setting is_enable_public_page to false ...")
isEnablePublicPage = false
}

fileSize, err := fileSizeInBytes(pth)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to get size of %s: %w", pth, err)
}

ipaInfoMap := map[string]interface{}{
"file_size_bytes": fmt.Sprintf("%f", fileSize),
"app_info": appInfo,
"provisioning_info": provisioningInfo,
}

logger.Printf("ipa infos: %v", appInfo)

const IPAContentType = "application/octet-stream ipa"
uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "ios-ipa", IPAContentType)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to create ipa artifact from %s: %w", pth, err)
}

if err := UploadArtifact(uploadURL, pth, IPAContentType); err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to upload ipa (%s): %w", pth, err)
}

buildArtifactMeta := AppDeploymentMetaData{
ArtifactInfo: ipaInfoMap,
NotifyUserGroups: notifyUserGroups,
NotifyEmails: notifyEmails,
IsEnablePublicPage: isEnablePublicPage,
}

artifactURLs, err := finishArtifact(buildURL, token, artifactID, &buildArtifactMeta, item.IntermediateFileMeta)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to finish ipa (%s) upload: %w", pth, err)
}

return artifactURLs, nil
}

func readIPADeploymentMeta(ipaPth string, logger logV2.Logger) (map[string]interface{}, map[string]interface{}, error) {
reader, err := zip.NewDefaultReader(ipaPth, logger)
if err != nil {
return nil, nil, err
}
defer func() {
if err := reader.Close(); err != nil {
log.Warnf("Failed to close archive: %s", pth)
logger.Warnf("%s", err)
}
}()

ipaReader := zip.NewIPAReader(*reader)
ipaReader := artifacts.NewIPAReader(reader)
infoPlist, err := ipaReader.AppInfoPlist()
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to unwrap Info.plist from ipa, error: %s", err)
return nil, nil, fmt.Errorf("failed to unwrap Info.plist from ipa: %w", err)
}

appTitle, _ := infoPlist.GetString("CFBundleName")
Expand All @@ -46,74 +97,28 @@ func DeployIPA(item deployment.DeployableItem, buildURL, token, notifyUserGroups
"device_family_list": deviceFamilyList,
}

log.Printf("ipa infos: %v", appInfo)

// ---
provisioningProfileInfo, err := ipaReader.ProvisioningProfileInfo()
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to read profile info: %w", err)
return nil, nil, fmt.Errorf("failed to read profile info from ipa: %w", err)
}

teamName := provisioningProfileInfo.TeamName
creationDate := provisioningProfileInfo.CreationDate
provisionsAlldevices := provisioningProfileInfo.ProvisionsAllDevices
provisionsAllDevices := provisioningProfileInfo.ProvisionsAllDevices
expirationDate := provisioningProfileInfo.ExpirationDate
deviceUDIDList := provisioningProfileInfo.ProvisionedDevices
profileName := provisioningProfileInfo.Name
exportMethod := provisioningProfileInfo.ExportType

if exportMethod == exportoptions.MethodAppStore {
log.Warnf("is_enable_public_page is set, but public download isn't allowed for app-store distributions")
log.Warnf("setting is_enable_public_page to false ...")
isEnablePublicPage = false
}

provisioningInfo := map[string]interface{}{
"creation_date": creationDate,
"expire_date": expirationDate,
"device_UDID_list": deviceUDIDList,
"team_name": teamName,
"profile_name": profileName,
"provisions_all_devices": provisionsAlldevices,
"provisions_all_devices": provisionsAllDevices,
"ipa_export_method": exportMethod,
}

// ---

fileSize, err := fileSizeInBytes(pth)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to get ipa size, error: %s", err)
}

ipaInfoMap := map[string]interface{}{
"file_size_bytes": fmt.Sprintf("%f", fileSize),
"app_info": appInfo,
"provisioning_info": provisioningInfo,
}

// ---

const IPAContentType = "application/octet-stream ipa"
uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "ios-ipa", IPAContentType)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to create ipa artifact: %s %w", pth, err)
}

if err := UploadArtifact(uploadURL, pth, IPAContentType); err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to upload ipa artifact, error: %s", err)
}

buildArtifactMeta := AppDeploymentMetaData{
ArtifactInfo: ipaInfoMap,
NotifyUserGroups: notifyUserGroups,
NotifyEmails: notifyEmails,
IsEnablePublicPage: isEnablePublicPage,
}

artifactURLs, err := finishArtifact(buildURL, token, artifactID, &buildArtifactMeta, item.IntermediateFileMeta)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to finish ipa artifact, error: %s", err)
}

return artifactURLs, nil
return appInfo, provisioningInfo, nil
}
101 changes: 55 additions & 46 deletions uploaders/xcarchiveuploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,85 @@ package uploaders
import (
"fmt"

"github.com/bitrise-io/go-utils/log"
logV2 "github.com/bitrise-io/go-utils/v2/log"
"github.com/bitrise-io/go-xcode/v2/artifacts"
"github.com/bitrise-io/go-xcode/v2/zip"
"github.com/bitrise-steplib/steps-deploy-to-bitrise-io/deployment"
)

// DeployXcarchive ...
func DeployXcarchive(item deployment.DeployableItem, buildURL, token string) (ArtifactURLs, error) {
logger := logV2.NewLogger()
pth := item.Path

reader, err := zip.NewReader(pth, logV2.NewLogger())
appInfo, scheme, err := readXCArchiveDeploymentMeta(pth, logger)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to open ipa file %s, error: %s", pth, err)
return ArtifactURLs{}, fmt.Errorf("failed to parse deployment info for %s: %w", pth, err)
}

fileSize, err := fileSizeInBytes(pth)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to get size of %s: %w", pth, err)
}

xcarchiveInfoMap := map[string]interface{}{
"file_size_bytes": fmt.Sprintf("%f", fileSize),
"app_info": appInfo,
"scheme": scheme,
}

logger.Printf("xcarchive infos: %v", appInfo)

uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "ios-xcarchive", "")
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to create xcarchive artifact from %s %w", pth, err)
}

if err := UploadArtifact(uploadURL, pth, ""); err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to upload xcarchive (%s): %w", pth, err)
}

buildArtifactMeta := AppDeploymentMetaData{
ArtifactInfo: xcarchiveInfoMap,
NotifyUserGroups: "",
NotifyEmails: "",
IsEnablePublicPage: false,
}

artifactURLs, err := finishArtifact(buildURL, token, artifactID, &buildArtifactMeta, item.IntermediateFileMeta)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to finish xcarchive (%s) upload: %w", pth, err)
}

return artifactURLs, nil
}

func readXCArchiveDeploymentMeta(xcarchivePth string, logger logV2.Logger) (map[string]interface{}, string, error) {
reader, err := zip.NewDefaultReader(xcarchivePth, logger)
if err != nil {
return nil, "", err
}
defer func() {
if err := reader.Close(); err != nil {
log.Warnf("Failed to close archive: %s", pth)
logger.Warnf("%s", err)
}
}()

xcarchiveReader := zip.NewXCArchiveReader(*reader)
xcarchiveReader := artifacts.NewXCArchiveReader(reader)
isMacos := xcarchiveReader.IsMacOS()
if isMacos {
log.Warnf("macOS archive deployment is not supported, skipping file: %s", pth)
return ArtifactURLs{}, nil // MacOS project is not supported, so won't be deployed.
logger.Warnf("macOS archive deployment is not supported, skipping xcarchive")
return nil, "", nil // MacOS project is not supported, so won't be deployed.
}
archiveInfoPlist, err := xcarchiveReader.InfoPlist()
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to parse archive Info.plist from %s: %s", pth, err)
return nil, "", fmt.Errorf("failed to unwrap Info.plist from xcarchive: %w", err)
}

iosXCArchiveReader := zip.NewIOSXCArchiveReader(*reader)
iosXCArchiveReader := artifacts.NewIOSXCArchiveReader(reader)
appInfoPlist, err := iosXCArchiveReader.AppInfoPlist()
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to parse application Info.plist from %s: %s", pth, err)
return nil, "", fmt.Errorf("failed to unwrap application Info.plist from xcarchive: %w", err)
}

appTitle, _ := appInfoPlist.GetString("CFBundleName")
Expand All @@ -57,40 +101,5 @@ func DeployXcarchive(item deployment.DeployableItem, buildURL, token string) (Ar
"device_family_list": deviceFamilyList,
}

// ---

fileSize, err := fileSizeInBytes(pth)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to get xcarchive size, error: %s", err)
}

xcarchiveInfoMap := map[string]interface{}{
"file_size_bytes": fmt.Sprintf("%f", fileSize),
"app_info": appInfo,
"scheme": scheme,
}

log.Printf("xcarchive infos: %v", appInfo)

uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "ios-xcarchive", "")
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to create xcarchive artifact: %s %w", pth, err)
}

if err := UploadArtifact(uploadURL, pth, ""); err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to upload xcarchive artifact, error: %s", err)
}

buildArtifactMeta := AppDeploymentMetaData{
ArtifactInfo: xcarchiveInfoMap,
NotifyUserGroups: "",
NotifyEmails: "",
IsEnablePublicPage: false,
}

artifactURLs, err := finishArtifact(buildURL, token, artifactID, &buildArtifactMeta, item.IntermediateFileMeta)
if err != nil {
return ArtifactURLs{}, fmt.Errorf("failed to finish xcarchive artifact, error: %s", err)
}
return artifactURLs, nil
return appInfo, scheme, nil
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5ae9364

Please sign in to comment.