Add Firebase Test Lab integration for Android instrumented tests
Implements issue #132. Builds debug app APK + androidTest APK via Dagger, then runs them on Firebase Test Lab using the FIREBASE_TEST_LAB_SERVICE_ACCOUNT_KEY secret and FIREBASE_PROJECT_ID variable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
2e080dd4ed
commit
01cbf5b805
@@ -1,14 +1,13 @@
|
||||
# We switched to Dagger. Running the emulator tests in Dagger does not really work
|
||||
# We will use an external service for device testing.
|
||||
# TODO: Switch to device testing. First choose a service. Maybe codemagic.io
|
||||
name: Android Emulator Tests (Disabled)
|
||||
name: Android Firebase Test Lab
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Manual trigger only
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
integration-android:
|
||||
name: Android Emulator Integration Tests
|
||||
firebase-tests:
|
||||
name: Android Instrumented Tests (Firebase Test Lab)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
@@ -17,18 +16,25 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 50
|
||||
|
||||
- name: Install Android SDK
|
||||
- name: Install Dagger & Task
|
||||
run: |
|
||||
SDK="${ANDROID_HOME:-$HOME/Android/Sdk}"
|
||||
if [ ! -d "$SDK/platforms/android-34" ]; then
|
||||
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O /tmp/cmdtools.zip
|
||||
mkdir -p "$SDK/cmdline-tools"
|
||||
unzip -q /tmp/cmdtools.zip -d "$SDK/cmdline-tools"
|
||||
[ -d "$SDK/cmdline-tools/cmdline-tools" ] && mv "$SDK/cmdline-tools/cmdline-tools" "$SDK/cmdline-tools/latest"
|
||||
yes | "$SDK/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null 2>&1 || true
|
||||
"$SDK/cmdline-tools/latest/bin/sdkmanager" "emulator" "system-images;android-34;google_apis;x86_64"
|
||||
"$SDK/cmdline-tools/latest/bin/sdkmanager" "platform-tools" "build-tools;34.0.0" "platforms;android-34"
|
||||
fi
|
||||
mkdir -p $HOME/.local/bin
|
||||
curl -L https://dl.dagger.io/dagger/install.sh | BIN_DIR=$HOME/.local/bin sh
|
||||
curl -sL https://taskfile.dev/install.sh | sh -s -- -b $HOME/.local/bin
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
sudo apt-get update && sudo apt-get install -y stunnel4 netcat-openbsd
|
||||
|
||||
- name: Run Android Integration Tests
|
||||
run: task integration-android
|
||||
- name: Setup Dagger Remote Engine (via stunnel)
|
||||
env:
|
||||
DAGGER_STUNNEL_URL: ${{ secrets.DAGGER_STUNNEL_URL }}
|
||||
DAGGER_CA_CERT: ${{ secrets.DAGGER_CA_CERT }}
|
||||
DAGGER_CLIENT_CERT: ${{ secrets.DAGGER_CLIENT_CERT }}
|
||||
DAGGER_CLIENT_KEY: ${{ secrets.DAGGER_CLIENT_KEY }}
|
||||
run: scripts/setup_dagger_remote.sh
|
||||
|
||||
- name: Run Android Tests on Firebase Test Lab
|
||||
env:
|
||||
FIREBASE_TEST_LAB_SERVICE_ACCOUNT_KEY: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT_KEY }}
|
||||
FIREBASE_PROJECT_ID: ${{ vars.FIREBASE_PROJECT_ID }}
|
||||
DAGGER_NO_NAG: "1"
|
||||
run: task test-android-firebase
|
||||
|
||||
@@ -189,6 +189,16 @@ tasks:
|
||||
cmds:
|
||||
- dagger call --progress=plain -q -m ci --source=. test-sync-reliability
|
||||
|
||||
test-android-firebase:
|
||||
desc: Build Android debug APKs and run instrumented tests on Firebase Test Lab (via Dagger)
|
||||
preconditions:
|
||||
- sh: test -n "$FIREBASE_TEST_LAB_SERVICE_ACCOUNT_KEY"
|
||||
msg: "FIREBASE_TEST_LAB_SERVICE_ACCOUNT_KEY is not set"
|
||||
- sh: test -n "$FIREBASE_PROJECT_ID"
|
||||
msg: "FIREBASE_PROJECT_ID is not set"
|
||||
cmds:
|
||||
- dagger call --progress=plain -q -m ci --source=. test-android-firebase --service-account-key env:FIREBASE_TEST_LAB_SERVICE_ACCOUNT_KEY --project-id "$FIREBASE_PROJECT_ID"
|
||||
|
||||
ci-graph:
|
||||
desc: Print a Mermaid diagram of the CI pipeline — paste into mermaid.live or any Markdown renderer
|
||||
cmds:
|
||||
|
||||
+49
@@ -252,6 +252,13 @@ func (m *Ci) androidSrc() *dagger.Directory {
|
||||
})
|
||||
}
|
||||
|
||||
// firebaseSrc is the source subset for Firebase Test Lab builds (app + instrumented tests).
|
||||
func (m *Ci) firebaseSrc() *dagger.Directory {
|
||||
return m.Source.Filter(dagger.DirectoryFilterOpts{
|
||||
Include: []string{"lib/", "android/", "integration_test/", "assets/", "pubspec.yaml", "pubspec.lock", "drift_schemas/"},
|
||||
})
|
||||
}
|
||||
|
||||
// linuxSrc is the source subset for Linux builds and integration tests.
|
||||
func (m *Ci) linuxSrc() *dagger.Directory {
|
||||
return m.Source.Filter(dagger.DirectoryFilterOpts{
|
||||
@@ -606,6 +613,48 @@ func (m *Ci) DeployApk(
|
||||
Stdout(ctx)
|
||||
}
|
||||
|
||||
// BuildAndroidDebugApks builds the debug app APK and the androidTest APK needed for Firebase Test Lab.
|
||||
// Returns a flat directory with app-debug.apk and app-debug-androidTest.apk.
|
||||
func (m *Ci) BuildAndroidDebugApks() *dagger.Directory {
|
||||
built := m.setup(m.firebaseSrc()).
|
||||
WithExec([]string{"flutter", "build", "apk", "--debug", "--no-pub"}).
|
||||
WithWorkdir("/src/android").
|
||||
WithExec([]string{"./gradlew", "app:assembleAndroidTest"}).
|
||||
WithWorkdir("/src")
|
||||
|
||||
return dag.Directory().
|
||||
WithFile("app-debug.apk",
|
||||
built.File("build/app/outputs/flutter-apk/app-debug.apk")).
|
||||
WithFile("app-debug-androidTest.apk",
|
||||
built.File("android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk"))
|
||||
}
|
||||
|
||||
// TestAndroidFirebase builds Android APKs and runs instrumented tests on Firebase Test Lab.
|
||||
func (m *Ci) TestAndroidFirebase(
|
||||
ctx context.Context,
|
||||
serviceAccountKey *dagger.Secret,
|
||||
projectID string,
|
||||
) (string, error) {
|
||||
apks := m.BuildAndroidDebugApks()
|
||||
|
||||
return dag.Container().
|
||||
From("google/cloud-sdk:slim").
|
||||
WithDirectory("/apks", apks).
|
||||
WithSecretVariable("FIREBASE_SA_KEY", serviceAccountKey).
|
||||
WithEnvVariable("FIREBASE_PROJECT_ID", projectID).
|
||||
WithExec([]string{"/bin/bash", "-c",
|
||||
`echo "$FIREBASE_SA_KEY" > /tmp/key.json && \
|
||||
gcloud auth activate-service-account --key-file=/tmp/key.json && \
|
||||
rm /tmp/key.json && \
|
||||
gcloud config set project "$FIREBASE_PROJECT_ID" && \
|
||||
gcloud firebase test android run \
|
||||
--type instrumentation \
|
||||
--app /apks/app-debug.apk \
|
||||
--test /apks/app-debug-androidTest.apk \
|
||||
--device model=Pixel6,version=33,locale=en,orientation=portrait`}).
|
||||
Stdout(ctx)
|
||||
}
|
||||
|
||||
// BuildAndroidRelease builds the AAB with a fixed build-number so Dagger can cache it.
|
||||
// versionCode and signing are applied separately via StampAndroidVersionCode + SignAndroidBundle.
|
||||
func (m *Ci) BuildAndroidRelease() *dagger.File {
|
||||
|
||||
Reference in New Issue
Block a user