Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 245 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,219 @@ jobs:
name: release
command: bundle exec fastlane github_release

run-maestro-e2e-tests-ios:
macos:
xcode: 26.3.0
resource_class: m4pro.medium
steps:
- checkout
- install-bundle-dependencies
- run:
name: Install Rosetta 2
command: softwareupdate --install-rosetta --agree-to-license || true
- run:
name: Install Java for Maestro
command: |
brew install openjdk@17
sudo ln -sfn "$(brew --prefix openjdk@17)/libexec/openjdk.jdk" /Library/Java/JavaVirtualMachines/openjdk-17.jdk
echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 17)' >> "$BASH_ENV"
- revenuecat/install-maestro
- run:
name: Install Unity Hub and Editor
command: |
brew install --cask unity-hub
/Applications/Unity\ Hub.app/Contents/MacOS/Unity\ Hub -- --headless install \
--version 6000.2.6f2 \
--changeset 4a4dcaec6541 \
-a arm64 \
--module ios
echo "Verifying iOS module installation..."
if [ ! -d "/Applications/Unity/Hub/Editor/6000.2.6f2/PlaybackEngines/iOSSupport" ]; then
echo "iOS module not found, installing separately..."
/Applications/Unity\ Hub.app/Contents/MacOS/Unity\ Hub -- --headless install-modules \
--version 6000.2.6f2 \
-m ios
fi
ls -la /Applications/Unity/Hub/Editor/6000.2.6f2/PlaybackEngines/ || echo "No PlaybackEngines dir"
no_output_timeout: 30m
- run:
name: Clear quarantine attributes from Unity
command: |
sudo xattr -cr /Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app || true
sudo xattr -cr "/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/Frameworks/UnityLicensingClient.app" || true
sudo spctl --master-disable 2>/dev/null || true
- run:
name: Activate Unity License
command: |
rm -f "/Library/Application Support/Unity/Unity_lic.ulf" 2>/dev/null || true
rm -rf ~/Library/Unity/licenses 2>/dev/null || true
rm -rf "/tmp/Unity.Licensing.Client" 2>/dev/null || true
mkdir -p "/Library/Application Support/Unity" 2>/dev/null || true

activated=false
for i in 1 2 3 4 5; do
pkill -9 -f "Unity.Licensing.Client" 2>/dev/null || true
pkill -9 -f "Unity " 2>/dev/null || true
sleep 5

echo "=== License activation attempt $i ==="
/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/MacOS/Unity \
-batchmode -nographics \
-serial "$UNITY_SERIAL" \
-username "$UNITY_EMAIL" \
-password "$UNITY_PASSWORD" \
-logFile - \
-quit &
UNITY_PID=$!
( sleep 120 && kill -9 $UNITY_PID 2>/dev/null ) &
WATCHDOG_PID=$!
if wait $UNITY_PID 2>/dev/null; then
kill $WATCHDOG_PID 2>/dev/null || true
activated=true
break
fi
kill $WATCHDOG_PID 2>/dev/null || true

echo "Attempt $i failed, cleaning up and retrying in 60s..."
pkill -9 -f "Unity.Licensing.Client" 2>/dev/null || true
pkill -9 -f "Unity " 2>/dev/null || true
rm -f "/Library/Application Support/Unity/Unity_lic.ulf" 2>/dev/null || true
sleep 60
done
if [ "$activated" = false ]; then
echo "All license activation attempts failed"
ls -la "/Library/Application Support/Unity/" 2>/dev/null || true
exit 1
fi
echo "License activated successfully"
ls -la "/Library/Application Support/Unity/" 2>/dev/null || true
no_output_timeout: 15m
- run:
name: Boot iOS Simulator
command: |
xcrun simctl boot "iPhone 17" || true
xcrun simctl bootstatus "iPhone 17" -b
- run:
name: Run Maestro E2E Tests (iOS)
command: bundle exec fastlane run_maestro_e2e_tests_ios
no_output_timeout: 30m
- store_test_results:
path: fastlane/test_output
- store_artifacts:
path: fastlane/test_output
- run:
name: Return Unity License
command: |
/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/MacOS/Unity \
-batchmode -quit -nographics \
-returnlicense \
-logFile - || true
when: always

