Preecington / preecington.github.io

My dev blog
0 stars 0 forks source link

iOS TestFlight Deploy With GitHub Actions #2

Open utterances-bot opened 3 years ago

utterances-bot commented 3 years ago

iOS TestFlight Deploy With GitHub Actions

A (not so quick) dive on getting an iOS app deployed to TestFlight using GitHub Actions

https://preece.dev/2020/06/ios-testflight-deploy-with-github-actions/

L4ZZA commented 3 years ago

Hey! Thank you for taking the time to writing this, it's one of the few really helpful articles around. I am having an issues trying to apply this to a xcode project built by Unity. The Generate App Store Connect API Token step is failing with this error code AttributeError: 'str' object has no attribute 'decode' do you have any idea what it could be?

action logs

 Successfully installed cffi-1.14.4 cryptography-3.4.4 pycparser-2.20
WARNING: You are using pip version 20.3.3; however, version 21.0.1 is available.
You should consider upgrading via the '/usr/local/opt/python@3.9/bin/python3.9 -m pip install --upgrade pip' command.
Collecting pyjwt
  Downloading PyJWT-2.0.1-py3-none-any.whl (15 kB)
Installing collected packages: pyjwt
Successfully installed pyjwt-2.0.1
WARNING: You are using pip version 20.3.3; however, version 21.0.1 is available.
You should consider upgrading via the '/usr/local/opt/python@3.9/bin/python3.9 -m pip install --upgrade pip' command.
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'

shell command run by the step

pip3 install cryptography
        pip3 install pyjwt
        exp=$(date -v +20M +%s)
        iss=$(date -v -1M +%s)
        jwt=$(python3 -c "import jwt; print(jwt.encode({'aud':'appstoreconnect-v1','iss':'$ISSUER_ID','exp':$exp,'iat':$iss},'''$AUTH_KEY''',algorithm='ES256', headers={'kid': '$KEY_ID'}).decode('utf-8'))")
        echo "::add-mask::$jwt"
        echo "::set-output name=appStoreToken::$jwt"
Preecington commented 3 years ago

Hey @L4ZZA , thanks for taking the time to comment! This is an issue I ran into a few days ago myself with this build pipeline, and an upgrade to the package has broken it on some macOS build agents. I'm going to upgrade the gist with a few improvements I've made since I wrote this, but to get the JWT token working again modify the pip3 install pyjwt line to pip3 install pyjwt==1.7.1. That should unblock you!

L4ZZA commented 3 years ago

Hey @Preecington thanks for the quick reply, I tried to investigate a bit more about it and found that by removing .decode('utf-8') does that job as apparently jwt.encode(...) already converts it to string. That worked for me without having to force a specific version on pyjwt. I do find interesting tough how you went for building with msbuild rather than xcode. Is that a requirement for flutter?

jrtibbetts commented 2 years ago

Echoing @L4ZZA's comment that removing .decode('utf-8') works on current (as of March 2022) versions of the tools.

I'm stuck at the

    - name: Prime App Store Connect API
      env:
        JWT: ${{ steps.app-store-api-token.outputs.appStoreToken }}
      uses: nick-invision/retry@v1.0.0
      with:
        timeout_minutes: 1
        max_attempts: 30
        command: 'curl --header "Authorization: Bearer $JWT" -s -o /dev/null -w "%{http_code}" --fail https://api.appstoreconnect.apple.com/v1/bundleIds'

step. No matter how many times I try it, I get a 401 error

{
    "errors": [{
        "status": "401",
        "code": "NOT_AUTHORIZED",
        "title": "Authentication credentials are missing or invalid.",
        "detail": "Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens"
    }]

At first, I wasn't sure exactly what format the secrets.APPCONNECT_API_KEY_PRIVATE value needed to be in, because just pasting in the ASCII .p8 as-is didn't work--I had to convert the newlines, so the raw ASCII

-----BEGIN PRIVATE KEY-----
FOO
BAR
BADA
BING
-----END PRIVATE KEY-----

had to become "-----BEGIN PRIVATE KEY-----\nFOO\nBAR\nBADA\nBING\n-----END PRIVATE KEY-----"

With that change, the output of lines 33 & 34 look like a JWT value that I expect.

I've tried using a couple of different App Store Connect API keys, and I get the same 401 every time.

I've also compared your GitHub action to the Apple-Actions/Example-IOS repo. That one skips the JWT and priming steps entirely:

jobs:
  build: # make sure build/ci work properly
    runs-on: macOS-latest
    timeout-minutes: 30
    steps:
    - uses: actions/checkout@v2
    - uses: Apple-Actions/import-codesign-certs@v1
      with:
        p12-file-base64: ${{ secrets.CERTIFICATES_FILE_BASE64 }}
        p12-password: ${{ secrets.CERTIFICATES_PASSWORD }}
    - uses: Apple-Actions/download-provisioning-profiles@v1
      with:
        bundle-id: codes.orj.Example-iOS
        issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
        api-key-id: ${{ secrets.APPSTORE_KEY_ID }}
        api-private-key: ${{ secrets.APPSTORE_PRIVATE_KEY }}
    - name: "#️⃣ Generate Build Number"
      id: buildnumber
      uses: einaregilsson/build-number@v2
      with:
        token: ${{ secrets.github_token }}
    - run: ./Build
    - uses: Apple-Actions/upload-testflight-build@master
      with:
        app-path: .build/Artifacts/Example-iOS.ipa/Example-iOS.ipa
        issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
        api-key-id: ${{ secrets.APPSTORE_KEY_ID }}
        api-private-key: ${{ secrets.APPSTORE_PRIVATE_KEY }}

but I don't get anywhere with that one, either--it tells me that my APPSTORE_PRIVATE_KEY secret (= your script's APPCONNECT_API_KEY_PRIVATE) has a malformed end line.