Skip to content

Instantly share code, notes, and snippets.

@CS6
Last active October 29, 2022 01:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save CS6/320ece2c01f9653b2225db28b7c8ca9f to your computer and use it in GitHub Desktop.
Save CS6/320ece2c01f9653b2225db28b7c8ca9f to your computer and use it in GitHub Desktop.
GitHub Actions 懶人部署-Android 打包入門.md

GitHub Actions (如果不放簽署過的AAB/APK記得移除部分區塊)

https://ithelp.ithome.com.tw/upload/images/20201004/20104220TTX3N7PW55.png

GitHub Actions ?

基本免費!! 還幫你準備好了多個平台 Windows & macOS 和 Linux

https://ithelp.ithome.com.tw/upload/images/20201004/20104220vrvgdO4eWR.png

https://ithelp.ithome.com.tw/upload/images/20201004/20104220szsM0XIZ7O.png GitHub Actions 的 Windows和macOS 運行作業消耗的時數是 Linux 上消耗速度的2到10倍。 例如: 執行消耗了 1,000分鐘的 Windows時數,將消耗您帳戶中所包含的 2000 分鐘時數。 執行消耗了 1,000分鐘的 macOS 時數,將消耗您帳戶中的 10,000 分鐘時數。

https://ithelp.ithome.com.tw/upload/images/20201004/20104220GlaLAfiWbn.png

如何測試他?

你會看到綠色勾勾,就是成功了 https://ithelp.ithome.com.tw/upload/images/20201005/20104220UdDzI3vxP8.png

Marketplace

裡面可以找到許多別人已寫好的 actions

https://github.com/marketplace/actions/cache

https://ithelp.ithome.com.tw/upload/images/20201005/201042204t7M0suw2B.png

Secrets 設定加密環境變數

https://ithelp.ithome.com.tw/upload/images/20201005/20104220PEYrwrt8Uf.png

再來,找到我們所需的 Actions (Marketplace)

reactnativecommunity/react-native-android 範例: https://github.com/react-native-community/ci-sample 這個 Docker image 提供的 container 可以幫助我們完成 React Naive Android 的環境建置 也有支援其他 CI 工具

  • circleci
  • gitlab
  • travis-ci
  • azure devops
  • github actions

Generate Build Number

actions/checkout@v2

Generate Build Number

einaregilsson/build-number@v2

create Release Tag

actions/create-release@v1

Upload Artifact

actions/upload-artifact@v1

Upload Asset to Release

actions/upload-release-asset@v1

接者,建立你專案的Actions(workflows)

在GitHub上的存儲庫中,找到在.github/workflows名為的目錄中創建一個新文件 Build-Android.yml。 有關更多信息,請參見“創建新文件”。

將以下YAML內容複製到 Build-Android.yml 文件中。 注意:如果您的默認分支不是main,請更新的值 DEFAULT_BRANCH 以匹配存儲庫的默認分支名稱。

在這裡

name: Github Actions

# on: [push, pull_request]
on:
  push:
    branches: [  master  ]
    tags:
      - 'v*'
  pull_request:
    branches: [  master  ]
jobs:
  build:
    runs-on: ubuntu-latest
    container: reactnativecommunity/react-native-android
    steps:
    - name: "#️⃣ Generate Build Number"
      id: buildnumber
      uses: einaregilsson/build-number@v2
      with:
        token: ${{ secrets.ACTION_TEST }}
    - name: Print new build number
      run: |
        echo "Build number is $BUILD_NUMBER"
        echo "Build number is $buildnumber" ${{ steps.buildnumber.outputs.build_number }}
        echo  $BUILD_NUMBER
    - uses: actions/checkout@v2
    - name: Envinfo
      run: npx envinfo
    - name: Build application
      run: |
        yarn install && cd android && chmod +x gradlew && ./gradlew build bundleRelease 
        du -shc `find . -regex '.+\.\(apk\|aab\)$'`
#      run: yarn install && cd android && chmod +x gradlew && ./gradlew assembleRelease
            
    #Prepare Release
      
    - name: Prepare Release
      id: prepare_release
      run: |
        APK_PATH=`find . -name '*.apk' | grep release`
        echo ::set-output name=apk_path::$APK_PATH
        APK_NAME=`basename $APK_PATH`
        echo ::set-output name=apk_name::$APK_NAME
        BUNDLE_PATH=`find . -name '*.aab' | grep release | grep -v intermediates`
        echo ::set-output name=bundle_path::$BUNDLE_PATH
        BUNDLE_NAME=`basename $BUNDLE_PATH`
        echo ::set-output name=bundle_name::$BUNDLE_NAME