run-maestro-e2e-tests-android:
macos:
xcode: 26.3.0
resource_class: m4pro.medium
steps:
- checkout
- install-bundle-dependencies
- run:
name: Install Rosetta 2
command: softwareupdate --install-rosetta --agree-to-license || true
- run:
name: Install Java for Maestro
command: |
brew install openjdk@17
sudo ln -sfn "$(brew --prefix openjdk@17)/libexec/openjdk.jdk" /Library/Java/JavaVirtualMachines/openjdk-17.jdk
echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 17)' >> "$BASH_ENV"
- revenuecat/install-maestro
- run:
name: Install Android SDK
command: |
brew install --cask android-commandlinetools
yes | sdkmanager --licenses || true
sdkmanager "platform-tools" "emulator" "system-images;android-34;google_apis;arm64-v8a"
- run:
name: Install Unity Hub and Editor
command: |
brew install --cask unity-hub
/Applications/Unity\ Hub.app/Contents/MacOS/Unity\ Hub -- --headless install \
--version 6000.2.6f2 \
--changeset 4a4dcaec6541 \
-a arm64 \
--module android
echo "Verifying Android module installation..."
ls -la /Applications/Unity/Hub/Editor/6000.2.6f2/PlaybackEngines/ || echo "No PlaybackEngines dir"
no_output_timeout: 60m
- run:
name: Clear quarantine attributes from Unity
command: |
sudo xattr -cr /Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app || true
sudo xattr -cr "/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/Frameworks/UnityLicensingClient.app" || true
sudo spctl --master-disable 2>/dev/null || true
- run:
name: Activate Unity License
command: |
rm -f "/Library/Application Support/Unity/Unity_lic.ulf" 2>/dev/null || true
rm -rf ~/Library/Unity/licenses 2>/dev/null || true
rm -rf "/tmp/Unity.Licensing.Client" 2>/dev/null || true
mkdir -p "/Library/Application Support/Unity" 2>/dev/null || true

activated=false
for i in 1 2 3 4 5; do
pkill -9 -f "Unity.Licensing.Client" 2>/dev/null || true
pkill -9 -f "Unity " 2>/dev/null || true
sleep 5

echo "=== License activation attempt $i ==="
/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/MacOS/Unity \
-batchmode -nographics \
-serial "$UNITY_SERIAL" \
-username "$UNITY_EMAIL" \
-password "$UNITY_PASSWORD" \
-logFile - \
-quit &
UNITY_PID=$!
( sleep 120 && kill -9 $UNITY_PID 2>/dev/null ) &
WATCHDOG_PID=$!
if wait $UNITY_PID 2>/dev/null; then
kill $WATCHDOG_PID 2>/dev/null || true
activated=true
break
fi
kill $WATCHDOG_PID 2>/dev/null || true

echo "Attempt $i failed, cleaning up and retrying in 60s..."
pkill -9 -f "Unity.Licensing.Client" 2>/dev/null || true
pkill -9 -f "Unity " 2>/dev/null || true
rm -f "/Library/Application Support/Unity/Unity_lic.ulf" 2>/dev/null || true
sleep 60
done
if [ "$activated" = false ]; then
echo "All license activation attempts failed"
ls -la "/Library/Application Support/Unity/" 2>/dev/null || true
exit 1
fi
echo "License activated successfully"
ls -la "/Library/Application Support/Unity/" 2>/dev/null || true
no_output_timeout: 15m
- run:
name: Run Maestro E2E Tests (Android)
command: bundle exec fastlane run_maestro_e2e_tests_android
no_output_timeout: 30m
- store_test_results:
path: fastlane/test_output
- store_artifacts:
path: fastlane/test_output
- run:
name: Return Unity License
command: |
/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/MacOS/Unity \
-batchmode -quit -nographics \
-returnlicense \
-logFile - || true
when: always

update-hybrid-common-versions:
description: "Creates a PR updating purchases-hybrid-common to latest release"
docker:
Expand Down Expand Up @@ -468,6 +681,16 @@ workflows:
- archive-ios:
requires:
- build-integration-tests-ios
- run-maestro-e2e-tests-ios:
context:
- maestro-e2e-tests
- e2e-tests
- unity
- run-maestro-e2e-tests-android:
context:
- maestro-e2e-tests
- e2e-tests
- unity
- hold:
type: approval
requires:
Expand Down Expand Up @@ -516,6 +739,28 @@ workflows:
- revenuecat/automatic-bump:
ruby_version: "3.2.0"

