ci: add publish workflow (#227) #198
This file contains 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
# Copyright 2023 Google LLC | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# https://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
name: Run tests and build | |
on: | |
pull_request: | |
push: | |
branches: | |
- main | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
test-dart: | |
name: Run dart unit tests | |
timeout-minutes: 45 | |
runs-on: | |
labels: ubuntu-latest | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
name: Checkout code | |
- uses: actions/setup-java@v4 | |
name: Setup java | |
with: | |
distribution: "temurin" | |
java-version: "17" | |
cache: "gradle" | |
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
name: Setup flutter | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
- uses: bluefireteam/melos-action@6085791af7036f6366c9a4b9d55105c0ef9c6388 | |
with: | |
melos-version: "6.0.0" | |
- name: "Run flutter test" | |
run: melos run test:dart | |
test-android: | |
name: Run Android native unit tests | |
timeout-minutes: 45 | |
runs-on: | |
labels: ubuntu-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
- name: Setup java | |
uses: actions/setup-java@v4 | |
with: | |
distribution: "temurin" | |
java-version: "17" | |
cache: "gradle" | |
- name: Setup flutter | |
uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
- name: Setup melos | |
uses: bluefireteam/melos-action@6085791af7036f6366c9a4b9d55105c0ef9c6388 | |
with: | |
melos-version: "6.0.0" | |
- name: "Run Android native unit tests" | |
run: melos run test:android | |
- name: Upload build artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
include-hidden-files: true | |
path: example/build | |
retention-days: 1 | |
test-ios: | |
name: Run iOS native unit tests | |
timeout-minutes: 45 | |
runs-on: | |
labels: macos-latest-xlarge | |
env: | |
working_directory: "example" | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
- name: Setup flutter | |
uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
- name: Setup melos | |
uses: bluefireteam/melos-action@6085791af7036f6366c9a4b9d55105c0ef9c6388 | |
with: | |
melos-version: "6.0.0" | |
- name: Cache podfiles | |
uses: actions/cache@v4 | |
with: | |
path: "**/Pods" | |
key: ${{ runner.os }}-pods-${{ hashFiles('**/*.podspec') }} | |
restore-keys: | | |
${{ runner.os }}-pods- | |
- name: Select XCode 16.0 | |
run: sudo xcode-select -s '/Applications/Xcode_16.app/Contents/Developer' | |
- name: Generate necessary files with flutter build | |
working-directory: ${{ env.working_directory }} | |
run: flutter build ios --config-only | |
- name: "Run iOS native unit tests" | |
run: DEVICE='iPhone 16 Pro' melos run test:ios | |
- name: Upload build artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
include-hidden-files: true | |
path: example/build | |
retention-days: 1 | |
build-android: | |
name: Build Android | |
needs: [test-dart, test-android, test-ios] | |
if: contains(github.base_ref, 'main') | |
timeout-minutes: 45 | |
runs-on: | |
labels: ubuntu-latest | |
env: | |
MAPS_API_KEY: ${{ secrets.ACTIONS_API_KEY }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
- name: Setup java | |
uses: actions/setup-java@v4 | |
with: | |
distribution: "temurin" | |
java-version: "17" | |
cache: "gradle" | |
- name: Setup flutter | |
uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
- name: Setup melos | |
uses: bluefireteam/melos-action@6085791af7036f6366c9a4b9d55105c0ef9c6388 | |
with: | |
melos-version: "6.0.0" | |
- name: Download Build Artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
- name: "Run build for Android" | |
run: melos run flutter-build-android | |
- name: Upload build artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
include-hidden-files: true | |
path: example/build | |
retention-days: 1 | |
overwrite: true | |
build-ios: | |
name: Build iOS | |
needs: [test-dart, test-android, test-ios] | |
if: contains(github.base_ref, 'main') | |
timeout-minutes: 90 | |
runs-on: | |
labels: macos-latest-xlarge | |
env: | |
MAPS_API_KEY: ${{ secrets.ACTIONS_API_KEY }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
- name: Setup flutter | |
uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
architecture: x64 | |
- name: Setup melos | |
uses: bluefireteam/melos-action@6085791af7036f6366c9a4b9d55105c0ef9c6388 | |
with: | |
melos-version: "6.0.0" | |
- name: Cache podfiles | |
uses: actions/cache@v4 | |
with: | |
path: "**/Pods" | |
key: ${{ runner.os }}-pods-${{ hashFiles('**/*.podspec') }} | |
restore-keys: | | |
${{ runner.os }}-pods- | |
- name: Download Build Artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
- name: Select XCode 16.0 | |
run: sudo xcode-select -s '/Applications/Xcode_16.app/Contents/Developer' | |
- name: "Run build for iOS" | |
run: melos run flutter-build-ios | |
- name: Upload build artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
include-hidden-files: true | |
path: example/build | |
retention-days: 1 | |
overwrite: true | |
integration-test-android: | |
name: Run Android Integration Tests | |
needs: [build-android] | |
if: contains(github.base_ref, 'main') | |
timeout-minutes: 90 | |
runs-on: | |
labels: ubuntu-latest | |
env: | |
MAPS_API_KEY: ${{ secrets.ACTIONS_API_KEY }} | |
patrol_cli_version: "3.2.0" | |
working_directory: "example" | |
steps: | |
- name: Fail if workflow has no access to API key | |
if: ${{ env.MAPS_API_KEY == '' }} | |
run: | | |
echo "MAPS_API_KEY is not available or empty." | |
exit 1 | |
- name: Checkout code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
- name: Setup java | |
uses: actions/setup-java@v4 | |
with: | |
distribution: "temurin" | |
java-version: "17" | |
cache: "gradle" | |
- name: Enable KVM group perms | |
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: Setup Android SDK | |
uses: android-actions/setup-android@v3 | |
- name: AVD Cache | |
uses: actions/cache@v4 | |
id: avd-cache | |
with: | |
path: | | |
~/.android/avd/* | |
~/.android/adb* | |
key: avd | |
- name: Setup flutter | |
uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
- name: Download Build Artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
- name: Cache pub global packages | |
uses: actions/cache@v4 | |
with: | |
path: ~/.pub-cache | |
key: ${{ runner.os }}-pub-cache-${{ env.patrol_cli_version }} | |
- name: Install patrol_cli | |
run: flutter pub global activate patrol_cli ${{ env.patrol_cli_version }} | |
- name: Run flutter pub get | |
run: flutter pub get | |
- name: Create and start emulator | |
run: | | |
echo "List installed packages" | |
$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed | |
echo "Installing system image" | |
echo "y" | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "system-images;android-35;google_apis;x86_64" | |
echo "Creating AVD" | |
echo "no" | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/avdmanager create avd -n test_emulator -k "system-images;android-35;google_apis;x86_64" --force | |
echo "Starting emulator" | |
$ANDROID_SDK_ROOT/emulator/emulator -avd test_emulator -no-audio -no-boot-anim -no-window -no-snapshot & | |
adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done; input keyevent 82' | |
- name: Generate gradlew file with flutter build | |
working-directory: ${{ env.working_directory }} | |
run: flutter build apk --config-only | |
- name: Run integration tests | |
working-directory: ${{ env.working_directory }} | |
run: patrol test --verbose | |
- name: Upload test report | |
uses: actions/upload-artifact@v4 | |
if: ${{ always() }} | |
with: | |
name: android_integration_test_report | |
path: example/build/app/reports/androidTests/connected/ | |
retention-days: 5 | |
integration-test-ios: | |
name: Run iOS Integration Tests | |
needs: [build-ios] | |
if: contains(github.base_ref, 'main') | |
timeout-minutes: 90 | |
runs-on: | |
labels: macos-latest-xlarge | |
env: | |
MAPS_API_KEY: ${{ secrets.ACTIONS_API_KEY }} | |
patrol_cli_version: "3.2.0" | |
working_directory: "example" | |
steps: | |
- name: Fail if workflow has no access to API key | |
if: ${{ env.MAPS_API_KEY == '' }} | |
run: | | |
echo "MAPS_API_KEY is not available or empty." | |
exit 1 | |
- name: Checkout code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | |
- name: Setup flutter | |
uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 | |
with: | |
flutter-version: "3.22.x" | |
channel: "stable" | |
cache: true | |
- name: Select XCode 16.0 | |
run: sudo xcode-select -s '/Applications/Xcode_16.app/Contents/Developer' | |
- name: Start iOS simulator | |
run: | | |
SIMULATOR_NAME="iPhone 16 Pro" | |
# Find the UUID of the existing simulator by name | |
DEVICE_ID=$(xcrun simctl list devices | grep "$SIMULATOR_NAME (" | grep -Eo "\([A-F0-9-]+\)" | head -n 1 | tr -d "()") | |
if [ -z "$DEVICE_ID" ]; then | |
echo "Simulator $SIMULATOR_NAME not found." | |
exit 1 | |
else | |
echo "Found existing simulator: $SIMULATOR_NAME ($DEVICE_ID)" | |
echo "Erasing the simulator to ensure a clean state..." | |
xcrun simctl erase "$DEVICE_ID" | |
fi | |
echo "Booting the simulator..." | |
xcrun simctl boot "$DEVICE_ID" | |
# Save DEVICE_ID for later use | |
echo "DEVICE_ID=$DEVICE_ID" >> $GITHUB_ENV | |
- name: Download Build Artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ runner.os }}-build-artifact | |
- name: Cache podfiles | |
uses: actions/cache@v4 | |
with: | |
path: "**/Pods" | |
key: ${{ runner.os }}-pods-${{ hashFiles('**/*.podspec') }} | |
restore-keys: | | |
${{ runner.os }}-pods- | |
- name: Cache pub global packages | |
uses: actions/cache@v4 | |
with: | |
path: ~/.pub-cache | |
key: ${{ runner.os }}-pub-cache-${{ env.patrol_cli_version }} | |
- name: Install patrol_cli | |
run: flutter pub global activate patrol_cli ${{ env.patrol_cli_version }} | |
- name: Run flutter pub get | |
run: flutter pub get | |
- name: Make sure the simulator is booted | |
run: | | |
xcrun simctl bootstatus "$DEVICE_ID" || exit 1 | |
- name: Run Integration tests | |
id: tests_step | |
working-directory: ${{ env.working_directory }} | |
run: | | |
patrol test --dart-define=MAPS_API_KEY="$MAPS_API_KEY" --verbose -d "$DEVICE_ID" | |
- name: Upload test report | |
uses: actions/upload-artifact@v4 | |
if: ${{ always() }} | |
with: | |
name: ios_integration_test_report | |
path: example/build/ios_results_*.xcresult | |
retention-days: 5 |