fix: Update Linux integration test step to use setup-xvfb action for … #735
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: Flutter CI | |
| permissions: | |
| contents: write | |
| on: | |
| push: | |
| branches: [master] | |
| paths: | |
| - 'client/**' | |
| - '.github/workflows/flutter-ci.yml' | |
| pull_request: | |
| branches: [master] | |
| paths: | |
| - 'client/**' | |
| - '.github/workflows/flutter-ci.yml' | |
| workflow_dispatch: | |
| env: | |
| FLUTTER_WORKING_DIR: client | |
| FLUTTER_VER: 3.38.8 | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: ${{ env.FLUTTER_WORKING_DIR }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Flutter SDK | |
| uses: flutter-actions/setup-flutter@v4 | |
| with: | |
| channel: stable | |
| version: ${{ env.FLUTTER_VER }} | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.pub-cache | |
| key: ${{ runner.os }}-pub-cache-${{ hashFiles('client/pubspec.yaml', 'client/pubspec.lock', 'client/packages/*/pubspec.yaml') }} | |
| restore-keys: ${{ runner.os }}-pub-cache- | |
| - name: Add pub cache to PATH | |
| run: echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH | |
| - name: Activate melos and bootstrap | |
| run: | | |
| dart pub global activate melos | |
| melos bootstrap | |
| - name: Run Melos format check | |
| run: melos format --set-exit-if-changed . | |
| - name: Run analyze | |
| run: melos run analyze | |
| - name: Run unit/widget tests | |
| run: | | |
| flutter test | |
| melos run test:dart --no-select | |
| - name: Install requirements for desktop integration tests and Linux builds) | |
| run: sudo apt-get update && sudo apt-get install -y xvfb libgtk-3-dev libstdc++-12-dev | |
| - name: Run linux integration tests | |
| uses: coactions/setup-xvfb@v1 | |
| with: | |
| run: flutter test integration_test/app_test.dart -d linux -r github | |
| build-apk: | |
| needs: test | |
| runs-on: ubuntu-latest | |
| container: 'ghcr.io/cirruslabs/flutter:3.38.8' | |
| defaults: | |
| run: | |
| working-directory: ${{ env.FLUTTER_WORKING_DIR }} | |
| outputs: | |
| version: ${{ steps.get_version.outputs.version }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Decode keystore from base64 | |
| shell: bash | |
| run: | | |
| printf "%s" "$KEYSTORE_BASE64" | base64 -d > android/app/keystore.jks | |
| env: | |
| KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} | |
| - name: Set up signing properties | |
| run: | | |
| cat > android/app/key.properties << EOF | |
| storeFile=keystore.jks | |
| keyAlias=${{ secrets.KEYSTORE_KEY_ALIAS }} | |
| storePassword=${{ secrets.KEYSTORE_PASSWORD }} | |
| keyPassword=${{ secrets.KEYSTORE_PASSWORD }} | |
| EOF | |
| - name: Validate Android keystore | |
| shell: bash | |
| run: | | |
| keytool -list -keystore android/app/keystore.jks -storepass "$KEYSTORE_PASSWORD" -alias "$KEYSTORE_KEY_ALIAS" | |
| env: | |
| KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} | |
| KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.pub-cache | |
| key: ${{ runner.os }}-pub-cache-${{ hashFiles('client/pubspec.yaml', 'client/pubspec.lock', 'client/packages/*/pubspec.yaml') }} | |
| restore-keys: ${{ runner.os }}-pub-cache- | |
| - name: Cache Gradle dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('client/**/*.gradle*', 'client/**/gradle-wrapper.properties') }} | |
| restore-keys: ${{ runner.os }}-gradle- | |
| - name: Add pub cache to PATH | |
| run: echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH | |
| - name: Activate melos and bootstrap | |
| run: | | |
| dart pub global activate melos | |
| melos bootstrap | |
| - name: Get Flutter dependencies | |
| run: flutter pub get | |
| - name: Get version from pubspec.yaml | |
| id: get_version | |
| run: | | |
| VERSION=$(grep '^version:' pubspec.yaml | head -n1 | awk '{print $2}' | cut -d'+' -f1) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Build APK | |
| run: flutter build apk --release --target-platform android-arm64 --build-number ${{ github.run_number }} | |
| - name: Rename APK with version | |
| run: | | |
| mv build/app/outputs/flutter-apk/app-release.apk \ | |
| build/app/outputs/flutter-apk/borneo-app-ce-${{ steps.get_version.outputs.version }}.apk | |
| - name: Upload APK artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: borneo-app-ce-${{ steps.get_version.outputs.version }} | |
| path: ${{ github.workspace }}/${{ env.FLUTTER_WORKING_DIR }}/build/app/outputs/flutter-apk/borneo-app-ce-${{ steps.get_version.outputs.version }}.apk | |
| build-windows: | |
| needs: test | |
| runs-on: windows-latest | |
| defaults: | |
| run: | |
| working-directory: ${{ env.FLUTTER_WORKING_DIR }} | |
| outputs: | |
| version: ${{ steps.get_version.outputs.version }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Flutter SDK | |
| uses: flutter-actions/setup-flutter@v4 | |
| with: | |
| channel: stable | |
| version: ${{ env.FLUTTER_VER }} | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.pub-cache | |
| key: ${{ runner.os }}-pub-cache-${{ hashFiles('client/pubspec.yaml', 'client/pubspec.lock', 'client/packages/*/pubspec.yaml') }} | |
| restore-keys: ${{ runner.os }}-pub-cache- | |
| # Cache NuGet packages to speed MSBuild / CMake native deps | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('client/windows/**') }} | |
| restore-keys: ${{ runner.os }}-nuget- | |
| - name: Cache MSBuild | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/AppData/Local/Microsoft/VisualStudio | |
| key: ${{ runner.os }}-msbuild-${{ hashFiles('client/windows/**') }} | |
| restore-keys: ${{ runner.os }}-msbuild- | |
| # Pre-download Flutter engine/artifacts for Windows (avoid on-the-fly downloads) | |
| - name: Flutter precache (windows) | |
| run: flutter precache --windows | |
| - name: Activate melos and bootstrap | |
| run: | | |
| dart pub global activate melos | |
| melos bootstrap | |
| - name: Get Flutter dependencies | |
| run: flutter pub get | |
| - name: Get version from pubspec.yaml | |
| id: get_version | |
| run: | | |
| $version = (Select-String -Path pubspec.yaml -Pattern '^version:' | Select-Object -First 1).Line.Split(':')[1].Trim().Split('+')[0] | |
| echo "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append | |
| - name: Build Windows executable | |
| run: flutter build windows --release --build-number ${{ github.run_number }} | |
| - name: Create and zip Windows release | |
| run: | | |
| pwsh ./scripts/windows-dist-pack.ps1 ce-${{ steps.get_version.outputs.version }} | |
| - name: Upload Windows zip artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: borneo-app-ce-${{ steps.get_version.outputs.version }}-windows-x64 | |
| path: client/build/windows/dist/borneo-app-ce-${{ steps.get_version.outputs.version }}-windows-x64.zip | |
| build-ios: | |
| needs: test | |
| runs-on: macos-14 | |
| defaults: | |
| run: | |
| working-directory: ${{ env.FLUTTER_WORKING_DIR }} | |
| outputs: | |
| version: ${{ steps.get_version.outputs.version }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Flutter SDK | |
| uses: flutter-actions/setup-flutter@v4 | |
| with: | |
| channel: stable | |
| version: ${{ env.FLUTTER_VER }} | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.pub-cache | |
| key: ${{ runner.os }}-pub-cache-${{ hashFiles('client/pubspec.yaml', 'client/pubspec.lock', 'client/packages/*/pubspec.yaml') }} | |
| restore-keys: ${{ runner.os }}-pub-cache- | |
| - name: Cache CocoaPods | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cocoapods | |
| ~/Library/Caches/CocoaPods | |
| ${{ github.workspace }}/client/ios/Pods | |
| key: ${{ runner.os }}-pods-${{ hashFiles('client/ios/Podfile.lock') }} | |
| restore-keys: ${{ runner.os }}-pods- | |
| - name: Flutter precache (iOS) | |
| run: flutter precache --ios | |
| - name: Activate melos and bootstrap | |
| run: | | |
| dart pub global activate melos | |
| melos bootstrap | |
| - name: Get Flutter dependencies | |
| run: flutter pub get | |
| - name: Get version from pubspec.yaml | |
| id: get_version | |
| run: | | |
| VERSION=$(grep '^version:' pubspec.yaml | head -n1 | awk '{print $2}' | cut -d'+' -f1) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Build iOS app (no codesign) | |
| run: flutter build ios --release --no-codesign --build-number ${{ github.run_number }} | |
| release: | |
| needs: [build-apk, build-windows, build-ios] | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/master' | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./release-artifacts | |
| merge-multiple: true | |
| - name: Set prerelease flag | |
| id: set_prerelease | |
| run: | | |
| if [[ "${{ needs.build-apk.outputs.version }}" == *beta* || "${{ needs.build-apk.outputs.version }}" == *alpha* ]]; then | |
| echo "prerelease=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "prerelease=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Create Versionized GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: app-ce-v${{ needs.build-apk.outputs.version }} | |
| name: Borneo-IoT App Release app-ce-v${{ needs.build-apk.outputs.version }} | |
| draft: false | |
| overwrite_files: true | |
| prerelease: ${{ steps.set_prerelease.outputs.prerelease }} | |
| files: | | |
| release-artifacts/borneo-app-ce-${{ needs.build-apk.outputs.version }}.apk | |
| release-artifacts/borneo-app-ce-${{ needs.build-windows.outputs.version }}-windows-x64.zip | |
| - name: Manage latest tag via API | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const tag = 'release-app-latest'; | |
| const refName = `tags/${tag}`; | |
| const fullRef = `refs/tags/${tag}`; | |
| try { | |
| await github.rest.git.deleteRef({ owner: context.repo.owner, repo: context.repo.repo, ref: refName }); | |
| console.log(`Deleted existing tag ${tag}`); | |
| } catch (err) { | |
| // GitHub returns 404 _or_ 422 when the tag doesn't exist; ignore both | |
| if (err.status === 404 || err.status === 422) { | |
| console.log(`Tag ${tag} did not exist, proceeding to create`); | |
| } else { | |
| throw err; | |
| } | |
| } | |
| await github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: fullRef, sha: context.sha }); | |
| console.log(`Created tag ${tag} pointing to ${context.sha}`); | |
| - name: Delete previous latest app release | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const tag = 'release-app-latest'; | |
| try { | |
| const rel = await github.rest.repos.getReleaseByTag({ owner: context.repo.owner, repo: context.repo.repo, tag }); | |
| await github.rest.repos.deleteRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| release_id: rel.data.id, | |
| }); | |
| console.log('Deleted previous latest app release.'); | |
| } catch (err) { | |
| if (err.status === 404) { | |
| console.log('Latest app release not found, nothing to delete.'); | |
| } else { | |
| throw err; | |
| } | |
| } | |
| - name: Create GitHub Latest App Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: release-app-latest | |
| name: Latest App Release | |
| draft: false | |
| overwrite_files: true | |
| files: release-artifacts/* |