From 61ef4c4f9fb0a07e76b75b074149e0655541a1a0 Mon Sep 17 00:00:00 2001 From: Ryunosuke Muramatsu Date: Thu, 9 May 2024 17:47:27 +0900 Subject: [PATCH] ci: Add iOS app deployment workflows --- .github/actions/deploy_ios_app/action.yml | 100 ++++++++++++++++++ .github/actions/upload_ios_app/action.yml | 60 ----------- .../workflows/deploy-ios-production-app.yaml | 37 +++++++ .github/workflows/deploy-ios-staging-app.yaml | 37 +++++++ 4 files changed, 174 insertions(+), 60 deletions(-) create mode 100644 .github/actions/deploy_ios_app/action.yml delete mode 100644 .github/actions/upload_ios_app/action.yml create mode 100644 .github/workflows/deploy-ios-production-app.yaml create mode 100644 .github/workflows/deploy-ios-staging-app.yaml diff --git a/.github/actions/deploy_ios_app/action.yml b/.github/actions/deploy_ios_app/action.yml new file mode 100644 index 00000000..40023d82 --- /dev/null +++ b/.github/actions/deploy_ios_app/action.yml @@ -0,0 +1,100 @@ +name: Deploy iOS App +description: "Deploy iOS App" +inputs: + working-directory: + description: "working-directory. example: ./packages/flutter_app" + required: false + default: "./" + flavor: + description: "Flavor name" + required: true + asc-key-id: + description: "App Store Connect Key ID" + required: true + asc-issuer-id: + description: "App Store Connect Issuer ID" + required: true + asc-key-base64: + description: "App Store Connect Key Base64" + required: true + certificates-p12-base64: + description: "Certificates p12 file base64" + required: true + certificates-p12-password: + description: "Certificates p12 file password" + required: true +runs: + using: "composite" + steps: + # Import developer certificates. + # NOTE: If `--no-codesign` is specified in flutter build, to correctly include Entitlement. + # Signing must be done at archive time, which requires importing the developer certificate into the keychain. + # because certificates registered in Secrets are automatically renewed, + # `CERTIFICATES_P12` and `CERTIFICATES_P12_PASSWORD` in Secrets need to be updated annually. + # Expect improvements on the Flutter side. + - name: Import Code Signing Certificate + uses: apple-actions/import-codesign-certs@v2 + with: + p12-file-base64: ${{ inputs.certificates-p12-base64 }} + p12-password: ${{ inputs.certificates-p12-password }} + + - name: Decode App Store Connect API Key + run: | + mkdir ./private_keys + echo "${{ inputs.asc-key-base64 }}" | base64 --decode > ./private_keys/AuthKey_${{ inputs.asc-key-id }}.p8 + echo "API_KEY_PATH=$(pwd)/private_keys/AuthKey_${{ inputs.asc-key-id }}.p8" >> $GITHUB_ENV + shell: bash + working-directory: ${{ inputs.working-directory }} + + - name: Build iOS by Flutter + # Specify `--no-codesign` as signing at this stage will result in an error. + run: | + flutter build ios --release --dart-define-from-file=dart_defines/${{ inputs.flavor }}.json --no-codesign + shell: bash + working-directory: ${{ inputs.working-directory }} + + - name: Create Xcode-Archive + run: | + xcodebuild archive \ + -workspace ./ios/Runner.xcworkspace \ + -scheme Runner \ + -configuration Release \ + -archivePath build/ios/Runner.xcarchive \ + -allowProvisioningUpdates \ + -authenticationKeyIssuerID ${{ inputs.asc-issuer-id }} \ + -authenticationKeyID ${{ inputs.asc-key-id }} \ + -authenticationKeyPath ${{ env.API_KEY_PATH }} + shell: bash + working-directory: ${{ inputs.working-directory }} + + - name: Export IPA + run: | + xcodebuild -exportArchive \ + -archivePath ./build/ios/Runner.xcarchive \ + -exportPath ./build/ios/ipa \ + -exportOptionsPlist ./ios/${{ inputs.flavor }}/ExportOptions.plist \ + -allowProvisioningUpdates \ + -authenticationKeyIssuerID ${{ inputs.asc-issuer-id }} \ + -authenticationKeyID ${{ inputs.asc-key-id }} \ + -authenticationKeyPath ${{ env.API_KEY_PATH }} + shell: bash + working-directory: ${{ inputs.working-directory }} + + - name: Set IPA file path + run: | + echo "IPA_PATH=$(find build/ios/ipa -type f -name '*.ipa')" >> "$GITHUB_ENV" + shell: bash + working-directory: ${{ inputs.working-directory }} + + - name: Upload IPA file to App Store Connect + run: | + xcrun altool --upload-app -t ios -f "${IPA_PATH}" --apiKey ${{ inputs.asc-key-id }} --apiIssuer ${{ inputs.asc-issuer-id }} + shell: bash + working-directory: ${{ inputs.working-directory }} + + - name: Remove App Store Connect API Key + if: ${{ always() }} + run: > + rm ./private_keys/AuthKey_${{ inputs.asc-key-id }}.p8 + shell: bash + working-directory: ${{ inputs.working-directory }} \ No newline at end of file diff --git a/.github/actions/upload_ios_app/action.yml b/.github/actions/upload_ios_app/action.yml deleted file mode 100644 index 3b960a60..00000000 --- a/.github/actions/upload_ios_app/action.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Upload Flutter iOS App -description: "Upload Flutter iOS App" -inputs: - working_directory: - description: "working-directory. example: packages/flutter_app" - required: false - default: "./" - flavor: - description: "Flavor name" - required: true - bundle_name: - description: "CFBundleName" - required: true - profile_name: - description: "Provisioning Profile file name" - required: true - build_number: - description: "Build number" - required: true - provisioning_profile: - description: "" - required: true - certificate_p12: - description: "" - required: true - certificate_password: - description: "" - required: true - apple_id: - description: "" - required: true - app_specific_password: - description: "" - required: true -runs: - using: "composite" - steps: - - name: Import Provisioning Profile - run: | - mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles - echo -n ${{ inputs.provisioning_profile }} | base64 -d > ~/Library/MobileDevice/Provisioning\ Profiles/${{ inputs.profile_name }}.mobileprovision - shell: bash - - - name: Import Code-Signing Certificates - uses: apple-actions/import-codesign-certs@v1 - with: - keychain: signing_temp - create-keychain: true - p12-file-base64: ${{ inputs.certificate_p12 }} - p12-password: ${{ inputs.certificate_password }} - - - name: Create ipa file - run: flutter build ipa --dart-define-from-file=dart_defines/${{ inputs.flavor }}.json --export-options-plist=ios/${{ inputs.flavor }}/ExportOptions.plist --build-number ${{ inputs.build_number }} - shell: bash - working-directory: ${{ inputs.working_directory }} - - - name: Upload to AppStoreConnect - run: xcrun altool --upload-app --file "./build/ios/ipa/${{ inputs.bundle_name }}.ipa" --type ios --username ${{ inputs.apple_id }} --password ${{ inputs.app_specific_password}} - shell: bash - working-directory: ${{ inputs.working_directory }} diff --git a/.github/workflows/deploy-ios-production-app.yaml b/.github/workflows/deploy-ios-production-app.yaml new file mode 100644 index 00000000..395c56a4 --- /dev/null +++ b/.github/workflows/deploy-ios-production-app.yaml @@ -0,0 +1,37 @@ +name: Deploy iOS Production App + +on: + pull_request: + types: [closed] + branches: + - main + workflow_dispatch: + +jobs: + deploy: + # macos-latest Specify macos-13 because an error occurs during archiving if it is macos-latest. + runs-on: macos-13 + timeout-minutes: 40 + if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && contains(github.head_ref, 'release/')) + env: + ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} + ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }} + ASC_KEY_BASE64: ${{ secrets.ASC_KEY_BASE64 }} + CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }} + CERTIFICATES_P12_PASSWORD: ${{ secrets.CERTIFICATES_P12_PASSWORD }} + steps: + - uses: actions/checkout@v4 + + - name: Setup Flutter + uses: ./.github/actions/setup_flutter + + - name: Deploy iOS app + uses: ./.github/actions/deploy_ios_app + with: + working-directory: ./packages/flutter_app_template + flavor: prod + asc-key-id: ${{ env.ASC_KEY_ID }} + asc-issuer-id: ${{ env.ASC_ISSUER_ID }} + asc-key-base64: ${{ env.ASC_KEY_BASE64 }} + certificates-p12-base64: ${{ env.CERTIFICATES_P12 }} + certificates-p12-password: ${{ env.CERTIFICATES_P12_PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/deploy-ios-staging-app.yaml b/.github/workflows/deploy-ios-staging-app.yaml new file mode 100644 index 00000000..3f25986e --- /dev/null +++ b/.github/workflows/deploy-ios-staging-app.yaml @@ -0,0 +1,37 @@ +name: Deploy iOS Staging app + +on: + pull_request: + types: [closed] + branches: + - main + workflow_dispatch: + +jobs: + deploy: + # macos-latest Specify macos-13 because an error occurs during archiving if it is macos-latest. + runs-on: macos-13 + timeout-minutes: 40 + if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && contains(github.head_ref, 'release/')) + env: + ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} + ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }} + ASC_KEY_BASE64: ${{ secrets.ASC_KEY_BASE64 }} + CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }} + CERTIFICATES_P12_PASSWORD: ${{ secrets.CERTIFICATES_P12_PASSWORD }} + steps: + - uses: actions/checkout@v4 + + - name: Setup Flutter + uses: ./.github/actions/setup_flutter + + - name: Deploy iOS app + uses: ./.github/actions/deploy_ios_app + with: + working-directory: ./packages/flutter_app_template + flavor: stg + asc-key-id: ${{ env.ASC_KEY_ID }} + asc-issuer-id: ${{ env.ASC_ISSUER_ID }} + asc-key-base64: ${{ env.ASC_KEY_BASE64 }} + certificates-p12-base64: ${{ env.CERTIFICATES_P12 }} + certificates-p12-password: ${{ env.CERTIFICATES_P12_PASSWORD }}