When Building the Android app in Debug Mode, The Standard Github Hosted Runner for Private Repos is fine. But for building an app in release mode, the 7GB RAM and 2cpu might not be sufficient and the action fails with out of memory exception.

Here, I have applied some tricks to make the release variant apk to succeed

name: Build Android
on:
  workflow_dispatch:
    inputs:
      app_variant:
        type: choice
        description: Pick App Variant
        options:
          - development
          - qa
          - uat
          - nextProd
          - beta
        required: true
 
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 120
    steps:
      - name: Remove unused software
        run: |
          echo "Available storage before:"
          sudo df -h
          echo
          sudo rm -rf /usr/share/dotnet
          sudo rm -rf /opt/ghc
          sudo rm -rf /opt/hostedtoolcache/CodeQL
          sudo rm -rf "/usr/local/share/boost"
          sudo rm -rf "$AGENT_TOOLSDIRECTORY"
          echo "Available storage after:"
          sudo df -h
          echo
          echo "Ram Details"
          free -h
 
      - name: Increase swapfile
        run: |
          sudo swapoff -a
          sudo fallocate -l 10G /swapfile
          sudo chmod 600 /swapfile
          sudo mkswap /swapfile
          sudo swapon /swapfile
          sudo swapon --show
 
      - name: Checkout
        uses: actions/checkout@v4
 
      - uses: oven-sh/setup-bun@v2
 
      - uses: actions/setup-java@v4
        with:
          distribution: 'zulu' # See 'Supported distributions' for available options
          java-version: '17'
 
      - name: Setup EAS
        uses: expo/expo-github-action@v8
        with:
          expo-version: latest
          eas-version: latest
          token: ${{ secrets.EXPO_TOKEN }}
          packager: 'bun'
          expo-cache: true
          eas-cache: true
 
      - name: Cache Gradle Dependencies and Wrapper
        uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-
 
      - name: Make Gradlew Executable
        run: cd android && chmod +x ./gradlew
 
      - name: Fetch version from eas config
        id: fetch_version
        run: |
          VERSION=$(eas config --profile production --platform android | grep '"version"' | head -n 1 | sed -E 's/.*"version": "(.*)".*/\1/')
          echo "APP_VERSION=${VERSION}" >> $GITHUB_ENV
 
      - name: Fetch Last Commit ID
        id: vars
        run: |
          calculatedSha=$(git rev-parse --short ${{ github.sha }})
          echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
 
      - name: Create Deployment
        id: deployment
        uses: bobheadxi/deployments@v1
        with:
          step: start
          token: ${{ secrets.GITHUB_TOKEN }}
          env: ${{ github.event.inputs.app_variant }}
          desc: 'Deploying to ${{ github.event.inputs.app_variant }}'
          ref: ${{ github.ref_name }}
 
      - name: Build Android Release
        run: eas build --profile ${{github.event.inputs.app_variant}} --platform android --local --output ${{ github.workspace }}/${{github.event.inputs.app_variant}}-${{env.APP_VERSION}}.apk
 
      - name: Notify on Slack
        uses: MeilCli/slack-upload-file@v4.0.17
        with:
          slack_token: ${{ secrets.SLACK_BOT_TOKEN }}
          channel_id: 'C0635NKP2TE'
          file_path: ${{github.event.inputs.app_variant}}-${{env.APP_VERSION}}.apk
          initial_comment: |
            Android Build Successful 🎉
 
            *Build Variant:* `${{github.event.inputs.app_variant}}`
            *Version:* `${{env.APP_VERSION}}`
            *Branch:*  `${{ github.ref_name }}`
            *Commit:*  <https://github.com/${{ github.repository }}/commit/${{ github.sha }}|${{ env.COMMIT_SHORT_SHA }}>
 
      - name: update deployment status
        uses: bobheadxi/deployments@v1
        if: always()
        with:
          step: finish
          token: ${{ secrets.GITHUB_TOKEN }}
          status: ${{ job.status }}
          env: ${{ github.event.inputs.app_variant }}
          deployment_id: ${{ steps.deployment.outputs.deployment_id }}

In the above Github Action, uat and nextProd are release variants.

Increase Build Time

Increase the Build time to 120 minutes so the build will still run even after 60 minutes, if it’s taking more time timeout-minutes: 120

Remove unused software

GtiHub Runner provides lots of packages that are not necessary for the Android Build which can be deleted.

The Step Remove unused software Deletes unnecessary files and folders in the runner. After running this step, you get around 10GB of space

Increase swapfile

The Standard GitHub Runner Specs is

Ram DetailsTotal
Memory7 GB
Swap3 GB

Overall, there is 10GB of RAM. Let’s utilize the 10GB freed-up space in the storage and increase the swapfile size to 10GB

The Step Increase swapfile increases the swapfile size. Now you have virtually 16GB of RAM which should be sufficient to build release variant of apk.

Ram DetailsTotal
Memory7 GB
Swap10 GB

Improve Gradle Properties

The Gradle properties in the newly created project allocated bare minimum RAM to build the apk. With the following changes we can utilise the Runner to the Max

org.gradle.jvmargs=-Xmx6g -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.daemon=false 

The jvmargs initially was 2g and it can be changed upto 14g. Let’s use 6g which means 6 GB

Note: In the latest versions of gradle 8 and above -XX:MaxPermSize name is changed to -XX:MaxMetaspaceSize=512m

Finally, you can now build with the least resources possible.