| 1 | name: Reusable Build Logic |
| 2 | |
| 3 | permissions: |
| 4 | contents: read |
| 5 | packages: write |
| 6 | |
| 7 | on: |
| 8 | workflow_call: |
| 9 | inputs: |
| 10 | ref: |
| 11 | required: true |
| 12 | type: string |
| 13 | pr_number: |
| 14 | required: true |
| 15 | type: string |
| 16 | |
| 17 | defaults: |
| 18 | run: |
| 19 | shell: bash |
| 20 | jobs: |
| 21 | PR_test_build: |
| 22 | runs-on: [Linux, amd64, android] |
| 23 | container: |
| 24 | image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly |
| 25 | env: |
| 26 | STORE_PASS: test@cake_wallet |
| 27 | KEY_PASS: test@cake_wallet |
| 28 | MONEROC_CACHE_DIR_ROOT: /opt/generic_cache |
| 29 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} |
| 30 | ANDROID_AVD_HOME: /root/.android/avd |
| 31 | volumes: |
| 32 | - /opt/cw_cache_android/root/.cache:/root/.cache |
| 33 | - /opt/cw_cache_android/root/.android/avd/:/root/.android/avd |
| 34 | - /opt/cw_cache_android/root/.ccache:/root/.ccache |
| 35 | - /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache |
| 36 | - /opt/cw_cache_android/root/.gradle/:/root/.gradle |
| 37 | - /opt/cw_cache_android/root/.android/:/root/.android |
| 38 | - /opt/cw_cache_android/root/go/pkg:/root/go/pkg |
| 39 | - /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache |
| 40 | - /dev/kvm:/dev/kvm |
| 41 | - /var/run/docker.sock:/var/run/docker.sock |
| 42 | strategy: |
| 43 | matrix: |
| 44 | api-level: [29] |
| 45 | |
| 46 | steps: |
| 47 | - name: Fix github actions messing up $HOME... |
| 48 | run: "echo HOME=/root | sudo tee -a $GITHUB_ENV" |
| 49 | - uses: actions/checkout@v4 |
| 50 | with: |
| 51 | ref: ${{ inputs.ref }} |
| 52 | |
| 53 | - name: Log in to GitHub Container Registry |
| 54 | uses: docker/login-action@v3 |
| 55 | with: |
| 56 | registry: ghcr.io |
| 57 | username: ${{ github.actor }} |
| 58 | password: ${{ secrets.GITHUB_TOKEN }} |
| 59 | |
| 60 | - name: Get the full commit message |
| 61 | run: | |
| 62 | FULL_MESSAGE="$(git log -1 --pretty=%B)" |
| 63 | echo "message<<EOF" >> $GITHUB_ENV |
| 64 | echo "$FULL_MESSAGE" >> $GITHUB_ENV |
| 65 | echo "EOF" >> $GITHUB_ENV |
| 66 | |
| 67 | - name: Add secrets |
| 68 | run: | |
| 69 | touch cw_bitcoin/lib/.secrets.g.dart |
| 70 | touch cw_evm/lib/.secrets.g.dart |
| 71 | touch cw_solana/lib/.secrets.g.dart |
| 72 | touch cw_core/lib/.secrets.g.dart |
| 73 | touch cw_nano/lib/.secrets.g.dart |
| 74 | touch cw_tron/lib/.secrets.g.dart |
| 75 | |
| 76 | echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart |
| 77 | echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart |
| 78 | echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart |
| 79 | echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart |
| 80 | echo "const blinkApiKey = '${{ secrets.BLINK_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart |
| 81 | echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart |
| 82 | echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart |
| 83 | echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart |
| 84 | |
| 85 | echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart |
| 86 | echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart |
| 87 | |
| 88 | echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart |
| 89 | echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart |
| 90 | |
| 91 | echo "const breezApiKey = '${{ secrets.BREEZ_API_KEY }}';" >> cw_bitcoin/lib/.secrets.g.dart |
| 92 | |
| 93 | echo "${{ secrets.MAIN_SECRETS_FILE }}" | base64 --decode > lib/.secrets.g.dart |
| 94 | |
| 95 | - name: Generate KeyStore |
| 96 | run: | |
| 97 | pushd /opt/generic_cache |
| 98 | if [[ ! -f key.jks ]]; |
| 99 | then |
| 100 | keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS |
| 101 | else |
| 102 | echo "$PWD/key.jks exist, not generating" |
| 103 | fi |
| 104 | popd |
| 105 | cp /opt/generic_cache/key.jks android/app |
| 106 | |
| 107 | - name: Build dependencies utilizing ghcr cache |
| 108 | run: | |
| 109 | env \ |
| 110 | CW_DOCKER_REGISTRY=ghcr.io/cake-tech/cake_wallet \ |
| 111 | CW_DOCKER_USE_CLOUD=true \ |
| 112 | ./scripts/android/docker/build.sh |
| 113 | |
| 114 | - name: Execute Build and Setup Commands |
| 115 | run: | |
| 116 | pushd scripts/android |
| 117 | source ./app_env.sh cakewallet |
| 118 | export GITHUB_HUH=yeah |
| 119 | ./app_config.sh |
| 120 | popd |
| 121 | |
| 122 | - name: Install Flutter dependencies |
| 123 | run: | |
| 124 | flutter pub get |
| 125 | |
| 126 | - name: Build generated code |
| 127 | run: | |
| 128 | ./model_generator.sh |
| 129 | |
| 130 | |
| 131 | - name: Generate key properties |
| 132 | run: | |
| 133 | dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS |
| 134 | |
| 135 | - name: Generate localization |
| 136 | run: | |
| 137 | dart run tool/generate_localization.dart |
| 138 | |
| 139 | - name: Compile graphics |
| 140 | run: | |
| 141 | ./compile_graphics.sh |
| 142 | |
| 143 | - name: Rename app |
| 144 | run: | |
| 145 | sanitized_branch_name=${BRANCH_NAME#origin/} # Remove 'origin/' prefix if it exists |
| 146 | sanitized_branch_name=${sanitized_branch_name:0:16} # Take only the first 16 characters |
| 147 | sanitized_branch_name=$(echo "$sanitized_branch_name" | tr '[:upper:]' '[:lower:]') # Convert to lowercase |
| 148 | sanitized_branch_name=$(echo "$sanitized_branch_name" | sed 's/[^a-z0-9]//g') # Remove all special characters |
| 149 | |
| 150 | echo -e "id=com.cakewallet.test_${sanitized_branch_name}\nname=${BRANCH_NAME}" > android/app.properties |
| 151 | |
| 152 | - name: Replace email address |
| 153 | run: | |
| 154 | PATTERN1="support@cakewallet.com" |
| 155 | PATTERN1REP="dev.testflight.cakewallet@mrcyjanek.net" |
| 156 | echo lib/utils/exception_handler.dart \ |
| 157 | lib/view_model/support_view_model.dart \ |
| 158 | | while IFS= read -r -d '' file; do |
| 159 | sed -i.bak \ |
| 160 | -e "s|$PATTERN1|$PATTERN1REP|g" \ |
| 161 | "$file" |
| 162 | done |
| 163 | |
| 164 | - name: Build |
| 165 | run: | |
| 166 | export ANDROID_NDK_HOME="$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION" |
| 167 | export ANDROID_NDK="$ANDROID_NDK_HOME" |
| 168 | pushd $ANDROID_SDK_ROOT/ndk |
| 169 | ln -s 28.2.13676358 25.1.8937393 |
| 170 | popd |
| 171 | flutter build apk --dart-define=hasDevOptions=true --release --split-per-abi |
| 172 | |
| 173 | - name: Rename apk file |
| 174 | run: | |
| 175 | sanitized_branch_name=$(grep '^id=' android/app.properties | cut -d'=' -f2 | sed 's/com\.cakewallet\.test_//') |
| 176 | cd build/app/outputs/flutter-apk |
| 177 | mkdir test-apk |
| 178 | cp app-arm64-v8a-release.apk test-apk/${sanitized_branch_name}.apk |
| 179 | cp app-x86_64-release.apk test-apk/${sanitized_branch_name}_x86.apk |
| 180 | |
| 181 | - name: Find APK file |
| 182 | id: find_apk |
| 183 | run: | |
| 184 | set -x |
| 185 | sanitized_branch_name=$(grep '^id=' android/app.properties | cut -d'=' -f2 | sed 's/com\.cakewallet\.test_//') |
| 186 | apk_file=$(ls build/app/outputs/flutter-apk/test-apk/${sanitized_branch_name}.apk || exit 1) |
| 187 | echo "APK_FILE=$apk_file" >> $GITHUB_ENV |
| 188 | - name: Write BRANCH_NAME to env |
| 189 | run: echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV |
| 190 | |
| 191 | - name: Upload to slack step |
| 192 | uses: vaporif/slack-file-upload-action@v1 |
| 193 | with: |
| 194 | token: ${{ secrets.SLACK_APP_TOKEN }} |
| 195 | initial_comment: ${{ env.message }} |
| 196 | files: > |
| 197 | [ |
| 198 | {"file": "${{ env.APK_FILE }}", "filename": "${{ env.BRANCH_NAME }}.apk"} |
| 199 | ] |
| 200 | channel_id: ${{ secrets.SLACK_APK_CHANNEL }} |
| 201 | |
| 202 | - name: cleanup |
| 203 | run: rm -rf build/app/outputs/flutter-apk/test-apk/ |
| 204 | |
| 205 | - name: Upload Artifact to github |
| 206 | uses: actions/upload-artifact@v4 |
| 207 | with: |
| 208 | path: ${{ github.workspace }}/build/app/outputs/flutter-apk |
| 209 | name: "android apk" |
| 210 | |
| 211 | - name: 16KB align |
| 212 | run: | |
| 213 | cd build/app/outputs/flutter-apk |
| 214 | for i in arm64-v8a x86_64; do |
| 215 | ../../../../scripts/android/check_16kb_align.sh app-$i-release.apk |
| 216 | done |