#        選用
#        TAG_NAME=`echo $GITHUB_REF | cut -d / -f3`
#        echo ::set-output name=tag_name::$TAG_NAME
#        PACKAGE_NAME=`./tools/aapt2 dump packagename $APK_PATH`
#        echo ::set-output name=package_name::$PACKAGE_NAME
    #Uploads
    - name: Upload Artifact
      if: steps.prepare_release.outputs.apk_path
      uses: actions/upload-artifact@v1
      with:
        name: app-release.apk
        path: android/app/build/outputs/apk/release/     
    #Uploads
    - name: Upload Artifact
      if: steps.prepare_release.outputs.bundle_path
      uses: actions/upload-artifact@v1
      with:
        name: app-release.aab
        path: android/app/build/outputs/bundle/release/  
        
    - name: Create GitHub release
      id: create_release
#       if: steps.version_check.outputs.changed == 'true'
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: V-${{ steps.buildnumber.outputs.build_number }}
        release_name: V-${{ steps.buildnumber.outputs.build_number }}
        body: |
          ![release!](https://i.giphy.com/media/lPulaaB9lDMnGZiivs/source.gif)
          # Changelog
          Release type: ${{ steps.buildnumber.outputs.build_number }}
        prerelease: true


    - name: Upload APK Asset
      if: steps.create_release.outputs.upload_url && steps.prepare_release.outputs.apk_path && steps.prepare_release.outputs.apk_name
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        upload_url: ${{steps.create_release.outputs.upload_url}}
        asset_path: ${{steps.prepare_release.outputs.apk_path}}
        asset_name: ${{steps.prepare_release.outputs.apk_name}}
        asset_content_type: application/vnd.android.package-archive
#       選用 BBA
    - name: Upload Bundle Asset
      if: steps.create_release.outputs.upload_url && steps.prepare_release.outputs.bundle_path && steps.prepare_release.outputs.bundle_name
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        upload_url: ${{steps.create_release.outputs.upload_url}}
        asset_path: ${{steps.prepare_release.outputs.bundle_path}}
        asset_name: ${{steps.prepare_release.outputs.bundle_name}}
        asset_content_type: application/octet-stream
        

測試他

你會看到,就是成功了 在 Download artifacts 有兩個可以下載的檔案

 app-release.aab26.3 MB
 app-release.apk

https://ithelp.ithome.com.tw/upload/images/20201006/20104220ce6Zsdf12e.png

在 Pre-release 中可以也找到完整的 Assets

app-release.aab 
app-release.apk 
Source code(zip)
Source code(tar.gz)

https://ithelp.ithome.com.tw/upload/images/20201006/20104220AAJyRpqTDk.png

上架準備

設定商店資訊

解決:找不到 APP ID : Package not found: XX.***.

https://ithelp.ithome.com.tw/upload/images/20201008/201042205BwEzmJ5Ut.png

https://ithelp.ithome.com.tw/upload/images/20201008/20104220mmZqfMUJjk.png

https://ithelp.ithome.com.tw/upload/images/20201008/201042208A1pXnXtdJ.png

Sign Bundle (WIP)

Generate an upload key and Keystore https://developer.android.com/studio/publish/app-signing#generate-key 將 KeyStore file,轉換為 base64 ,並加到 GitHub 專案的設定中的 Secret

cat MyKeyStore  | base64 | pbcopy
#ios cat AppleID.p12 | base64 | pbcopy

set version (WIP)

in android/app/build.gradle

def getMyVersionCode = { ->
    def code = project.hasProperty('versionCode') ? versionCode.toInteger() : -1
    println "VersionCode is set to $code"
    return code
}

def getMyVersionName = { ->
    def name = project.hasProperty('versionName') ? versionName : "1.0"
    println "VersionName is set to $name"
    return name
}

in android/app/build.gradle

    defaultConfig {
        applicationId "dev.dayuan.rn3d"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
+       versionCode getMyVersionCode()
+       versionName getMyVersionName()
-       // versionCode 1
-       // versionName "1.0"

    }

測試 Build

gradle build bundleRelease -PversionCode=483 -PversionName=4.0.3

測試 Run

adb -s emulator-5554 install app/build/outputs/apk/release/app-release.apk

專案/whatsNewDirectory/whatsnew-zh-TW

<zh-TW>
HAHAHAHmapping.txtmapping.txt在這裡輸入或貼上 zh-TW 版的版本資訊
</zh-TW>

自動打包簽署上架(WIP: 自動改版號)

name: Github Actions

# on: [push, pull_request]
on:
  push:
    branches: [  Release-Store  ]
    tags:
      - 'Store*'
  pull_request:
    branches: [  Release-Store  ]
jobs:
  build:
    runs-on: ubuntu-latest
    container: reactnativecommunity/react-native-android
    steps:
    - name: "#️⃣ Generate Build Number"
      id: buildnumber
      uses: einaregilsson/build-number@v2
      with:
        token: ${{ secrets.ACTION_TEST }}
    - name: "#️⃣ Generate Build Number store"
      id: buildnumber_store
      uses: einaregilsson/build-number@v2
      with:
        token: ${{ secrets.ACTION_TEST }}
        prefix: store
    - name: Print new build number
      run: |
        echo "Build number is $BUILD_NUMBER"
        echo "Build number is $buildnumber" ${{ steps.buildnumber.outputs.build_number }}
        echo "Build number is $buildnumber_store" ${{ steps.buildnumber.outputs.buildnumber_store }}
        echo  $BUILD_NUMBER
    - uses: actions/checkout@v2
    - name: Envinfo
      run: npx envinfo
    - name: Build application
      run: |
        yarn install && cd android && chmod +x gradlew && ./gradlew build bundleRelease 
        du -shc `find . -regex '.+\.\(apk\|aab\)$'`
#      run: yarn install && cd android && chmod +x gradlew && ./gradlew assembleRelease
      
      
#       ./gradlew build bundleRelease
#         du -shc `find . -regex '.+\.\(apk\|aab\)$'`
      
      
    #Prepare Release
      
    - name: Prepare Release
      id: prepare_release
#       if: contains(github.ref, 'tags/')
      run: |
        APK_PATH=`find . -name '*.apk' | grep release`
        echo ::set-output name=apk_path::$APK_PATH
        APK_NAME=`basename $APK_PATH`
        echo ::set-output name=apk_name::$APK_NAME
        BUNDLE_PATH=`find . -name '*.aab' | grep release | grep -v intermediates`
        echo ::set-output name=bundle_path::$BUNDLE_PATH
        BUNDLE_NAME=`basename $BUNDLE_PATH`
        echo ::set-output name=bundle_name::$BUNDLE_NAME
#        選用
#        TAG_NAME=`echo $GITHUB_REF | cut -d / -f3`
#        echo ::set-output name=tag_name::$TAG_NAME
#        PACKAGE_NAME=`./tools/aapt2 dump packagename $APK_PATH`
#        echo ::set-output name=package_name::$PACKAGE_NAME
    - name: Print build PATH
      run: |
        echo ${{steps.prepare_release.outputs.bundle_path}}
        echo ${{steps.prepare_release.outputs.apk_name}}
        echo ${{steps.prepare_release.outputs.bundle_path}}/${{steps.prepare_release.outputs.apk_name}}
#       簽署 BBA
    - name: Sign AAB
      id: sign
      uses: r0adkll/sign-android-release@v1
      with:
        releaseDirectory: ./android/app/build/outputs/bundle/release/
        signingKeyBase64: ${{ secrets.SIGNING_KEY }}
        alias: ${{ secrets.ALIAS }}
        keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
        keyPassword: ${{ secrets.KEY_PASSWORD }}

    #Uploads
    - name: Upload Artifact
      if: steps.prepare_release.outputs.apk_path
      uses: actions/upload-artifact@v1
      with:
        name: app-release.apk
        path: android/app/build/outputs/apk/release/     
    #Uploads
    - name: Upload Artifact
      if: steps.prepare_release.outputs.bundle_path
      uses: actions/upload-artifact@v1
      with:
        name: app-release.aab
        path: android/app/build/outputs/bundle/release/  
        
    - name: Create GitHub release
      id: create_release
#       if: steps.version_check.outputs.changed == 'true'
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.ACTION_TEST }}
      with:
        tag_name: V-${{ steps.buildnumber.outputs.build_number }}
        release_name: V-${{ steps.buildnumber.outputs.build_number }}
        body: |
          ![release!](https://i.giphy.com/media/lPulaaB9lDMnGZiivs/source.gif)
          # Changelog
          Release type: ${{ steps.buildnumber.outputs.build_number }}
        prerelease: true


    - name: Upload APK Asset
      if: steps.create_release.outputs.upload_url && steps.prepare_release.outputs.apk_path && steps.prepare_release.outputs.apk_name
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        upload_url: ${{steps.create_release.outputs.upload_url}}
        asset_path: ${{steps.prepare_release.outputs.apk_path}}
        asset_name: ${{steps.prepare_release.outputs.apk_name}}
        asset_content_type: application/vnd.android.package-archive
#       選用上傳 BBA 至 release  asset
    - name: Upload Bundle Asset
      if: steps.create_release.outputs.upload_url && steps.prepare_release.outputs.bundle_path && steps.prepare_release.outputs.bundle_name
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        upload_url: ${{steps.create_release.outputs.upload_url}}
        asset_path: ${{steps.prepare_release.outputs.bundle_path}}
        asset_name: ${{steps.prepare_release.outputs.bundle_name}}
        asset_content_type: application/octet-stream
#       上傳 BBA
    - name: Upload Android Release to Play Store (internal track publishing is default)
      uses: r0adkll/upload-google-play@v1
      with:
        serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
        packageName: dev.dayuan.rn3d
        releaseFile: ${{steps.prepare_release.outputs.bundle_path}}
        track: internal
        whatsNewDirectory: distribution/whatsnew

Authentication

First you have to create a Google Play API Access. To do that go to the Google Play Developer Console and then with the account owner go to Settings -> API access and create a Google Play Android Developer project.

After that follow the instructions to create a Service Account. When you click Create Client ID, choose Service Account. You will get a JSON file with a public key and the service email.

Google Play publisher account

For the initial setup only, you must have access to the Google account which owns the [Google Play publisher account][gp-docs-distribute].

This is required to enable API access from GitHub Actions to your Google Play account.

Note that having admin access is not enough; you need the account owner.
You can see who the account owner is under [Settings → User accounts & rights][gp-console-admin] in the Google Play developer console.

Please note

  • The app being uploaded must already exist in Google Play; you cannot use the API to upload brand new apps

Bundle size warnings

If you try to upload an AAB file to Google Play (including manually via the Google Play Developer Console), and its size is perhaps 100MB+, it may give you a warning:

The installation of the app bundle may be too large and trigger user warning on some […] this needs to be explicitly acknowledged

This plugin automatically "acknowledges" that warning on Google Play on your behalf when uploading any AAB files, regardless of their size, so you should not see any errors.

If you do see see any unexpected behaviour related to uploading bundles, or warnings appearing for end users, please let us know.

Setup

One-time: Set up Google Play credentials

The following initial setup process is demonstrated in this imge

截圖 2020-08-16 上午6 39 25

Install plugin

Install this plugin via the marketplace plugin manager. ensure that the prerequisite [Google OAuth Credentials Plugin][plugin-google-oauth], [Token Macro Plugin][plugin-token-macro] and their dependencies are also.

Create Google service account

To enable automated access to your Google Play account, you must create a service account:

  1. Sign in to the [Google Play developer console][gp-console] as the account owner
  2. Select Settings → Developer account → API access
  3. Under Service Accounts, click "Create Service Account"
  4. Follow the link to the Google API Console
  5. Click the "Create service account" button
  6. Give the service account any name you like, e.g. "Github Actions"
  7. Choose Service Accounts > Service Account User ( 中文搜尋要用[服務帳戶使用者]) for the "Role" field
  8. Enable "Furnish a new private key"
  9. Choose "JSON" as the key type (P12 works as well, but the Plugin suppter a JSON is a little simpler)
  10. Click the "Save" button
  11. Note that a .json file is downloaded, named something like "api-xxxxxxxxx-xxxxx-xxxx.json"
  12. Close the dialog that appears
  13. Copy the email address of the new user (something like "Github Actions@api-xxxxxxxxx-xxxxx-xxxx.iam.gserviceaccount.com")
  14. You can now close the page

Assign permissions to the service account

  1. Return to the Google Play developer console page
  2. Click "Done" on the dialog
  3. Note that the service account has been associated with the Google Play publisher account
    If it hasn't, follow these additional steps before continuing:
    1. Click "Users & permissions" in the menu
    2. Click "Invite new user"
    3. Paste in the email address you copied above
    4. Continue from step 5
  4. Click the "Grant access" button for the account (e.g. "Github Actions@api-xxxxxxxxx-xxxxx-xxxx.iam.gserviceaccount.com")
  5. Ensure that at least the following permissions are enabled:
    • View app information — this is required for the plugin to function
    • Manage production releases — optional, if you want to upload APKs to production
    • Manage testing track releases — if you want to upload APKs to alpha, beta, internal, or custom test tracks
  6. Click "Add user" (or "Send invitation", as appropriate)
  7. You can now log out of the Google Play publisher account

To do so, visit Google Play Console to set up API access and don’t forget to click Grant Access when you are done.

Refer to

https://github.com/jenkinsci/google-play-android-publisher-plugin/blob/master/README.md https://medium.com/@iqan/continuously-releasing-flutter-app-to-play-store-using-github-actions-eca2f5f6e996

@CS6
Copy link
Author

CS6 commented Oct 6, 2020

WIP 用 GitHub Actions 修改 Build Number 並上架到 Play Console測試
FIX-CI
r0adkll/upload-google-play@v1
Notify Build status on Slack / Telegram

@CS6
Copy link
Author

CS6 commented Oct 6, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment