diff --git a/.github/workflows/build-submit-ios.yml b/.github/workflows/build-submit-ios.yml index 73430687a0..9b16a2d12c 100644 --- a/.github/workflows/build-submit-ios.yml +++ b/.github/workflows/build-submit-ios.yml @@ -24,11 +24,6 @@ on: type: boolean description: Assign the build to the "QA Team" TestFlight group after submitting default: false - releaseNotes: - type: string - description: Notes to set as the TestFlight "What to Test" changelog - required: false - default: '' outputs: package-version: description: Version from package.json @@ -216,7 +211,6 @@ jobs: # eas submit only uploads to App Store Connect; it can't assign a build to a # TestFlight group. fastlane's distribute_only mode skips the upload and assigns the # already-submitted build to the group, polling until Apple finishes processing it. - # The "What to Test" changelog is supplied by the caller (e.g. the nightly workflow). - name: ๐Ÿงช Assign build to TestFlight group if: ${{ inputs.assignTestFlightGroup }} env: @@ -225,26 +219,30 @@ jobs: ASC_KEY_P8_BASE64: ${{ secrets.ASC_KEY_P8_BASE64 }} APP_VERSION: ${{ steps.get-build-info.outputs.PACKAGE_VERSION }} BUILD_NUMBER: ${{ steps.ipa-build-number.outputs.build-number }} - RELEASE_NOTES: ${{ inputs.releaseNotes }} run: | # Ensure the API key material is removed even if fastlane exits non-zero # (the step runs under `bash -e`, which would otherwise abort before cleanup). - trap 'rm -f asc_api_key.p8 asc_api_key.json' EXIT - echo "$ASC_KEY_P8_BASE64" | base64 --decode > asc_api_key.p8 - printf '{"key_id":"%s","issuer_id":"%s","key_filepath":"%s","in_house":false}' \ - "$ASC_KEY_ID" "$ASC_ISSUER_ID" "$PWD/asc_api_key.p8" > asc_api_key.json - changelog_args=() - if [ -n "$RELEASE_NOTES" ]; then - changelog_args=(changelog:"$RELEASE_NOTES") - fi + trap 'rm -f asc_api_key.json' EXIT + # fastlane's Token.from_json_file expects the .p8 contents inline under "key" + # (PEM with embedded newlines), not a path. jq handles the newline escaping. + key_content="$(echo "$ASC_KEY_P8_BASE64" | base64 --decode)" + jq -n \ + --arg key_id "$ASC_KEY_ID" \ + --arg issuer_id "$ASC_ISSUER_ID" \ + --arg key "$key_content" \ + '{key_id: $key_id, issuer_id: $issuer_id, key: $key, in_house: false}' \ + > asc_api_key.json + # app_platform is required in non-interactive mode: distribute_only otherwise + # calls fetch_app_platform, which prompts for input and crashes without a TTY. fastlane run upload_to_testflight \ api_key_path:"$PWD/asc_api_key.json" \ distribute_only:true \ + app_platform:"ios" \ app_identifier:"xyz.blueskyweb.app" \ app_version:"$APP_VERSION" \ build_number:"$BUILD_NUMBER" \ - "${changelog_args[@]}" \ - groups:"QA Team" + groups:"QA Team" \ + notify_external_testers:true - name: ๐Ÿ”” Notify Slack of Production Build if: ${{ inputs.profile == 'production' }} diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 9fe0ce8bfc..f3ec4ac3d1 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -62,7 +62,7 @@ jobs: if [ -z "$notes" ]; then notes="Nightly build โ€” no new commits since the last nightly." fi - # Cap the whole changelog (TestFlight "What to Test" is limited to 4000 characters). + # Cap the whole changelog to keep the Slack message a reasonable size. # head -c caps the combined stream; cut -c would only cap each line independently. notes=$(printf '%s' "$notes" | head -c 3900) { @@ -78,12 +78,16 @@ jobs: with: profile: testflight assignTestFlightGroup: true - releaseNotes: ${{ needs.prepare.outputs.notes }} secrets: inherit android: name: Nightly Android Build needs: [prepare] + # build-submit-android.yml contains an attachToRelease job that requests contents: write. + # That job is skipped for nightly (it needs a production tag build), but GitHub statically + # validates the reusable-workflow permission ceiling, so the caller must grant it here. + permissions: + contents: write uses: ./.github/workflows/build-submit-android.yml with: profile: testflight-android