Search Unity

Path to the final IPA file

Discussion in 'Unity Build Automation' started by Wolar, Oct 2, 2019.

  1. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    Hello,
    I wanted to use Post-Build Script in the Cloud Build to push IPA file directly to the itunes connect as part of the build. I have created script like this


    xcrun altool --upload-app -f path -u myemail -p myappgeneratedpassword


    what I'm missing here is the path. Is there a way how to get the path of the final IPA file? And if not, is there some other recommended way how to upload the IPA file automatically?

    Thank you
     
  2. ollieblanks

    ollieblanks

    Unity Technologies

    Joined:
    Aug 21, 2017
    Posts:
    460
    Hi @Wolar,
    The path to the generated ipa file is
    /BUILD_PATH/<ORG_ID>.<PROJECT_ID>.<BUILD_TARGET_ID>/.build/last/<BUILD_TARGET_ID>/build.ipa

    The identifiers within the above path can be found either by using the Cloud Build API or by observing the Developer Dashboard URL for the project/Build Targets. Hope that helps!
     
  3. victorw

    victorw

    Joined:
    Sep 14, 2016
    Posts:
    459
    As a side note, I would recommend using Environment Variables for your username and password so that you do not have to check them into source control - currently this is only available via the Build API but it will also be coming to the Developer Dashboard soon.
     
    ibyte likes this.
  4. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    Hello @ollieblanks, thank you, path seems to be correct but the IPA doesn't seems to be there for some reason.

    I can see in the log right before executing my custom script

    12415: Successfully exported and signed the ipa file:
    12416: /BUILD_PATH/dottodotsro.idledottodot.ios-appstore/.build/last/ios-appstore/build.ipa


    Then it runs my script which fails because the file is not there


    12431: Uploading IPA to Appstore Connect...
    12432: 2019-10-04 11:53:55.486 altool[14288:37968] *** Error: Errors uploading '/BUILD_PATH/dottodotsro.idledottodot.ios-appstore/.build/last/ios-appstore/build.ipa': (
    12433: "Error Domain=ITunesSoftwareServiceErrorDomain Code=-19066 \"The path '/BUILD_PATH/dottodotsro.idledottodot.ios-appstore/.build/last/ios-appstore/build.ipa' does not contain a file.\" UserInfo={NSLocalizedDescription=The path '/BUILD_PATH/dottodotsro.idledottodot.ios-appstore/.build/last/ios-appstore/build.ipa' does not contain a file., NSLocalizedFailureReason=Unable to validate your application.}"
    12434: )
    12435: Upload IPA to Appstore Connect failed


    Any idea what is / I did wrong here?

    It's build #20 in case you want to investigate it directly in our cloud build.
     
  5. alan_motionlab

    alan_motionlab

    Joined:
    Nov 27, 2014
    Posts:
    99
    I've been looking for a way to do this for a while - would you mind sharing your post build script @Wolar ?
     
  6. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    Hello @alan_motionlab, it's basically just a bash script with the command I have pasted above. But as I have described in one post earlier, for some reason it's still not working.

    Code (csharp):
    1.  
    2. #!/bin/bash
    3.  
    4. echo "Uploading IPA to Appstore Connect..."
    5.  
    6. username="<put your email here>"
    7. password="<put your app generated password here>"
    8.  
    9. #Path is "/BUILD_PATH/<ORG_ID>.<PROJECT_ID>.<BUILD_TARGET_ID>/.build/last/<BUILD_TARGET_ID>/build.ipa"
    10. path="/BUILD_PATH/dottodotsro.colorme-coloring.final-release-ios/.build/last/final-release-ios/build.ipa"
    11.  
    12. if xcrun altool --upload-app -f $path -u $username -p $password ; then
    13.     echo "Upload IPA to Appstore Connect finished with success"
    14. else
    15.     echo "Upload IPA to Appstore Connect failed"
    16. fi
    17.  
    App generated password can be generated here appleid.apple.com under the Security section. You can also use reference to keychain instead of this but I don't think we can put stuff into Cloud Builds server keychain, that would be useable if you would use your custom CI.

    I intend to replace that hardcoded email and password inside the script by using Environment Variables as hinted by victorw as soon as those are available in the Cloud Build dashboard.

    You can find <ORG_ID>, <PROJECT_ID> and <BUILD_TARGET_ID> in the url of your cloud build config as hinted by ollieblanks which is what I did or that path can also be found in the full log of the build, seach for something like "Successfully exported and signed the ipa file:". Or it should be possible to get it via API which I didn't try.

    Screenshot 2019-10-06 at 15.26.18.png
     
    pland likes this.
  7. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    Hello @ollieblanks, just pinging if it would be possible to check this issue, it would really save us lot of time to automate this but this is still a roadblock for us. Thank you!
     
  8. victorw

    victorw

    Joined:
    Sep 14, 2016
    Posts:
    459
    Hi, sorry for the slow response - there's an environment variable called
    WORKSPACE
    which contains the build path, org_id, and project_id. So you should be able to find the path to the build.ipa by using

    $WORKSPACE/.build/last/<BUILD_TARGET_ID>/build.ipa
     
  9. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    I just want to say thanks to Wolar and victorw as I was able to use the information in this thread and successfully add a build to my Apple developer account application page as part of the build process.

    I used environment variables for the username and password.
     
    Last edited: Oct 16, 2019
  10. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    I can confirm that it works great, I have also changed the script to use environment variables for email, password and build target. Thank you victorw.
     
  11. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    So after my build appeared, I got an approval email to use the build for testflight. When I went to check on it, I had the export regulations questions to answer. It reverted back to in processing and it's been stuck there for more then 12 hours. :(

    What is the best way to update the plist.info file to set the export regulations flag correctly?
     
  12. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    I assume you're using the Xcode manipulation stuff. I've managed to sort that using:

    Code (csharp):
    1.  
    2. string plistPath = path + "/Info.plist";
    3. PlistDocument plist = new PlistDocument();
    4. plist.ReadFromString(File.ReadAllText(plistPath));
    5.        
    6. // Get root
    7. PlistElementDict rootDict = plist.root;
    8. rootDict.SetString( "ITSAppUsesNonExemptEncryption" , "false" );
    9.  
     
  13. Deleted User

    Deleted User

    Guest

    Is the Build Target ID (and Project ID) also available as an environment variable? I am reusing the same script for multiple targets and wouldn't want to hard code this.
     
  14. victorw

    victorw

    Joined:
    Sep 14, 2016
    Posts:
    459
    You can find the build number as
    BUILD_NUMBER
    and the full job name (i.e. <ORG_ID>.<PROJECT_ID>.<BUILD_TARGET_ID>) as
    JOB_NAME
    but as far as I know there's not currently an environment variable that specifically points to the build target id.

    You could probably pull it out using regex on the JOB_NAME, it might break in future if we ever change how that field is configured (and we do have some upcoming work which might result in path changes) but that's probably true of everything in this thread and I'll try to bear this usage in mind when we make those changes.
     
    Deleted User likes this.
  15. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Just to clarify then, with username/password as environment vars and the Workspace stuff metioned above, the script should look like this:


    Code (csharp):
    1.  
    2. #!/bin/bash
    3.  
    4. echo "Uploading IPA to Appstore Connect..."
    5.  
    6. #Path is "/BUILD_PATH/<ORG_ID>.<PROJECT_ID>.<BUILD_TARGET_ID>/.build/last/<BUILD_TARGET_ID>/build.ipa"
    7. path="$WORKSPACE/.build/last/production-ios/build.ipa"
    8.  
    9. if xcrun altool --upload-app -f $path -u $ITUNES_USERNAME -p $ITUNES_PASSWORD ; then
    10.     echo "Upload IPA to Appstore Connect finished with success"
    11. else
    12.     echo "Upload IPA to Appstore Connect failed"
    13. fi
     
    crekri and firegate666 like this.
  16. victorw

    victorw

    Joined:
    Sep 14, 2016
    Posts:
    459
    Oh yeah good point, it's worth mentioning that Environment Variables now has a frontend implementation so you can configure $ITUNES_USERNAME and $ITUNES_PASSWORD in the config page for each build target.

    ... also now that I re-read the OP it occurs to me to suggest that you do all this via Fastlane since that's probably going to be more stable, extensible and reusable. Cloud Build has full Fastlane support and can be used for most Xcode-related tasks - here's the documentation for integrating with the Appstore via Fastlane and here's an example of how to use Fastlane in UCB
     
    ibyte likes this.
  17. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Sorry for so many questions - I'm not that familiar with Fastlane. Does that mean I can use this:

    BuildScripts/ubc_xcode_fastlane.json
    Code (csharp):
    1. {
    2.     "fastfile": "BuildScripts/Fastfile",
    3.     "lanes": {
    4.         "pre_build": "",
    5.         "post_build": "release"
    6.     }
    7. }
    BuildScripts/Fastfile
    Code (csharp):
    1. lane :release do
    2.     upload_to_app_store
    3. end
    seems a little simple?
     
    Last edited: Oct 16, 2019
  18. victorw

    victorw

    Joined:
    Sep 14, 2016
    Posts:
    459
    I'm also not super familiar with Fastlane but yes, I think that approach should work or at least be close to working. You might need to pass it some additional parameters or call it using
    upload_to_app_store()
    though. You will also need to configure your Username and Password as required by Fastlane, which can be achieved by populating the
    FASTLANE_USER
    and
    FASTLANE_PASSWORD
    environment variables. The Fastlane docs also have specific suggestions around best-practices for managing your uploads via an application-specific password.
     
    ibyte likes this.
  19. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Well, I got it working with that above script anyway for now - I'll have a look into the fastlane version if its more stable.
     
  20. Arik_st

    Arik_st

    Joined:
    Oct 29, 2013
    Posts:
    1
    Hi, was able to set up a fastlane like this:

    Code (Fastlane.json):
    1. {
    2.     "fastfile": "Fastlane/fastfile",
    3.     "lanes": {
    4.         "pre_build": "bump_version",
    5.         "post_build": "upload"
    6.     }
    7. }
    8.  
    Code (Fastfile):
    1. lane :bump_version do
    2.     project = 'Unity-iPhone.xcodeproj'
    3.     build_number = number_of_commits
    4.     set_info_plist_value(path: "./Info.plist", key: "CFBundleVersion", value: build_number.to_s)
    5. end
    6.  
    7. lane :upload do
    8.     upload_to_testflight(skip_submission: true, skip_waiting_for_build_processing: true)
    9. end
    Code (ENV VARIABLES):
    1. FASTLANE_USER
    2. FASTLANE_PASSWORD
    3. FASTLANE_ITC_TEAM_ID
    4. FASTLANE_APP_IDENTIFIER
    Right now I am using "number_of_commits" to increment a buildNumber which is not perfect but works at least somehow predictable

    UCB uses BUILDNUMBER env variable but I have no idea how it gets incremented. Sometimes it does, sometime it remains the same for a number of build jobs.

    Also tried using "latest_testflight_build_number" but it's as unpredictable as BUILDNUMBER, probably works somewhat the same behind the scene.

    Does anyone know if it's possible to get a job build number directly from UCB environment?
     
    tonybf likes this.
  21. lloydv

    lloydv

    Joined:
    Sep 15, 2015
    Posts:
    55
    Code (CSharp):
    1. # Unity Cloud Build manifest file location, only available post-build
    2. UCB_MANIFEST=$WORKSPACE/Unity/Assets/__UnityCloud__/Resources/UnityCloudBuildManifest.json.txt
    3.  
    4. # extract the build number using regex
    5. CLOUD_BUILD_NUMBER=$(grep -o '"buildNumber":"[^"]*' $UCB_MANIFEST | grep -o '[^":]*$')
    Path to built ipa is

    Code (CSharp):
    1.  
    2. $2/build.ipa
    3.  
    Took me lots of rummaging around in the dark to figure this out, hopefully saves somebody else some time.
     
    MartinAnd and akashkevich like this.
  22. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    I was successfully using the script mentioned earlier on another project. I am trying to use it on another project but getting this message during the build

    Executing Post-Build Script at scripts/post_build_task.sh
    sh: /BUILD_PATH/ibyte-productions.vivoxtanksample.default-ios/scripts/post_build_task.sh: /bin/bash^M: bad interpreter: No such file or directory

    This an exact copy of the previous build script and the only change is that I am using collaborate as the repo vs gitlab

    Any suggestions?
     
  23. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    is your build config called default-ios on the second project?
     
  24. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    I meant to get back here to update my question. It turns out that line endings when checked into GitLab must be set to unix LF only (as required on the Mac) and when you use Collaborate they are left alone. When I adjusted the line endings of the bash script the issue was resolved.
     
    Boyozu, NGC6543 and ollieblanks like this.
  25. lloydv

    lloydv

    Joined:
    Sep 15, 2015
    Posts:
    55
    For the record, it appears the manifest path is different in Unity 2019.3?, since the above no longer gets the build number correctly (worked with 2018 LTS). I haven't had time to dig into it again to discover the correct path.
     
  26. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
  27. mayeager22

    mayeager22

    Joined:
    Dec 4, 2019
    Posts:
    10
    If the build number is only available post build, are you bumping the version in the IPA after the build? If so, do you mind sharing how you do that?
     
  28. firegate666

    firegate666

    Joined:
    Nov 20, 2015
    Posts:
    19
    You are pretty amazing. Just stumbled upon this thread, copied your shell script, added it to cloud build and it instantly works.

    Thank you su much! That saves a lot of uploading in the future!
     
  29. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Can someone please summarize what files would one need to send the build from Unity Cloud to Testflight?
    Do they need to be in the repository?
    And did someone manage to make it work with Unity 2019.3?
     
  30. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    The only thing you need to send from Cloud Build to Testflight it the IPA file (result of the build), that's it, nothing else.

    There is one thing to note, the IPA needs to be signed by App Store distribution provisioning profile (which means by distribution certificate), this is done automatically during the Cloud Build as you need to provide provisioning profile and certificate anyway (but if you want to test the IPA directly from the Cloud Build you would provide Ad Hoc or development provisioning profile / certificate).
     
  31. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Sorry, I should have been more clear. My idea was to automate this process through a script / set of scripts, which would be helpful for people who don't have access to a Mac pc or laptop.

    What I understood so far from the discussion above, it can be achieved with a Postbuild script in a combination with a fastlane script - and correct me if I'm wrong, I understand that Unity Cloud build uses fastlane, so we can override some of its functionality.
     
  32. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    I'm not familiar with how to setup fastlane to do that (it should be possible) but you can use (of modify) the script we use that I have posted above, this is the current version we use

    You need to provide it with (can be set via the Cloud Build config on the Cloud Build website)
    ITUNES_USERNAME - Basically email
    ITUNES_PASSWORD - App generated password
    TARGET_NAME - Name of the target in the Unity Cloud build (maybe this could be replaced by some env variable inside Cloud Build or extracted from WORKSPACE variable, I was just lazy to do that since this works good enough for us)
    the other env variable(s) like WORKSPACE are set by Cloud Build

    Code (CSharp):
    1. #!/bin/bash
    2. echo "Uploading IPA to Appstore Connect..."
    3. #Path is "/BUILD_PATH/<ORG_ID>.<PROJECT_ID>.<BUILD_TARGET_ID>/.build/last/<BUILD_TARGET_ID>/build.ipa"
    4. path="$WORKSPACE/.build/last/$TARGET_NAME/build.ipa"
    5. if xcrun altool --upload-app -f $path -u $ITUNES_USERNAME -p $ITUNES_PASSWORD ; then
    6.     echo "Upload IPA to Appstore Connect finished with success"
    7. else
    8.     echo "Upload IPA to Appstore Connect failed"
    9. fi
     
  33. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    I see, thanks for explaining. The only thing I'm still not clear about is how to run this bash script?
    Are there some rules for naming and location of the script?
     
  34. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    1) Put that bash script in your Assets\Editor folder (I called it post-build-push-ipa-appstore.bash)

    2) In the iOS cloud config click 'Environment Variables' and add new environment variables for target, username and password (TARGET_NAME, ITUNES_USERNAME and ITUNES_PASSWORD). If you're concerned about using your password you can get a one-off password from Apple that only works on Application Loader. (see https://support.apple.com/en-gb/HT204397)

    3) In the iOS cloud config click 'Advanced Options' and in the Post-Build Script path put "Assets/Editor/post-build-push-ipa-appstore.bash"

    4) Run build

    5) Save time

    6) Fill extra time by doing more work :)
     
    vejab, samhain323, Elermond and 14 others like this.
  35. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Perfect, thanks! Will try it out and report later!
     
  36. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Thanks Wolar and tonemcbride, seems to be working, it's asking me to upload an app icon before I can upload the build ;)
     
    tonemcbride likes this.
  37. Trivium_Dev

    Trivium_Dev

    Joined:
    Aug 1, 2017
    Posts:
    78

    This is honestly amazing. Thanks Wolar!
     
  38. xLeo

    xLeo

    Joined:
    Sep 21, 2010
    Posts:
    194
    Just a quick note about creating this script on a Windows machine: watch out for line endings, it caused our upload to fail (our file was created with CRLF by default).
     
  39. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    One more quick note, the script doesn't have to be in the Assets and/or Editor folder, for example we have "scripts" folder with all of our scripts at the same level as Assets folder and our post build script path is "scripts/script-filename.sh".
     
    tonialatalo likes this.
  40. Npicouet

    Npicouet

    Joined:
    May 17, 2018
    Posts:
    30
    This works fantastically for testflight. Thanks so much.
    Has anyone attempted the same for Google Play with the Developer API?
     
  41. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    I remember that I did try and I gave up as it was not worth my time but I cannot remeber what the problem was. But if anyone implemented it I would be glad to copy the solution :D
     
  42. Npicouet

    Npicouet

    Joined:
    May 17, 2018
    Posts:
    30
    At the very least, does anyone know the file path to the latest android APK after a cloud build?
    I thought it would be similiar to iOS, but that doesn't seem to be the case.

    I changed this to my android workspace, and used "build.apk". Doesn't seem to work.
    "$WORKSPACE/.build/last/$TARGET_NAME/build.apk"

    The only line I can see about the APK in the build logs is this:
    "Exporting player to /BUILD_PATH/curious-media-inc.curiosity-shop.android-apk/Curiosity Shop/temp20200311-6457-mtnka8/Default Android.apk"

    If that is the path, how would we get that temp location?
     
  43. ASI2000

    ASI2000

    Joined:
    Nov 29, 2015
    Posts:
    3
    Hi, my problem:

    6120: Uploading IPA to Appstore Connect...
    6121: /BUILD_PATH/skorb-studio.bridge-tap.test-ios-builds/Assets/Editor/post-build.sh: line 4: /BUILD_PATH/skorb-studio.bridge-tap.test-ios-builds/.build/last/test-ios-builds/build.ipa: Permission denied
    6122: 2020-04-05 17:32:40.434 altool[11902:33268] *** Error: No command was specified. Unable to run altool.
    6123: Upload IPA to Appstore Connect failed

    The path to the ipa corresponds to the Assembly location.
     
    Last edited: Apr 7, 2020
  44. John3D

    John3D

    Joined:
    Mar 7, 2014
    Posts:
    441
    Hi,

    I have this error:

    27808: Executing Post-Build Script at Assets/Editor/post-build-push-ipa-appstore.bash
    27809: sh: /BUILD_PATH/edited.production-ios/Assets/Editor/post-build-push-ipa-appstore.bash: /bin/bash^M: bad interpreter: No such file or directory

    Why is this happening please?

    Thanks!
     
    ScottAdams likes this.
  45. John3D

    John3D

    Joined:
    Mar 7, 2014
    Posts:
    441
    Now I saw this message:

    I used Notepadd++ to change the line endings in the bash file: Edit > EOL Conversion > UNIX Format.
    Cloud build started. Hopefully it will work this time.
     
  46. Connorses

    Connorses

    Joined:
    Jan 28, 2016
    Posts:
    15
    I followed the directions here, got the .bash file to run and got a "Upload IPA to Appstore Connect finished with success", but I don't see my build in Appstore Connect. I'm trying to get it on TestFlight. I used an Ad Hod provisioning profile. Could there be some other issue with the build that causes it to not show up?
     
  47. CengageJermAker

    CengageJermAker

    Joined:
    Nov 29, 2017
    Posts:
    9
    The environment variable UCB_BUILD_NUMBER seems pretty reliable for getting the build number.

    Does anyone know how to find the latest WebGL build? $WORKSPACE/.build/last/<BUILD_TARGET_ID>/???
     
  48. CengageJermAker

    CengageJermAker

    Joined:
    Nov 29, 2017
    Posts:
    9
    Answering my own question here. After a LOT of testing it appears the the post-build task for WebGL happens before the .zip artifact is created. Same for Android builds - the post build task happens before the .apk file is saved. Which is definitely a misrepresentation of POST. :mad:
     
    Last edited: Nov 11, 2020
  49. TheVirtualMunk

    TheVirtualMunk

    Joined:
    Sep 6, 2019
    Posts:
    150
    Same issue - uploaded without any errors, getting the "Upload IPA to Appstore Connect finished with success" in the full log, but no build visible on appstore connect. :(
    Did you manage to fix this?

    EDIT: In the words of Charles Leclerc; "I am stupid...". The build goes to the testflight tab where you need to go through some verification steps before its visible in the "App Store" tab.
     
    Last edited: Jan 13, 2021
  50. S-Saruul-Ulzii

    S-Saruul-Ulzii

    Joined:
    Dec 3, 2012
    Posts:
    1
    I hope your bash is using Windows EOL. Please convert it to Linux EOL.