maestro-e2e-tests-ios:
when:
or:
- equal: ["maestro_e2e_tests", << pipeline.schedule.name >>]
jobs:
- run-maestro-e2e-tests-ios:
context:
- maestro-e2e-tests
- e2e-tests
- unity

maestro-e2e-tests-android:
when:
or:
- equal: ["maestro_e2e_tests", << pipeline.schedule.name >>]
jobs:
- run-maestro-e2e-tests-android:
context:
- maestro-e2e-tests
- e2e-tests
- unity

update-hybrid-common-versions:
when:
equal: [ upgrade-hybrid-common, << pipeline.parameters.action >> ]
Expand Down
86 changes: 86 additions & 0 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,92 @@ lane :update_hybrid_common do |options|
)
end

desc "Run maestro E2E tests on iOS"
lane :run_maestro_e2e_tests_ios do
UI.user_error!("RC_E2E_TEST_API_KEY_PRODUCTION_TEST_STORE is not set") if ENV["RC_E2E_TEST_API_KEY_PRODUCTION_TEST_STORE"].to_s.empty?
project_path = "../e2e-tests/MaestroTestApp"
xcode_project_path = "#{project_path}/build/ios"
derived_data_path = "#{project_path}/build/xcode"

sh("sed -i '' 's/MAESTRO_TESTS_REVENUECAT_API_KEY/'\"$RC_E2E_TEST_API_KEY_PRODUCTION_TEST_STORE\"'/g' #{project_path}/Assets/Scripts/MaestroTestApp.cs")

unity_path = ENV['UNITY_PATH'] || '/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/MacOS/Unity'

sh(
"#{unity_path}",
"-batchmode",
"-quit",
"-projectPath", project_path,
"-executeMethod", "SceneSetup.SetupScene",
"-nographics",
"-logFile", "-"
)

sh(
"#{unity_path}",
"-batchmode",
"-quit",
"-projectPath", project_path,
"-buildTarget", "iOS",
"-executeMethod", "BuildScript.BuildIOS",
"-nographics",
"-logFile", "-"
)

sh(
"xcodebuild",
"-project", "#{xcode_project_path}/Unity-iPhone.xcodeproj",
"-scheme", "Unity-iPhone",
"-configuration", "Debug",
"-sdk", "iphonesimulator",
"-destination", "platform=iOS Simulator,name=iPhone 17",
"-derivedDataPath", derived_data_path
)

app_path = "#{derived_data_path}/Build/Products/Debug-iphonesimulator/MaestroTestApp.app"
sh("xcrun simctl install booted '#{app_path}'")

sh("mkdir -p test_output")
sh("maestro test --format junit --output test_output/report.xml --test-output-dir test_output ../e2e-tests/maestro/")
end

desc "Run maestro E2E tests on Android"
lane :run_maestro_e2e_tests_android do
UI.user_error!("RC_E2E_TEST_API_KEY_PRODUCTION_TEST_STORE is not set") if ENV["RC_E2E_TEST_API_KEY_PRODUCTION_TEST_STORE"].to_s.empty?
project_path = "../e2e-tests/MaestroTestApp"
apk_path = "#{project_path}/build/android/MaestroTestApp.apk"

sh("sed -i 's/MAESTRO_TESTS_REVENUECAT_API_KEY/'\"$RC_E2E_TEST_API_KEY_PRODUCTION_TEST_STORE\"'/g' #{project_path}/Assets/Scripts/MaestroTestApp.cs")

unity_path = ENV['UNITY_PATH'] || '/Applications/Unity/Hub/Editor/6000.2.6f2/Unity.app/Contents/MacOS/Unity'

sh(
"#{unity_path}",
"-batchmode",
"-quit",
"-projectPath", project_path,
"-executeMethod", "SceneSetup.SetupScene",
"-nographics",
"-logFile", "-"
)

sh(
"#{unity_path}",
"-batchmode",
"-quit",
"-projectPath", project_path,
"-buildTarget", "Android",
"-executeMethod", "BuildScript.BuildAndroid",
"-nographics",
"-logFile", "-"
)

sh("adb install '#{apk_path}'")

sh("mkdir -p test_output")
sh("maestro test --format junit --output test_output/report.xml --test-output-dir test_output ../e2e-tests/maestro/")
end

desc "Tag current branch with current version number"
lane :tag_current_branch do |options|
version_number = current_version_number
Expand Down