Skip to content

Feat/actions and tests #48

Feat/actions and tests

Feat/actions and tests #48

Workflow file for this run

name: Workflow
on:
push:
branches:
- "**"
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
pull_request:
branches:
- "**"
# # Allow manual runs so integration tests can be triggered explicitly
# workflow_dispatch:
env:
PATH_TO_DEMO: demo
FLUTTER_VERSION: 3.38.3
jobs:
#############################################
# Linting and formatting for demo and package
##############################################
lint-demo:
name: Lint Demo App
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
- name: Install demo dependencies
run: flutter pub get
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Run flutter analyze
run: make lint-demo
- name: Run flutter format check
run: make format-demo
lint-package:
name: Lint Package
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
- name: Install package dependencies
run: flutter pub get
- name: Lint Package (Flutter Analyze)
run: make lint-package
- name: Format Package (Dart Format)
run: make format-package
#############################################
# Tests for demo and package
##############################################
unit-test-package:
name: Unit Test Package
needs: [lint-package]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
- name: Install package dependencies
run: flutter pub get
- name: Install demo dependencies
run: flutter pub get
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Install junitreport converter
run: |
dart pub global activate junitreport
echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
# - name: Run unit tests
# run: make test-package-unit
- name: Run unit tests with coverage
run: make test-package-unit-coverage
- name: Upload Unit Test Coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: unit-test-coverage
path: coverage/unit/lcov.info
# - name: Upload Unit Test Console Logs
# uses: actions/upload-artifact@v4
# if: always()
# with:
# name: unit-test-console-logs
# path: build/test-results/unit/test-output.log
- name: Upload Unit Test Results
uses: actions/upload-artifact@v4
if: always()
with:
name: unit-test-results
path: build/test-results/unit/junit.xml
- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: build/test-results/unit/junit.xml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
widget-test-package:
name: Widget Test Package
needs: [lint-package]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
# In order for flutter_js to be testable on linux platform in widget tests, we need to first build our app for linux to compile the native libraries, which are then loaded during widget tests. This is a bit of a workaround but allows us to run widget tests for flutter_js on CI.
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libglu1-mesa ninja-build clang cmake pkg-config
- name: Install package dependencies
run: flutter pub get
- name: Install demo dependencies
run: flutter pub get
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Build Linux desktop app to compile native libraries
run: flutter build linux --debug
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Verify and find native library location
run: |
echo "Searching for libquickjs_c_bridge_plugin.so..."
find ${{ env.PATH_TO_DEMO }}/build -name "libquickjs_c_bridge_plugin.so" -type f || echo "Not found in build directory"
echo "Listing demo/build/linux structure:"
ls -la ${{ env.PATH_TO_DEMO }}/build/linux/ || echo "No linux directory"
find ${{ env.PATH_TO_DEMO }}/build/linux -type f -name "*.so" 2>/dev/null || echo "No .so files found"
- name: Install junitreport converter
run: |
dart pub global activate junitreport
echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
# Run widget tests once without coverage to get human-readable logs
# - name: Run widget tests
# run: make test-package-widget
# env:
# LIBQUICKJSC_TEST_PATH: "$ {{ github.workspace }}/demo/build/linux/x64/debug/plugins/flutter_js/bundle/lib/libquickjs_c_bridge_plugin.so"
- name: Run widget tests with coverage
run: make test-package-widget-coverage
env:
LIBQUICKJSC_TEST_PATH: "${{ github.workspace }}/demo/build/linux/x64/debug/plugins/flutter_js/bundle/lib/libquickjs_c_bridge_plugin.so"
- name: Upload Widget Test Coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: widget-test-coverage
path: coverage/widget/lcov.info
# - name: Upload Widget Test Console Logs
# uses: actions/upload-artifact@v4
# if: always()
# with:
# name: widget-test-console-logs
# path: build/test-results/widget/test-output.log
- name: Upload Widget Test Results
uses: actions/upload-artifact@v4
if: always()
with:
name: widget-test-results
path: build/test-results/widget/junit.xml
- name: Publish Widget Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: build/test-results/widget/junit.xml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
integration-test-ios:
# Run automatically on PRs, main, and tags; allow manual via workflow_dispatch
if: >
github.event_name == 'pull_request' ||
(github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))) ||
github.event_name == 'workflow_dispatch'
name: "Integration Tests iOS (Demo and Package)"
needs: [unit-test-package, widget-test-package, lint-demo]
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4
- uses: futureware-tech/simulator-action@v3
with:
model: "iPhone 16 Plus"
- uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
- name: Install package dependencies
run: flutter pub get
- name: Install demo dependencies
run: flutter pub get
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Install junitreport converter
run: |
dart pub global activate junitreport
echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
# - name: Run integration tests (iOS)
# working-directory: .
# run: make test-integration
- name: Cache Flutter build artifacts (iOS)
uses: actions/cache@v4
with:
path: |
build
.dart_tool
demo/build
demo/.dart_tool
~/Library/Developer/Xcode/DerivedData
key: flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-${{ github.sha }}
restore-keys: |
flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-
flutter-build-${{ github.job }}-${{ runner.os }}-
- name: Run integration tests (iOS) with coverage
working-directory: .
run: make test-integration
- name: Upload Integration Test Coverage (iOS)
uses: actions/upload-artifact@v4
with:
name: integration-ios-coverage
path: demo/coverage/integration/lcov.info
# - name: Upload Integration Test Console Logs (iOS)
# uses: actions/upload-artifact@v4
# if: always()
# with:
# name: integration-ios-console-logs
# path: demo/build/test-results/integration/console-output.log
- name: Upload Integration Test Results (iOS)
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-ios-results
path: demo/build/test-results/integration/junit.xml
- name: Publish Integration Test Results (iOS)
uses: EnricoMi/publish-unit-test-result-action/macos@v2
if: always()
with:
files: demo/build/test-results/integration/junit.xml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
integration-test-android:
# Run automatically on PRs, main, and tags; allow manual via workflow_dispatch
if: >
github.event_name == 'pull_request' ||
(github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))) ||
github.event_name == 'workflow_dispatch'
name: "Integration Tests Android (Demo and Package)"
runs-on: ubuntu-latest
needs: [unit-test-package, widget-test-package, lint-demo]
steps:
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v2
with:
distribution: "zulu"
java-version: "21"
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
- name: Setup Gradle cache
uses: gradle/actions/setup-gradle@v4
- name: Install package dependencies
run: flutter pub get
- name: Install demo dependencies
run: flutter pub get
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Install junitreport converter
run: |
dart pub global activate junitreport
echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-api-31
- name: Cache Flutter build artifacts (Android)
uses: actions/cache@v4
with:
path: |
build
.dart_tool
demo/build
demo/.dart_tool
key: flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-${{ github.sha }}
restore-keys: |
flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-
flutter-build-${{ github.job }}-${{ runner.os }}-
- name: Create AVD snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 31
target: google_apis
arch: x86_64
profile: pixel_7_pro
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."
- name: Run integration tests (Android)
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 31
target: google_apis
arch: x86_64
profile: pixel_7_pro
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: make test-integration
- name: Upload Integration Test Coverage (Android)
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-android-coverage
path: demo/coverage/integration/lcov.info
# - name: Upload Integration Test Console Logs (Android)
# uses: actions/upload-artifact@v4
# if: always()
# with:
# name: integration-android-console-logs
# path: demo/build/test-results/integration/console-output.log
- name: Upload Integration Test Results (Android)
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-android-results
path: demo/build/test-results/integration/junit.xml
- name: Publish Integration Test Results (Android)
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: demo/build/test-results/integration/junit.xml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# (cd $ {{ env.PATH_TO_APP }}; flutter test demo/integration_test/demo_test.dart)
integration-test-web:
name: "Integration Tests Web (Demo)"
# Run automatically on PRs, main, and tags; allow manual via workflow_dispatch
if: >
github.event_name == 'pull_request' ||
(github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))) ||
github.event_name == 'workflow_dispatch'
needs: [unit-test-package, widget-test-package, lint-demo]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
# - name: Install package dependencies
# run: flutter pub get
# - name: Install demo dependencies
# run: flutter pub get
# working-directory: ${{ env.PATH_TO_DEMO }}
# - name: Generate demo localizations
# run: flutter gen-l10n
# working-directory: ${{ env.PATH_TO_DEMO }}
# - name: Verify demo localizations
# run: |
# set -euo pipefail
# echo "Listing generated localization files"
# ls -la lib/l10n
# echo "Showing first 40 lines of app_localizations.dart"
# head -n 40 lib/l10n/app_localizations.dart || true
# echo "File checksum (helps detect stale cache)"
# sha256sum lib/l10n/app_localizations.dart
# working-directory: ${{ env.PATH_TO_DEMO }}
- name: Install Chrome & ChromeDriver
id: setup-chrome
uses: browser-actions/setup-chrome@v2
with:
chrome-version: 146
install-chromedriver: true
- name: Verify Chrome & ChromeDriver install
run: |
"${{ steps.setup-chrome.outputs.chrome-path }}" --version
"${{ steps.setup-chrome.outputs.chromedriver-path }}" --version
- name: Symlink Chrome for Testing as system Chrome
run: |
sudo mv /opt/google/chrome/chrome /opt/google/chrome/chrome.bak || true
sudo ln -sf "${{ steps.setup-chrome.outputs.chrome-path }}" /opt/google/chrome/chrome
- name: Cache Flutter build artifacts (Web Tests)
uses: actions/cache@v4
with:
path: |
build
.dart_tool
demo/build
demo/.dart_tool
key: flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-${{ github.sha }}
restore-keys: |
flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-
flutter-build-${{ github.job }}-${{ runner.os }}-
# - name: Install junitreport converter
# run: |
# dart pub global activate junitreport
# echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
# echo "Flutter version:"
# flutter --version
# echo "Configured devices:"
# flutter devices
# echo "Verifying localization artifacts before running tests"
# if [[ ! -f lib/l10n/app_localizations.dart ]]; then
# echo "lib/l10n/app_localizations.dart is missing"
# find lib -maxdepth 3 -type f -name 'app_localizations*.dart'
# exit 42
# fi
# ls -la lib/l10n
- name: Run demo integration test (Web)
run: |
set -o pipefail
chromedriver --port=4444 &
CHROMEDRIVER_PID=$!
trap "kill $CHROMEDRIVER_PID" EXIT
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/tests/demo_test.dart -d web-server --dart-define=CI=true --verbose-system-logs | tee output.log
status=$?
if [[ $status -ne 0 ]]; then
echo "flutter drive exited with status $status"
tail -n 200 output.log || true
exit $status
fi
if ! grep -q "All tests passed." output.log; then
echo "All tests did not pass. Please check the logs for more information."
exit 1
fi
working-directory: ${{ env.PATH_TO_DEMO }}
# - name: Upload Integration Test Coverage (Web)
# uses: actions/upload-artifact@v4
# with:
# name: integration-web-coverage
# path: demo/coverage/integration_web/lcov.info
# - name: Upload Integration Test Results (Web)
# uses: actions/upload-artifact@v4
# with:
# name: integration-web-results
# path: demo/build/test-results/integration_web/junit.xml
# - name: Publish Integration Test Results (Web)
# uses: EnricoMi/publish-unit-test-result-action@v2
# with:
# files: demo/build/test-results/integration_web/junit.xml
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
######################################################
# Release Package and deploy demo app to GitHub Pages
######################################################
build-web-demo:
name: "Build Web"
needs:
[integration-test-web, integration-test-android, integration-test-ios]
# Only build when main branch builds succeed
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "master"
flutter-version: "${{ env.FLUTTER_VERSION }}"
cache: true
cache-key: flutter-${{ runner.os }}-${{ env.FLUTTER_VERSION }}
pub-cache-key: flutter-pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Install package dependencies
run: flutter pub get
- name: Install demo dependencies
run: flutter pub get
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Cache Flutter build artifacts (Web Build)
if: always()
uses: actions/cache@v4
with:
path: |
build
.dart_tool
demo/build
demo/.dart_tool
key: flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-${{ github.sha }}
restore-keys: |
flutter-build-${{ github.job }}-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'demo/pubspec.lock') }}-
flutter-build-${{ github.job }}-${{ runner.os }}-
- name: Build app for web
run: flutter build web --base-href "${{ steps.pages.outputs.base_path }}/"
working-directory: ${{ env.PATH_TO_DEMO }}
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ${{ env.PATH_TO_DEMO }}/build/web
# deploy demo app to GitHub Pages after successful tests and build
deploy-web-demo:
name: Deploy Demo App to GitHub Pages
needs: [build-web-demo]
# Only deploy when main branch builds succeed
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
# Publish to pub.dev only on tag pushes after successful tests
publish-package:
name: Publish Package to pub.dev
needs: [
integration-test-web,
integration-test-android,
integration-test-ios,
] # Only run after lint, unit test, and widget test jobs succeed
# Only run on version tags
if: startsWith(github.ref, 'refs/tags/v')
permissions:
id-token: write # Required for authentication using OIDC
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
# with:
# working-directory: .