--- name: Android - Verify F-Droid and reproducible builds on: schedule: # At 04:20 UTC every monday. # Notifications for scheduled workflows are sent to the user who last modified the cron # syntax in the workflow file. If you update this you must have notifications for # Github Actions enabled, so these don't go unnoticed. # https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/notifications-for-workflow-runs - cron: '20 6 * * 1' workflow_dispatch: inputs: commit_hash: type: string required: false pull_request: paths: - '.github/workflows/android-reproducible-builds.yml' - 'building/android-container-image.txt' - 'dist-assets/android-version*' - 'android/src/main/play/release-notes/en-US/default.txt' - 'android/gradle/**' - 'android/flake*' push: tags: - 'android/**' permissions: {} jobs: set-up-env: name: Setup commit hash runs-on: ubuntu-latest steps: - id: hash name: Set commit hash or default to github.sha run: | # If the input has a value, it is filled by that value; otherwise, fallback to PR sha. # If it is not triggered by a PR, use github.sha. if [ -n "${{ inputs.commit_hash }}" ]; then echo "commit_hash=${{ inputs.commit_hash }}" >> "$GITHUB_OUTPUT" else echo "commit_hash=${{ github.event.pull_request.head.sha || github.sha }}" >> "$GITHUB_OUTPUT" fi outputs: COMMIT_HASH: ${{ steps.hash.outputs.commit_hash }} build-using-container: name: Build fdroid variant using container runs-on: ubuntu-latest needs: set-up-env steps: - name: Checkout repository uses: actions/checkout@v4 with: ref: ${{ needs.set-up-env.outputs.COMMIT_HASH }} submodules: true - name: Fetch submodules and tags run: | git submodule update --init wireguard-go-rs/libwg/wireguard-go git fetch --no-tags origin 'refs/tags/android/*:refs/tags/android/*' - name: Build app run: ./building/containerized-build.sh android --fdroid - name: Upload apks uses: actions/upload-artifact@v4 with: name: apk-container path: android/app/build/outputs/apk/ossProd/fdroid/app-oss-prod-fdroid-unsigned.apk if-no-files-found: error retention-days: 7 build-using-fdroidserver: name: Build fdroid variant using fdroidserver runs-on: ubuntu-latest needs: set-up-env steps: - name: Install fdroidserver run: | sudo apt-get -y update sudo apt-get -y install fdroidserver - name: Check out gradle properties uses: actions/checkout@v4 with: ref: ${{ needs.set-up-env.outputs.COMMIT_HASH }} path: app-gradle sparse-checkout: | android/gradle/wrapper/gradle-wrapper.properties sparse-checkout-cone-mode: false - name: Extract gradle version run: | echo "gradle_version=\ $(grep -oP 'gradle-\K[0-9]+\.[0-9]+\.[0-9]+' app-gradle/android/gradle/wrapper/gradle-wrapper.properties)" \ >> $GITHUB_ENV - name: Install gradle run: | sudo apt-get -y remove gradle mkdir /opt/gradle curl -sfLo /opt/gradle/gradle-${{ env.gradle_version }}-bin.zip \ https\://services.gradle.org/distributions/gradle-${{ env.gradle_version }}-bin.zip unzip -d /opt/gradle /opt/gradle/gradle-${{ env.gradle_version }}-bin.zip # These are equivalent to the sudo section of the metadata file - name: Install dependencies run: sudo apt-get install -y build-essential protobuf-compiler libprotobuf-dev - name: Init fdroid run: fdroid init - name: Check out metadata uses: actions/checkout@v4 with: path: app-metadata sparse-checkout: | android/fdroid-build/metadata/net.mullvad.mullvadvpn.yml sparse-checkout-cone-mode: false - name: Prepare metadata run: | mkdir metadata cp app-metadata/android/fdroid-build/metadata/net.mullvad.mullvadvpn.yml metadata/net.mullvad.mullvadvpn.yml sed -i 's/commit-hash/${{ needs.set-up-env.outputs.COMMIT_HASH }}/' metadata/net.mullvad.mullvadvpn.yml - name: Build app run: | export PATH=$PATH:/opt/gradle/gradle-${{ env.gradle_version }}/bin fdroid build net.mullvad.mullvadvpn:1 - name: Upload apks uses: actions/upload-artifact@v4 with: name: apk-fdroidserver path: | build/net\.mullvad\.mullvadvpn/android/app/build/outputs/apk/ossProd/fdroid/app-oss-prod-fdroid-unsigned.apk if-no-files-found: error retention-days: 7 build-using-nix: name: Build fdroid variant using nix runs-on: ${{ matrix.runs-on }} needs: set-up-env strategy: fail-fast: false matrix: include: - runs-on: ubuntu-latest - runs-on: macos-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: ref: ${{ needs.set-up-env.outputs.COMMIT_HASH }} submodules: true - name: Fetch submodules and tags run: | git submodule update --init wireguard-go-rs/libwg/wireguard-go git fetch --no-tags origin 'refs/tags/android/*:refs/tags/android/*' - uses: cachix/install-nix-action@v31 with: nix_path: nixpkgs=channel:nixos-unstable - name: Build app working-directory: android run: nix develop -c ./gradlew assembleOssProdFdroid - name: Upload apks uses: actions/upload-artifact@v4 with: name: apk-nix-${{ matrix.runs-on }} path: android/app/build/outputs/apk/ossProd/fdroid/app-oss-prod-fdroid-unsigned.apk if-no-files-found: error retention-days: 7 compare-builds: name: Check builds runs-on: ubuntu-latest needs: [build-using-container, build-using-fdroidserver, build-using-nix] steps: - name: Download artifacts uses: actions/download-artifact@v4 with: path: artifacts pattern: apk-* merge-multiple: false - name: Print checksums working-directory: ./artifacts run: sha256sum */* - name: Compare files working-directory: ./artifacts run: diff apk-container/app-oss-prod-fdroid-unsigned.apk apk-fdroidserver/app-oss-prod-fdroid-unsigned.apk # Included in this workflow since it's the only place # release artifacts are built. Should eventually be moved. check-permissions: name: Check APK permissions runs-on: ubuntu-latest needs: [set-up-env, build-using-container] steps: - name: Install apktool run: sudo apt-get install -y apktool - name: Checkout repository uses: actions/checkout@v4 with: ref: ${{ needs.set-up-env.outputs.COMMIT_HASH }} submodules: true - name: Download container apk uses: actions/download-artifact@v4 with: name: apk-container - name: Extract resources run: | apktool d app-oss-prod-fdroid-unsigned.apk -s -o output - name: Compare manifest permissions with checked in snapshot run: | diff android/snapshot/manifest-permissions-oss.txt <(cat output/AndroidManifest.xml | grep uses-permission)