fix(vpn): tolerate apps absent from the device in the per-app ACL #187
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - 'v*' | |
| pull_request: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| concurrency: | |
| group: build-${{ github.ref }} | |
| cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| env: | |
| IS_STABLE: ${{ startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-') }} | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2.23.0 | |
| with: | |
| channel: stable | |
| flutter-version: 3.35.7 | |
| cache: true | |
| - name: Flutter pub get | |
| run: flutter pub get | |
| - name: Dart format check | |
| run: dart format --output=none --set-exit-if-changed . | |
| - name: Flutter analyze (fatal infos, app code only) | |
| run: | | |
| out=$(flutter analyze --no-pub --fatal-infos 2>&1) | |
| echo "$out" | |
| filtered=$(printf '%s\n' "$out" | grep -E '^\s+(info|warning|error)' | grep -v 'plugins/' || true) | |
| if [ -n "$filtered" ]; then | |
| echo "::error::flutter analyze reported issues in app code" | |
| exit 1 | |
| fi | |
| - name: DCM check-unused-code | |
| run: | | |
| out=$(dart run dart_code_linter:metrics check-unused-code lib 2>&1) | |
| echo "$out" | |
| if echo "$out" | grep -q "✖ total unused"; then | |
| echo "::error::dart_code_linter found unused code" | |
| exit 1 | |
| fi | |
| - name: DCM check-unused-files | |
| run: | | |
| out=$(dart run dart_code_linter:metrics check-unused-files lib 2>&1) | |
| echo "$out" | |
| if echo "$out" | grep -q "✖ total unused files"; then | |
| echo "::error::dart_code_linter found unused files" | |
| exit 1 | |
| fi | |
| - name: Flutter test | |
| run: flutter test --no-pub --reporter=expanded | |
| - name: Setup Java for detekt | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Install detekt | |
| run: | | |
| curl -sSLo detekt.jar https://github.com/detekt/detekt/releases/download/v1.23.7/detekt-cli-1.23.7-all.jar | |
| echo '#!/usr/bin/env bash' > /usr/local/bin/detekt | |
| echo 'exec java -jar '"$PWD/detekt.jar"' "$@"' >> /usr/local/bin/detekt | |
| sudo chmod +x /usr/local/bin/detekt | |
| - name: Detekt | |
| run: | | |
| detekt \ | |
| --input android/app/src/main/kotlin,android/app/src/main/java,android/app/src/bydpi/kotlin,android/service/src/main/java,android/common/src/main/java \ | |
| --build-upon-default-config \ | |
| ${{ hashFiles('detekt.yml') != '' && '--config detekt.yml' || '' }} | |
| secrets-scan: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Gitleaks | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| build: | |
| # Pull requests get lint+secrets only (under 5 min). Full APK matrix runs | |
| # on push to main and on version tags, where it gates the release. | |
| if: github.event_name != 'pull_request' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| needs: lint | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: android | |
| os: ubuntu-latest | |
| flavor: classic | |
| - platform: android | |
| os: ubuntu-latest | |
| flavor: bydpi | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Setup Android Signing | |
| run: | | |
| echo "${{ secrets.KEYSTORE }}" | base64 --decode > android/app/keystore.jks | |
| echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/local.properties | |
| echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> android/local.properties | |
| echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/local.properties | |
| - name: Setup Java | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Setup Gradle | |
| uses: gradle/actions/setup-gradle@v4 | |
| with: | |
| cache-read-only: false | |
| build-scan-publish: false | |
| gradle-home-cache-cleanup: true | |
| - name: Cache Android NDK | |
| id: ndk-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/local/lib/android/sdk/ndk/28.0.13004108 | |
| key: ndk-28.0.13004108-${{ runner.os }} | |
| restore-keys: | | |
| ndk-28.0.13004108- | |
| - name: Install Android NDK | |
| if: steps.ndk-cache.outputs.cache-hit != 'true' | |
| run: | | |
| "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --install "ndk;28.0.13004108" | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2.23.0 | |
| with: | |
| channel: stable | |
| flutter-version: 3.35.7 | |
| cache: true | |
| - name: Get Flutter Dependency | |
| run: | | |
| flutter --version | |
| flutter pub get | |
| - name: Setup | |
| run: dart setup.dart ${{ matrix.platform }} --flavor ${{ matrix.flavor }} ${{ env.IS_STABLE == 'true' && '--env stable' || '' }} | |
| - name: Verify 16-KB page-size alignment for native libs | |
| if: startsWith(matrix.platform,'android') | |
| run: | | |
| BUILD_TOOLS=$(ls -d "$ANDROID_HOME"/build-tools/*/ | sort -V | tail -1) | |
| ZIPALIGN="${BUILD_TOOLS}zipalign" | |
| echo "Using $ZIPALIGN" | |
| shopt -s nullglob | |
| apks=(./dist/*.apk) | |
| if [ ${#apks[@]} -eq 0 ]; then | |
| echo "No APK in ./dist, nothing to verify" | |
| exit 0 | |
| fi | |
| for apk in "${apks[@]}"; do | |
| echo "Checking $apk for 16-KB .so alignment (Android 15+)" | |
| "$ZIPALIGN" -P 16 -c -v 4 "$apk" 2>&1 | grep -E "\.so .* (BAD|OK)" || true | |
| "$ZIPALIGN" -P 16 -c 4 "$apk" || { echo "FAILED: native .so libs in $apk are not 16-KB aligned"; exit 1; } | |
| done | |
| - name: Upload | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: artifact-${{ matrix.platform }}-${{ matrix.flavor }} | |
| path: ./dist | |
| overwrite: true | |
| release: | |
| needs: build | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine prerelease flag | |
| id: detect | |
| run: | | |
| TAG="${GITHUB_REF#refs/tags/}" | |
| TAG_SHA=$(git rev-parse "$TAG^{commit}") | |
| IS_ON_MAIN=false | |
| if git merge-base --is-ancestor "$TAG_SHA" origin/main 2>/dev/null; then | |
| IS_ON_MAIN=true | |
| fi | |
| HAS_HYPHEN=false | |
| [[ "$TAG" == *"-"* ]] && HAS_HYPHEN=true | |
| if $IS_ON_MAIN && ! $HAS_HYPHEN; then | |
| PRERELEASE=false | |
| else | |
| PRERELEASE=true | |
| fi | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "prerelease=$PRERELEASE" >> "$GITHUB_OUTPUT" | |
| echo "Tag: $TAG, on-main=$IS_ON_MAIN, has-hyphen=$HAS_HYPHEN, prerelease=$PRERELEASE" | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| pattern: artifact-* | |
| - name: Collect APKs | |
| run: | | |
| mkdir -p release-apks | |
| find artifacts -name '*.apk' -exec cp {} release-apks/ \; | |
| ls -la release-apks/ | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v2.6.2 | |
| with: | |
| tag_name: ${{ steps.detect.outputs.tag }} | |
| name: ${{ steps.detect.outputs.tag }} | |
| prerelease: ${{ steps.detect.outputs.prerelease }} | |
| generate_release_notes: true | |
| files: release-apks/*.apk | |
| fail_on_unmatched_files: true |