Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Fastlane for IOS and Android

Discussion in 'Unity Build Automation' started by c_andrews, Dec 9, 2020.

  1. c_andrews

    c_andrews

    Joined:
    Jan 26, 2015
    Posts:
    106
    Hi, So I've hit a couple of walls, I was hoping implementing Fastlane was going to be a simple task but I'm having some issues.

    For IOS I am not able to Authenticate the 2FA with my iCloud credentials. It seems the only way to be able to achieve this is with an updated version of Fastlane so that we can use api_key_path or api_key in the parameters. Is there any news or information about getting the latest version of Fastlane installed?

    For Android it doesn't seem like I can setup Fastlane in the Cloud Build config. Is it supported for Android on Cloud Build or am I doing something wrong to not see it?

    Any help would be really appreciated.
    Thanks in advance.
     
  2. tarmo-jussila

    tarmo-jussila

    Joined:
    Jun 4, 2015
    Posts:
    42
    Fastlane works without 2FA if BOTH apple_id and skip_waiting_for_build_processing are sent as parameters to upload_to_testflight action in the Fastfile. As far as I know the API approach is not yet supported by the Fastlane version used in the Unity Cloud Build currently.

    For Android, it indeed seems that the custom Fastlane configuration option is missing. I have been looking for that as well. I think a custom post process logic is required to make it work. I hope Unity would add support for custom Fastlane setup for Android as well, so I could use Fastlane/Supply to deliver builds directly to Google Play.
     
  3. c_andrews

    c_andrews

    Joined:
    Jan 26, 2015
    Posts:
    106
    I've been using Fastlane to deliver my Android App to Google play using supply:

    Code (CSharp):
    1. PACKAGE_NAME="com.my.package.name"
    2. BUILD_TARGET=$(jq -r 'keys[0]' < build.json)
    3. BUILD_PLATFORM=$(jq -r ".[\"${BUILD_TARGET}\"].platform" < build.json)
    4.  
    5. fastlane supply --aab "${WORKSPACE}/.build/last/${BUILD_TARGET}/Android.aab" --track internal --json_key "UCB/ucb_android_googleplay_api_key.json" --package_name "$PACKAGE_NAME"
    I haven't had a problem with it so far, though I haven't updated a build recently so i'm hoping Unity haven't changed it.
     
    CQIAutobuild and tarmo-jussila like this.
  4. tarmo-jussila

    tarmo-jussila

    Joined:
    Jun 4, 2015
    Posts:
    42
    Thank you. I tried this, but I'm getting:
    Code (CSharp):
    1. invalid option: --aab
    ...response from the Supply command. JSON validation works, though, so perhaps it's an issue with Google API or I'm missing some relevant permission.
     
  5. c_andrews

    c_andrews

    Joined:
    Jan 26, 2015
    Posts:
    106
    Interesting, so i'm assuming its not fussing about Fastlane but maybe the version that is being used by Cloud build. It might be worth running "fastlane version" in your shell script and take a look at the Fastlane Docs to see if something has changed.

    Are you creating an APK instead of the AAB?
     
  6. tarmo-jussila

    tarmo-jussila

    Joined:
    Jun 4, 2015
    Posts:
    42
    Actually, I figured this out. The problem was with the Fastlane Supply AAB path parameter. I didn't realize at first that the "Android.aab" was actually the supposed to be the unique name of the build target. Mine was not named "Android" so naturally the submission failed.

    Below is my adjusted script, which is a bit more advanced so that all the parameters (such as JSON_KEY path, and RELEASE_TRACK) can be setup in the beginning of the script. This also removes the requirement to manually add the BUILD_NAME in case this same script is used in multiple pipelines (which is our use case).

    Code (CSharp):
    1. PACKAGE_NAME="com.package.name"
    2. JSON_KEY="json-key-path.json"
    3. RELEASE_TRACK="internal"
    4. BUILD_TARGET=$(jq -r 'keys[0]' < build.json)
    5. BUILD_NAME=$(jq -r ".[\"${BUILD_TARGET}\"].executablename" < build.json)
    6.  
    7. fastlane run supply package_name:"$PACKAGE_NAME" track:"$RELEASE_TRACK" json_key:"$JSON_KEY" aab:"${WORKSPACE}/.build/last/${BUILD_TARGET}/${BUILD_NAME}.aab"
    This is working quite perfectly :cool: Thank you for your contribution @c_andrews!
     
    CQIAutobuild likes this.
  7. c_andrews

    c_andrews

    Joined:
    Jan 26, 2015
    Posts:
    106
    No problem, glad its working for you and thanks for the modification
     
  8. L4ZZAR8

    L4ZZAR8

    Joined:
    Jan 18, 2021
    Posts:
    22
    Where do you guys get this JSON key from?
    Is it this?
    upload_2022-5-18_14-22-59.png
     
  9. c_andrews

    c_andrews

    Joined:
    Jan 26, 2015
    Posts:
    106
    ooxcit likes this.
  10. L4ZZAR8

    L4ZZAR8

    Joined:
    Jan 18, 2021
    Posts:
    22
    Totally! I've found it now thanks!

    What I have not found yet is a way to do the same with my iOS target!.. Was anyone able to succeed with this?
     
  11. c_andrews

    c_andrews

    Joined:
    Jan 26, 2015
    Posts:
    106
    The IOS target is a lot easier. The main thing is creating an application Access Code on your Apple ID which bypasses the 2 Factor Authentication.

    More info can be found in the FastLane docs: https://docs.fastlane.tools/getting-started/ios/authentication/

    However I wasn't able to use FastLane to upload the IPA to the App Store. This shell script might help:


    "ucb_ios_post_build.sh"
    Code (CSharp):
    1. #!/bin/sh -u
    2.  
    3. # Properties for Cloud Build
    4. # WORKSPACE=""
    5. # BUILD_TARGET="ios-app-store" - UCB Config name
    6.  
    7. # Inputs
    8. __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    9.  
    10. BUILD_TARGET=$(jq -r 'keys[0]' < build.json)
    11. BUILD_PLATFORM=$(jq -r ".[\"${BUILD_TARGET}\"].platform" < build.json)
    12.  
    13. # set the path based on the first argument
    14. path="${WORKSPACE}/.build/last/${BUILD_TARGET}/extra_data/addrs/ServerData/$BUILD_PLATFORM"
    15.  
    16. # env
    17.  
    18. echo "\n"
    19. echo "----------------------------------------------------------"
    20. echo "UCB IOS Post Build"
    21. echo "----------------------------------------------------------"
    22. echo "- Workspace: ${WORKSPACE}"
    23. echo "- Build Platform: ${BUILD_PLATFORM}"
    24. echo "- Build Target: ${BUILD_TARGET}"
    25. echo "\n"
    26.  
    27. # App Store
    28.  
    29. # $BUILD_TYPE
    30. # $ITUNES_USERNAME
    31. # $ITUNES_PASSWORD
    32.  
    33. echo "Pushing IPA to App Store"
    34.  
    35. # upload the file to s3
    36. sh "${__dir}"/ucb_ios_post_build_push_to_store.sh "$WORKSPACE" "$BUILD_TARGET" "$ITUNES_USERNAME" "$ITUNES_PASSWORD"
    37.  
    38. echo "\n"

    "ucb_ios_post_build_push_to_store.sh"
    Code (CSharp):
    1. #!/bin/bash
    2.  
    3. # $BUILD_TYPE
    4. # $ITUNES_USERNAME
    5. # $ITUNES_PASSWORD
    6.  
    7. # Inputs
    8. workspace="$1"
    9. buildtarget="$2"
    10. itunesusername="$3"
    11. itunespassword="$4"
    12. echo "Uploading IPA to Appstore Connect..."
    13. path="$workspace/.build/last/$buildtarget/build.ipa"
    14. if xcrun altool --upload-app -f $path -t ios -u $itunesusername -p $itunespassword ; then
    15.     echo "Upload IPA to Appstore Connect finished with success"
    16. else
    17.     echo "Upload IPA to Appstore Connect failed"
    18. fi

    In cloud build the Post Build Script is set to "ucb_ios_post_build.sh"
    Then I setup two Environment variables "ITUNES_USERNAME" and "ITUNES_PASSWORD"

    Hopefully that helps. Sorry im a bit stacked atm but let me know if any of that makes sense.
     
    L4ZZAR8 likes this.
  12. L4ZZAR8

    L4ZZAR8

    Joined:
    Jan 18, 2021
    Posts:
    22
    Thank you for your input. I had indeed managed to upload it to TestFlight using xcrun altool --upload-app [see below], but I was really trying to figure out a way to do it with fastlane.. since it is already installed and that is what UCB uses to build the ipa anyway.
    I'm baffled though that this has become a week-long tasks.. while it should just be a check box in the build configurations...

    I have also reported the issue to fastlane directly because the authentication is failing even after following their docs/tutorial..

    this is really a lot harder than it should be.. I wish more companies started to think about developers' quality of life..

    Some useful links:
    https://forum.unity.com/threads/publishing-to-appstore-without-mac-and-ios.1298004/
    https://forum.unity.com/threads/path-to-the-final-ipa-file.754331/#post-5528596

    My alt tool version:
    Code (CSharp):
    1. #!/bin/bash
    2.  
    3. #Path is "/BUILD_PATH/<ORG_ID>.<PROJECT_ID>.<BUILD_TARGET_ID>/.build/last/<BUILD_TARGET_ID>/build.ipa"
    4. build_folder_path="$WORKSPACE/.build/last/$TARGET_NAME"
    5. path="$build_folder_path/build.ipa"
    6. echo "###############################################"
    7. echo "Uploading IPA to Appstore Connect..."
    8. echo "-----------------------------------------------"
    9. env
    10. echo "-----------------------------------------------"
    11. pwd
    12. echo "-----------------------------------------------"
    13. brew install jq
    14. echo "-----------------------------------------------"
    15.  
    16. BUILD_TARGET=$(jq -r 'keys[0]' < build.json)
    17. BUILD_NAME=$(jq -r ".[\"${BUILD_TARGET}\"].executablename" < build.json)
    18. BUNDLE_ID=$(jq -r ".[\"${BUILD_TARGET}\"].bundleid" < build.json)
    19.  
    20. if [[ -z "${BUNDLE_ID}" ]]; then
    21.     # bundleId="your.hardcoded.bundleid"
    22.     echo "======== Using default value for bundleId - ${bundleId}"
    23. else
    24.     bundleId="$BUNDLE_ID"
    25.     echo "======== bundleId set to ${bundleId}"
    26. fi
    27.  
    28. if [[ -z "${APPSTORE_PUSH_TYPE}" ]]; then
    29.     pushType="ios"
    30.     echo "======== Using default value for pushType - ${pushType}"
    31. else
    32.     pushType="$APPSTORE_PUSH_TYPE"
    33.     echo "======== pushType set to ${pushType}"
    34. fi
    35.  
    36. # https://stackoverflow.com/a/31921249/6120464
    37.  
    38. # CFBundleShortVersionString gives you the version of your app.
    39. # It's typically incremented each time you publish your app to the App Store.
    40. # This is the version that is visible on the "Version" section for the App Store page of your application.
    41. if ! [[ -z "${BUNDLE_VERSION}" ]]; then
    42.     echo "-----------------------------------------------"
    43.     bundleShortVersionString="$BUNDLE_VERSION"
    44.     echo "======== bundleShortVersionString set to ${bundleShortVersionString}"
    45. # else
    46. #     echo "======== Using default value for bundleShortVersionString - ${bundleShortVersionString}"
    47. fi
    48.  
    49. # CFBundleVersion gives you the build number which is used for development and testing, namely "technical" purposes.
    50. # The end user is rarely interested in the build number but during the development you may need to know what's being developed
    51. # and fixed on each build. This is typically incremented on each iteration of internal release. And you can use continuous
    52. # integration tools like Jenkins to auto-increment the build number on each build.
    53. if ! [[ -z "${UCB_BUILD_NUMBER}" ]]; then
    54.     bundleVersion="$UCB_BUILD_NUMBER"
    55.     echo "======== bundleVersion set to ${UCB_BUILD_NUMBER}"
    56. # else
    57. #     echo "======== Using default value for bundleVersion - ${bundleVersion}"
    58. fi
    59.  
    60. echo "-----------------------------------------------"
    61.  
    62. search_depth=2
    63. search_results=($(find . -maxdepth $search_depth -type f -name Info.plist))
    64. plist_filepath=${search_results[0]}
    65. find_error_message="File Doesn't Exist, Will Create"
    66.  
    67. # regex operator https://linuxize.com/post/how-to-check-if-string-contains-substring-in-bash/#using-regex-operator
    68. if [ $plist_filepath == "" ] ||  [[ "$plist_filepath" =~ .*"$find_error_message".* ]]; then
    69.     echo "Error PList no found!\n $search_results"
    70.     exit 1
    71. else
    72.     echo "Found PList! $plist_filepath"
    73. fi
    74.  
    75. plist_build_number=$(/usr/libexec/PlistBuddy -c "print :CFBundleVersion" "$plist_filepath")
    76. plist_version=$(/usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" "$plist_filepath")
    77.  
    78. echo "-----------------------------------------------"
    79.  
    80. if [ $plist_build_number -lt 1 ]; then
    81.     echo "Error! plist_build_number [$plist_build_number] should match bundleVersion [$bundleVersion]"
    82. else
    83.     echo "plist_build_number [$plist_build_number] retrieved correctly."
    84.     bundleVersion=$plist_build_number
    85. fi
    86.  
    87. if [[ "$plist_version" == "" ]]; then
    88.     echo "Error! plist_version [$plist_version] should match bundleShortVersionString [$plist_version]"
    89. else
    90.     echo "plist_version [$plist_version] retrieved correctly."
    91.     bundleShortVersionString=$plist_version
    92. fi
    93.  
    94. echo "-----------------------------------------------"
    95. echo " Info.plist log "
    96. echo "-----------------------------------------------"
    97. cat $plist_filepath
    98. echo "-----------------------------------------------"
    99.  
    100. #  https://keith.github.io/xcode-man-pages/altool.1.html
    101.  
    102. exit_code=0
    103. if xcrun altool --upload-package $path \
    104.     --type $pushType \
    105.     --apple-id $APPLE_ID \
    106.     --bundle-version $bundleVersion \
    107.     --bundle-short-version-string $bundleShortVersionString \
    108.     --bundle-id $bundleId \
    109.     -u $APPLE_DEVELOPMENT_USERNAME \
    110.     -p $APP_SPECIFIC_PASSWORD ; then
    111.     echo "======== Upload IPA to Appstore Connect finished with success"
    112.     # end without error
    113.     exit_code=0
    114. else
    115.     echo "======== Upload IPA to Appstore Connect failed"
    116.     echo "======== Current Folder Content"
    117.     ls -a .
    118.     # end with error
    119.     exit_code=1
    120. fi
    121.  
    122. echo "###############################################"
    123. exit $exit_code
     
  13. Swah

    Swah

    Joined:
    May 13, 2015
    Posts:
    80
    @L4ZZAR8 were you able to figure out how to upload using fastlane? We're also able to use altool, but I think the benefits of fastlane would be that we can change additional things like release / test notes.
     
  14. L4ZZAR8

    L4ZZAR8

    Joined:
    Jan 18, 2021
    Posts:
    22
    Nope.. fastlane did not work well for me locally on my macbook so I could not figure out how to do it with the time I had been given..
     
  15. Swah

    Swah

    Joined:
    May 13, 2015
    Posts:
    80
    Ah that's too bad - thanks for answering in any case. If we figure out how to upload, or update the release / test notes I'll post here.
     
    L4ZZAR8 likes this.
  16. Swah

    Swah

    Joined:
    May 13, 2015
    Posts:
    80
    Just a quick note that we were able to make this work using the following post build script. It allows us to add information to testflight release notes, which is super useful when building with multiple configs.We're creating the json file live as we didn't want to check that in our source code, so the API key is an environment variable.


    FILE="<key_id>.json"
    JSON_STRING='{"key_id":"<key_id>", "issuer_id":"<issuer_id>", "key":"'$IOS_API_KEY'"}'

    echo "$JSON_STRING" > $FILE

    BUILD_ID="UCB-${UCB_TARGET_NAME}-${UCB_BUILD_NUMBER}"
    echo "POST BUILD IOS BUILD_ID ${BUILD_ID}"

    fastlane pilot upload --changelog "${BUILD_ID}" --apple_id <apple_id> --ipa $UNITY_PLAYER_PATH --api_key_path $FILE


    Everything in <> should be replaced with the appropriate IDs
     
    aukilabs-oskar likes this.