How to upload .ipa files to external services with XCode Cloud?

I'm setting up my XCode Cloud workflows based on an existing CICD pipeline. One of the things I'd really like the workflow to do is upload an IPA file to BrowserStack, which is the tool we use for our testing. I have a curl command which will do that:

curl -u "<username>:<api key>" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@/path/to/app/file/Application-debug.ipa"

So I added this to the ci_post_xcodebuild script:

if [[ $CI_XCODEBUILD_ACTION = "archive" ]];
then
    curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@$CI_ARCHIVE_PATH"
    curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@$CI_ARCHIVE_PATH"
fi

But I got an "incorrect extension" error. Once I echoed the $CI_ARCHIVE_PATH, it was obvious why - it was leading to a file called build.xcarchive.

Is there any way to get access to the IPA file? There's a different curl command that will upload an IPA file from a URL, so I could try getting the URL for the build from App Store Connect? It has to be a public URL, though, so I'm not sure BrowserStack would be able to access our builds.

Accepted Reply

I got it working - turned out I needed to use one of the signed app paths, in my case CI_DEVELOPMENT_SIGNED_APP_PATH. The IPA is located within that directory, named <name of app>.ipa. Here's the updated script:

if [[ $CI_XCODEBUILD_ACTION = "archive" ]];
then
    ipaFileName="<app name>Build${CI_BUILD_NUMBER}.ipa"
    if [[ $CI_WORKFLOW = "ArchiveAndDistribute" ]];
    then
        cd $CI_DEVELOPMENT_SIGNED_APP_PATH
        # add build number to file name for identification purposes
        mv <app name>.ipa $ipaFileName
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@$ipaFileName"
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@$ipaFileName"
    
    elif [[ $CI_WORKFLOW = "Release build" ]];
    then
        cd $CI_APP_STORE_SIGNED_APP_PATH
        mv MyAmfam.ipa $ipaFileName
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@$ipaFileName"
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@$ipaFileName"
    fi
fi

Replies

I got it working - turned out I needed to use one of the signed app paths, in my case CI_DEVELOPMENT_SIGNED_APP_PATH. The IPA is located within that directory, named <name of app>.ipa. Here's the updated script:

if [[ $CI_XCODEBUILD_ACTION = "archive" ]];
then
    ipaFileName="<app name>Build${CI_BUILD_NUMBER}.ipa"
    if [[ $CI_WORKFLOW = "ArchiveAndDistribute" ]];
    then
        cd $CI_DEVELOPMENT_SIGNED_APP_PATH
        # add build number to file name for identification purposes
        mv <app name>.ipa $ipaFileName
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@$ipaFileName"
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@$ipaFileName"
    
    elif [[ $CI_WORKFLOW = "Release build" ]];
    then
        cd $CI_APP_STORE_SIGNED_APP_PATH
        mv MyAmfam.ipa $ipaFileName
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@$ipaFileName"
        curl -u "$BROWSERSTACK_USERID:$BROWSERSTACK_APIKEY" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@$ipaFileName"
    fi
fi