Skip to content

Integration tests #11981

Integration tests

Integration tests #11981

name: Integration tests
on:
schedule:
- cron: "0 9 * * *" # 9am UTC = 1am PST / 2am PDT. for all testapps except firestore
- cron: "0 10 * * *" # 10am UTC = 2am PST / 3am PDT. for firestore test against release iOS/Android SDK
- cron: "0 11 * * *" # 11am UTC = 3am PST / 4am PDT. for firestore desktop test aginst tip-of-tree iOS repo
pull_request:
types: [ labeled, closed ]
workflow_dispatch:
inputs:
platforms:
description: 'CSV of Desktop, Android, iOS and/or tvOS'
default: 'Desktop,Android,iOS,tvOS'
required: true
apis:
description: 'CSV of apis to build and test'
default: 'analytics,app_check,auth,database,dynamic_links,firestore,functions,gma,installations,messaging,remote_config,storage'
required: true
operating_systems:
description: 'CSV of VMs to run on'
default: 'ubuntu-20.04,windows-latest,macos-13'
required: true
desktop_ssl_variants:
description: 'CSV of desktop SSL variants to use'
default: 'openssl,boringssl'
required: true
mobile_test_on:
description: 'Run mobile tests on real and/or virtual devices? (separated by commas)'
default: 'real,virtual'
required: true
use_expanded_matrix:
description: 'Use an expanded matrix? Note: above config will be ignored.'
default: '0'
required: true
test_packaged_sdk:
description: 'Optional: Packaging run # to build against?'
test_pull_request:
description: 'Optional: Pull request # to build and test? (With optional commit hash, separated by a colon. Specify the FULL hash.)'
firestore_dep_source:
description: 'Optional: Where to get firestore iOS SDK from: "RELEASED", "TIP" or "<git-commit> from firestore-ios-sdk"'
env:
triggerLabelPrefix: "tests-requested: "
triggerLabelFull: "tests-requested: full"
triggerLabelQuick: "tests-requested: quick"
pythonVersion: '3.8'
xcodeVersion: '15.1'
artifactRetentionDays: 2
GITHUB_TOKEN: ${{ github.token }}
# All self-hosted ARM Mac runners should have this label. Due to how
# our custom reporting works, it must be exactly two words separated
# by a hyphen. The first word must be "macos". The second word will
# be omitted from the summary log.
runnerLabelMacArm64: "macos-m1custom"
jobs:
check_and_prepare:
runs-on: ubuntu-20.04
outputs:
trigger: ${{ steps.set_outputs.outputs.trigger }}
github_ref: ${{ steps.set_outputs.outputs.github_ref }}
pr_number: ${{ steps.set_outputs.outputs.pr_number }}
matrix_platform: ${{ steps.matrix_config.outputs.matrix_platform }}
matrix_os: ${{ steps.matrix_config.outputs.matrix_os }}
matrix_arch_macos: ${{ steps.matrix_config.outputs.matrix_arch_macos }}
matrix_arch_windows_linux: ${{ steps.matrix_config.outputs.matrix_arch_windows_linux }}
matrix_arch_combined: ${{ steps.matrix_config.outputs.matrix_arch_combined }}
matrix_ssl: ${{ steps.matrix_config.outputs.matrix_ssl }}
apis: ${{ steps.matrix_config.outputs.apis }}
mobile_test_on: ${{ steps.matrix_config.outputs.mobile_test_on }}
android_device: ${{ steps.matrix_config.outputs.android_device }}
xcode_version: ${{ steps.matrix_config.outputs.xcode_version }}
ios_device: ${{ steps.matrix_config.outputs.ios_device }}
tvos_device: ${{ steps.matrix_config.outputs.tvos_device }}
# Copy the runner label here because matrix specifiers cannot see env.
runner_label_macos_arm64: ${{ env.runnerLabelMacArm64 }}
steps:
### Fail the workflow if the user does not have admin access to run the tests.
- name: Check if user has permission to trigger tests
uses: lannonbr/[email protected]
with:
permission: "admin"
### It sets "github_ref,trigger,pr_number,requested_tests" outputs to control the following jobs and steps
### trigger value: manual_trigger, scheduled_trigger, label_trigger, postsubmit_trigger
- id: set_outputs
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
if [[ "${{ github.event.inputs.test_pull_request }}" != "nightly-packaging" ]]; then
# Triggered manually
echo "trigger=manual_trigger" >> $GITHUB_OUTPUT
if [[ "${{ github.event.inputs.use_expanded_matrix }}" == "1" ]]; then
echo "requested_tests=expanded" >> $GITHUB_OUTPUT
fi
if [[ -z "${{github.event.inputs.test_pull_request}}" ]]; then
# test_pull_request not specified
echo "github_ref=$GITHUB_SHA" >> $GITHUB_OUTPUT
elif [[ "${{github.event.inputs.test_pull_request}}" == *:* ]]; then
# If specified as pr:commit_hash, split them.
echo "github_ref=$(echo ${{ github.event.inputs.test_pull_request }} | cut -d: -f2)" >> $GITHUB_OUTPUT
echo "pr_number=$(echo ${{ github.event.inputs.test_pull_request }} | cut -d: -f1)" >> $GITHUB_OUTPUT
else
# Just the PR specified, use refs/pull/<number>/merge as the ref.
echo "github_ref=refs/pull/${{github.event.inputs.test_pull_request}}/merge" >> $GITHUB_OUTPUT
echo "pr_number=${{ github.event.inputs.test_pull_request }}" >> $GITHUB_OUTPUT
fi
elif [[ "${{ github.event.inputs.test_pull_request }}" == "nightly-packaging" ]]; then
# Triggered by scheduled packaging SDK workflow.
echo "trigger=scheduled_trigger" >> $GITHUB_OUTPUT
echo "github_ref=$GITHUB_SHA" >> $GITHUB_OUTPUT
echo "requested_tests=expanded" >> $GITHUB_OUTPUT
fi
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "trigger=scheduled_trigger" >> $GITHUB_OUTPUT
echo "github_ref=$GITHUB_SHA" >> $GITHUB_OUTPUT
echo "requested_tests=expanded" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "github_ref=$GITHUB_SHA" >> $GITHUB_OUTPUT
if [[ "${{ github.event.action }}" == "labeled" && "${{ github.event.label.name }}" == "${{ env.triggerLabelPrefix }}"* ]]; then
echo "trigger=label_trigger" >> $GITHUB_OUTPUT
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
if [[ "${{ github.event.label.name }}" == "${{ env.triggerLabelQuick }}" ]]; then
echo "requested_tests=auto" >> $GITHUB_OUTPUT
else
echo "requested_tests=expanded" >> $GITHUB_OUTPUT
fi
elif [[ "${{ github.event.action }}" == "closed" && "${{ github.event.pull_request.merged == true}}" == "true" ]]; then
echo "trigger=postsubmit_trigger" >> $GITHUB_OUTPUT
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
echo "requested_tests=auto" >> $GITHUB_OUTPUT
fi
fi
### If it's not a defined trigger, cancel workflow
### e.g. Triggered by non-"test-request" label; triggered by not merged PR close event.
- name: Cancel workflow
if: ${{ !steps.set_outputs.outputs.trigger }}
uses: andymckay/[email protected]
- name: Wait for workflow cancellation
if: ${{ !steps.set_outputs.outputs.trigger }}
run: |
sleep 300
exit 1 # fail out if the cancellation above somehow failed.
- name: Cancel previous runs on the same PR
if: steps.set_outputs.outputs.trigger == 'label_trigger'
uses: styfle/[email protected]
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v3
with:
ref: ${{steps.set_outputs.outputs.github_ref}}
fetch-depth: 0
submodules: false
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: Install python deps
uses: nick-invision/retry@v2
with:
timeout_minutes: 1
max_attempts: 3
shell: bash
command: pip install -r scripts/gha/python_requirements.txt
- id: matrix_config
env:
HEAD_REF: ${{github.event.pull_request.head.ref}}
BASE_REF: ${{github.event.pull_request.base.ref}}
run: |
if [[ "${{ steps.set_outputs.outputs.requested_tests }}" == "expanded" ]]; then
TEST_MATRIX_PARAM=-e=1
echo "::warning ::Running on the expanded matrix"
elif [[ "${{ steps.set_outputs.outputs.requested_tests }}" == "minimal" ]]; then
TEST_MATRIX_PARAM=-m=1
echo "::warning ::Running on the minimal matrix"
elif [[ "${{ steps.set_outputs.outputs.requested_tests }}" == "auto" ]]; then
# auto-diff only apply when running in a PR.
# diff against the PR's base. "git merge-base main branch_name" will give the common ancestor of both branches.
MERGE_BASE=$(git merge-base "origin/${HEAD_REF}" "origin/${BASE_REF}" || true)
# If origin/<branch> is no longer valid, then just run all tests.
if [[ -n "${MERGE_BASE}" ]]; then
echo "::warning ::Auto-diff origin/${HEAD_REF}..${MERGE_BASE}"
git diff --name-only "origin/${HEAD_REF}..${MERGE_BASE}"
TEST_MATRIX_PARAM="--auto_diff origin/${HEAD_REF}..${MERGE_BASE}"
fi
fi
# To feed input into the job matrix, we first need to convert to a JSON
# list. Then we can use fromJson to define the field in the matrix for the tests job.
if [[ "${{ github.event.schedule }}" == "0 9 * * *" ]]; then
# at 1am PST/2am PDT. Running integration tests and generate test report for all testapps except firestore
apis="analytics,app_check,auth,database,dynamic_links,functions,gma,installations,messaging,remote_config,storage"
echo "::warning ::Running main nightly tests"
elif [[ "${{ github.event.schedule }}" == "0 10 * * *" || "${{ github.event.schedule }}" == "0 11 * * *" ]]; then
# at 2am PST/3am PDT and 3am PST/4am PDT. Running integration tests for firestore and generate test report.
echo "::warning ::Running Firestore nightly tests"
apis="firestore"
else
echo "::warning ::Running pull request tests"
apis=$( python scripts/gha/print_matrix_configuration.py -c -w integration_tests -k apis -o "${{github.event.inputs.apis}}" ${TEST_MATRIX_PARAM} )
fi
if [[ "${{ github.event.schedule }}" == "0 11 * * *" ]]; then
# at 3am PST/4am PDT. Running firestore desktop integration test aginst tip-of-tree ios repo
echo "::warning ::Running against Firestore tip-of-tree"
matrix_platform="Desktop"
matrix_os=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k os -o "ubuntu-20.04,macos-13")
else
matrix_platform=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k platform -o "${{github.event.inputs.platforms}}" --apis ${apis} )
matrix_os=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k os -o "${{github.event.inputs.operating_systems}}")
fi
echo "apis=${apis}" >> $GITHUB_OUTPUT
echo "matrix_platform=${matrix_platform}" >> $GITHUB_OUTPUT
echo "matrix_os=${matrix_os}" >> $GITHUB_OUTPUT
echo "matrix_arch_macos=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k architecture_macos)" >> $GITHUB_OUTPUT
echo "matrix_arch_windows_linux=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k architecture_windows_linux)" >> $GITHUB_OUTPUT
# Combine architecture_macos and architecture_windows_linux to get a list of all architectures for the build matrix.
matrix_arch_combined=`echo $( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k architecture_macos | sed 's/[]\[,]//g') \
$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k architecture_windows_linux | sed 's/[]\[,]//g' ) \
| sed 's/ /\n/g' | sort | uniq`
matrix_arch_combined_json=["$(echo ${matrix_arch_combined} | sed 's/ /,/g')"]
echo "matrix_arch_combined=${matrix_arch_combined_json}" >> $GITHUB_OUTPUT
# If building against a packaged SDK, consider it as using boringssl, as the packaged SDK uses boringssl under the hood.
# This avoids trying to install openssl on the system when compiling against the packaged SDK.
# As an added bonus, we ensure that the packaged SDK works even without openssl explicitly installed.
if [[ -n "${{ github.event.inputs.test_packaged_sdk }}" ]]; then
echo "::warning ::Downloading SDK package from previous run: https://github.com/${{github.repository}}/actions/runs/${{ github.event.inputs.test_packaged_sdk }}"
echo "matrix_ssl=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k ssl_lib -o boringssl )" >> $GITHUB_OUTPUT
else
echo "matrix_ssl=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k ssl_lib -o "${{github.event.inputs.desktop_ssl_variants}}" )" >> $GITHUB_OUTPUT
fi
mobile_test_on=$( python scripts/gha/print_matrix_configuration.py -c -w integration_tests -k mobile_test_on -o "${{github.event.inputs.mobile_test_on}}")
echo "mobile_test_on=${mobile_test_on}" >> $GITHUB_OUTPUT
echo "android_device=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k android_device -t ${mobile_test_on} )" >> $GITHUB_OUTPUT
echo "xcode_version=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k xcode_version)" >> $GITHUB_OUTPUT
echo "ios_device=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k ios_device -t ${mobile_test_on} )" >> $GITHUB_OUTPUT
echo "tvos_device=$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k tvos_device -t ${mobile_test_on} )" >> $GITHUB_OUTPUT
- name: Update PR label and comment
if: steps.set_outputs.outputs.pr_number
shell: bash
run: |
#Add the in-progress label and remove any previous labels.
python scripts/gha/it_workflow.py --stage start \
--token ${{github.token}} \
--issue_number ${{steps.set_outputs.outputs.pr_number}} \
--actor ${{github.actor}} \
--commit ${{steps.set_outputs.outputs.github_ref}} \
--run_id ${{github.run_id}}
build_desktop:
name: build-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
needs: [check_and_prepare]
runs-on: ${{ matrix.os }}
# Skip this if there is an empty matrix (which can happen if "auto" was set above).
# But check cancelled() && !failure() so it runs even if check_trigger was skipped.
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'Desktop') && needs.check_and_prepare.outputs.apis != '' && !cancelled() && !failure()
strategy:
fail-fast: false
matrix:
os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }}
arch: ${{ fromJson(needs.check_and_prepare.outputs.matrix_arch_combined) }}
ssl_variant: ${{ fromJson(needs.check_and_prepare.outputs.matrix_ssl) }}
# Because matrix_arch_combined combines Mac, Linux, and Windows, we need
# a few exclusions. These are standard exclusions used in several
# places.
exclude:
# Do not attempt to use arm64 on Windows or Linux.
- os: windows-latest
arch: arm64
- os: ubuntu-20.04
arch: arm64
# Do not attempt to use x86 on Mac.
- os: macos-13
arch: x86
# Until we support building openssl from source, we can't use the
# system's openssl when cross-compiling, except on Linux. Builds all
# happen on x64 machines, so arm64 and x86 are technically
# cross-compiling.
- os: windows-latest
ssl_variant: openssl
arch: x86
- os: macos-13
ssl_variant: openssl
arch: arm64
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
submodules: true
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: setup default Xcode version (macos)
if: ${{ runner.os == 'macOS' }}
run: |
sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
# Remove default Xcode version to prevent the wrong SDK from being used.
rm -rf /Applications/Xcode.app
- name: Install Desktop SDK & integration tests prerequisites
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 15
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p Desktop -a '${{ matrix.arch }}' -s '${{ matrix.ssl_variant }}'
- name: Add msbuild to PATH (Windows)
if: startsWith(matrix.os, 'windows')
uses: microsoft/[email protected]
- name: Cache vcpkg C++ dependencies
id: cache_vcpkg
uses: actions/cache@v3
with:
path: external/vcpkg/installed
key: dev-vcpkg-${{ env.VCPKG_TRIPLET }}-${{ hashFiles(format('{0}', env.VCPKG_RESPONSE_FILE)) }}-${{ hashFiles('.git/modules/external/vcpkg/HEAD') }}
- name: Fetch prebuilt packaged SDK from previous run
uses: dawidd6/action-download-artifact@v2
if: ${{ github.event.inputs.test_packaged_sdk != '' }}
with:
name: 'firebase_cpp_sdk.zip'
workflow: 'cpp-packaging.yml'
run_id: ${{ github.event.inputs.test_packaged_sdk }}
- name: Build integration tests
shell: bash
env:
CCACHE_DIR: ${{ github.workspace }}/ccache_dir
run: |
python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}"
declare -a additional_flags
if [[ -n "${{ github.event.inputs.test_packaged_sdk }}" ]]; then
# Building integration tests against a packaged SDK.
mkdir downloaded_sdk
unzip -q firebase_cpp_sdk.zip -d downloaded_sdk/
additional_flags+=(--packaged_sdk downloaded_sdk/firebase_cpp_sdk)
else
# Building integration tests against the SDK source.
#
# When building the SDK from source, the default SSL is openssl.
# To build using boringssl, a cmake flag must be added:
if [[ "${{ matrix.ssl_variant }}" == "boringssl" ]]; then
additional_flags+=(--cmake_flag=-DFIREBASE_USE_BORINGSSL=ON)
fi
fi
if [[ "${{ github.event.schedule }}" == "0 11 * * *" ]]; then
# at 3am PST/4am PDT. Running firestore desktop integration test aginst tip-of-tree ios repo
additional_flags+=(--cmake_flag=-DFIRESTORE_DEP_SOURCE=TIP)
elif [[ "${{ github.event.inputs.firestore_dep_source }}" ]]; then
additional_flags+=(--cmake_flag=-DFIRESTORE_DEP_SOURCE=${{ github.event.inputs.firestore_dep_source }})
fi
python scripts/gha/build_testapps.py --p Desktop \
--t ${{ needs.check_and_prepare.outputs.apis }} \
--output_directory "${{ github.workspace }}" \
--artifact_name "desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}" \
--noadd_timestamp \
--short_output_paths \
--gha_build \
--arch ${{ matrix.arch }} \
${additional_flags[*]}
- name: Upload Desktop Cmake
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: cmake-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
path: D:/a/firebase-cpp-sdk/firebase-cpp-sdk/ta/firestore/iti/CMakeFiles/
retention-days: 1
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
if [ ! -f build-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log.json ]; then
# No summary was created, make a placeholder one.
echo "__SUMMARY_MISSING__" > build-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log.json
fi
- name: Upload Desktop integration tests artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
path: testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload Desktop build results artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: log-artifact
path: build-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
pushd ${{env.GCS_UPLOAD_DIR}}
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize build results
if: ${{ !cancelled() }}
shell: bash
run: |
cat build-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
build_android:
name: build-android-${{ matrix.os }}
needs: [check_and_prepare]
runs-on: ${{ matrix.os }}
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'Android') && needs.check_and_prepare.outputs.apis != '' && !cancelled() && !failure()
strategy:
fail-fast: false
matrix:
os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
submodules: true
- name: Force Java 8 (macOS)
if: startsWith(matrix.os, 'macos')
shell: bash
run: echo "JAVA_HOME=${JAVA_HOME_8_X64}" >> $GITHUB_ENV
- name: Add msbuild to PATH (Windows)
if: startsWith(matrix.os, 'windows')
uses: microsoft/[email protected]
- name: Cache NDK
id: cache_ndk
uses: actions/cache@v3
with:
path: /tmp/android-ndk-r21e
key: android-ndk-${{ matrix.os }}-r21e
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: Install Android SDK & integration tests prerequisites
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 10
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p Android
- name: Fetch prebuilt packaged SDK from previous run
uses: dawidd6/action-download-artifact@v2
if: ${{ github.event.inputs.test_packaged_sdk != '' }}
with:
name: 'firebase_cpp_sdk.zip'
workflow: 'cpp-packaging.yml'
run_id: ${{ github.event.inputs.test_packaged_sdk }}
- name: Build integration tests
shell: bash
run: |
python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}"
declare -a additional_flags
if [[ -n "${{ github.event.inputs.test_packaged_sdk }}" ]]; then
# Building integration tests against a packaged SDK.
mkdir downloaded_sdk
cd downloaded_sdk
unzip -q ../firebase_cpp_sdk.zip
cd ..
additional_flags+=(--packaged_sdk downloaded_sdk/firebase_cpp_sdk)
fi
python scripts/gha/build_testapps.py --p Android \
--t ${{ needs.check_and_prepare.outputs.apis }} \
--output_directory "${{ github.workspace }}" \
--artifact_name "android-${{ matrix.os }}" \
--noadd_timestamp \
--short_output_paths \
--gha_build \
${additional_flags[*]}
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
if [ ! -f build-results-android-${{ matrix.os }}.log.json ]; then
echo "__SUMMARY_MISSING__" > build-results-android-${{ matrix.os }}.log.json
fi
- name: Upload Android integration tests artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: testapps-android-${{ matrix.os }}
path: testapps-android-${{ matrix.os }}
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload Android build results artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: log-artifact
path: build-results-android-${{ matrix.os }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize build results
if: ${{ !cancelled() }}
shell: bash
run: |
cat build-results-android-${{ matrix.os }}.log
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
build_ios:
name: build-ios-${{ matrix.os }}
needs: [check_and_prepare]
runs-on: ${{ matrix.os }}
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'iOS') && needs.check_and_prepare.outputs.apis != '' && !cancelled() && !failure()
strategy:
fail-fast: false
matrix:
os: [macos-13]
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
submodules: true
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: setup default Xcode version (macos)
if: ${{ runner.os == 'macOS' }}
run: |
sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
# Remove default Xcode version to prevent the wrong SDK from being used.
rm -rf /Applications/Xcode.app
- name: Install iOS SDK & integration tests prerequisites
uses: nick-invision/retry@v2
with:
timeout_minutes: 3
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p iOS
- name: Fetch prebuilt packaged SDK from previous run
uses: dawidd6/action-download-artifact@v2
if: ${{ github.event.inputs.test_packaged_sdk != '' }}
with:
name: 'firebase_cpp_sdk.zip'
workflow: 'cpp-packaging.yml'
run_id: ${{ github.event.inputs.test_packaged_sdk }}
- name: Build integration tests
shell: bash
run: |
python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}"
declare -a additional_flags
if [[ -n "${{ github.event.inputs.test_packaged_sdk }}" ]]; then
# Building integration tests against a packaged SDK.
mkdir downloaded_sdk
cd downloaded_sdk
unzip -q ../firebase_cpp_sdk.zip
cd ..
additional_flags+=(--packaged_sdk downloaded_sdk/firebase_cpp_sdk)
fi
python scripts/gha/build_testapps.py --p iOS \
--t ${{ needs.check_and_prepare.outputs.apis }} \
--output_directory "${{ github.workspace }}" \
--ios_sdk ${{ needs.check_and_prepare.outputs.mobile_test_on }} \
--artifact_name "ios-${{ matrix.os }}" \
--noadd_timestamp \
--short_output_paths \
--gha_build \
${additional_flags[*]}
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
if [ ! -f build-results-ios-${{ matrix.os }}.log.json ]; then
echo "__SUMMARY_MISSING__" > build-results-ios-${{ matrix.os }}.log.json
fi
- name: Upload iOS integration tests artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: testapps-ios-${{ matrix.os }}
path: testapps-ios-${{ matrix.os }}
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload iOS build results artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: log-artifact
path: build-results-ios-${{ matrix.os }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize build results
if: ${{ !cancelled() }}
shell: bash
run: |
cat build-results-ios-${{ matrix.os }}.log
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
build_tvos:
name: build-tvos-${{ matrix.os }}
needs: [check_and_prepare]
runs-on: ${{ matrix.os }}
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'tvOS') && needs.check_and_prepare.outputs.apis != '' && !cancelled() && !failure()
strategy:
fail-fast: false
matrix:
os: [macos-13]
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
submodules: true
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: setup default Xcode version (macos)
if: ${{ runner.os == 'macOS' }}
run: |
sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
# Remove default Xcode version to prevent the wrong SDK from being used.
rm -rf /Applications/Xcode.app
- name: Install tvOS SDK & integration tests prerequisites
uses: nick-invision/retry@v2
with:
timeout_minutes: 3
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p tvOS
- name: Fetch prebuilt packaged SDK from previous run
uses: dawidd6/action-download-artifact@v2
if: ${{ github.event.inputs.test_packaged_sdk != '' }}
with:
name: 'firebase_cpp_sdk.zip'
workflow: 'cpp-packaging.yml'
run_id: ${{ github.event.inputs.test_packaged_sdk }}
- name: Build integration tests
shell: bash
run: |
python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}"
declare -a additional_flags
if [[ -n "${{ github.event.inputs.test_packaged_sdk }}" ]]; then
# Building integration tests against a packaged SDK.
mkdir downloaded_sdk
cd downloaded_sdk
unzip -q ../firebase_cpp_sdk.zip
cd ..
additional_flags+=(--packaged_sdk downloaded_sdk/firebase_cpp_sdk)
fi
python scripts/gha/build_testapps.py --p tvOS \
--t ${{ needs.check_and_prepare.outputs.apis }} \
--output_directory "${{ github.workspace }}" \
--artifact_name "tvos-${{ matrix.os }}" \
--noadd_timestamp \
--short_output_paths \
--gha_build \
${additional_flags[*]}
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
if [ ! -f build-results-tvos-${{ matrix.os }}.log.json ]; then
echo "__SUMMARY_MISSING__" > build-results-tvos-${{ matrix.os }}.log.json
fi
- name: Upload tvOS integration tests artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: testapps-tvos-${{ matrix.os }}
path: testapps-tvos-${{ matrix.os }}
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload tvOS build results artifact
uses: actions/upload-artifact@v3
if: ${{ !cancelled() }}
with:
name: log-artifact
path: build-results-tvos-${{ matrix.os }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize build results
if: ${{ !cancelled() }}
shell: bash
run: |
cat build-results-tvos-${{ matrix.os }}.log
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
test_desktop:
name: test-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
needs: [check_and_prepare, build_desktop]
runs-on: ${{ matrix.os }}
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'Desktop') && needs.check_and_prepare.outputs.apis != '' && !cancelled()
strategy:
fail-fast: false
matrix:
os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }}
arch: ${{ fromJson(needs.check_and_prepare.outputs.matrix_arch_combined) }}
ssl_variant: ${{ fromJson(needs.check_and_prepare.outputs.matrix_ssl) }}
# Because matrix_arch_combined combines Mac, Linux, and Windows, we need
# a few exclusions. These are standard exclusions used in several
# places.
exclude:
# Do not attempt to use arm64 on Windows or Linux.
- os: windows-latest
arch: arm64
- os: ubuntu-20.04
arch: arm64
# Do not attempt to use x86 on Mac.
- os: macos-13
arch: x86
# Until we support building openssl from source, we can't use the
# system's openssl when cross-compiling, except on Linux. Builds all
# happen on x64 machines, so arm64 and x86 are technically
# cross-compiling.
- os: windows-latest
ssl_variant: openssl
arch: x86
# Custom for this matrix: MacOS GitHub-hosted runner cannot test arm64
# code. Exclude that scenario from running here; it will run in
# test_desktop_custom_runners.
- os: macos-13
arch: arm64
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Download Desktop integration tests artifact
uses: actions/download-artifact@v3
with:
path: testapps/testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
name: testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: setup default Xcode version (macos)
if: ${{ runner.os == 'macOS' }}
run: |
sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
# Remove default Xcode version to prevent the wrong SDK from being used.
rm -rf /Applications/Xcode.app
- name: Install prerequisites for testing
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 15
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p Desktop -t true -a '${{ matrix.arch }}' -s '${{ matrix.ssl_variant }}'
- name: Set up Node (18)
uses: actions/setup-node@v3
with:
node-version: 18.x
- name: Setup Firestore Emulator
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 5
max_attempts: 3
command: npm install firebase-tools
- name: Add firebase-tools to PATH
shell: bash
run: |
echo "$(npm root)" >> $GITHUB_PATH
echo "$(npm root)/.bin" >> $GITHUB_PATH
- name: Setup java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run Desktop integration tests
env:
USE_FIRESTORE_EMULATOR: true
shell: bash
run: |
if [[ "${{ needs.check_and_prepare.outputs.apis }}" == *"firestore"* ]]; then
firebase emulators:exec --only firestore --project demo-example 'python scripts/gha/desktop_tester.py --testapp_dir testapps --logfile_name "desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}"'
else
python scripts/gha/desktop_tester.py --testapp_dir testapps --logfile_name "desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}"
fi
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
# If testapps do not exist, then it's a build error not test error.
if [ -d "testapps/testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}" ] && [ ! -f testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log.json ]; then
mkdir -p testapps && echo "__SUMMARY_MISSING__" > testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log.json
fi
- name: Upload Desktop test results artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: log-artifact
path: testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize test results
if: ${{ !cancelled() }}
shell: bash
run: |
cat testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
# Run tests that depend on custom (self-hosted) runners.
# For now, this is only used for ARM Mac builds.
test_desktop_custom_runners:
name: test-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}-custom-runner
needs: [check_and_prepare, build_desktop]
runs-on: [self-hosted, firebase-cpp, '${{ matrix.runner_label }}']
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'Desktop') && contains(needs.check_and_prepare.outputs.matrix_arch_combined, 'arm64') && contains(needs.check_and_prepare.outputs.matrix_os, 'macos-13') && needs.check_and_prepare.outputs.apis != '' && !cancelled()
strategy:
fail-fast: false
matrix:
ssl_variant: ${{ fromJson(needs.check_and_prepare.outputs.matrix_ssl) }}
os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }}
arch: ${{ fromJson(needs.check_and_prepare.outputs.matrix_arch_combined) }}
runner_label: ['${{ needs.check_and_prepare.outputs.runner_label_macos_arm64 }}']
exclude:
# Don't run Linux or Windows tests on the Mac arm64 runner.
- os: ubuntu-20.04
runner_label: ${{ needs.check_and_prepare.outputs.runner_label_macos_arm64 }}
- os: windows-latest
runner_label: ${{ needs.check_and_prepare.outputs.runner_label_macos_arm64 }}
# Don't run x86 tests on any Mac runner.
- os: macos-13
arch: x86
# Don't run x64 tests on the Mac arm64 runner.
- os: macos-13
arch: x64
runner_label: ${{ needs.check_and_prepare.outputs.runner_label_macos_arm64 }}
# Until we support building openssl from source, we can't link to system
# openssl when cross-compiling, so exclude openssl from mac arm64 testing.
- os: macos-13
arch: arm64
ssl_variant: openssl
steps:
- name: Clean up previous run
shell: bash
run: |
echo "Cleaning up previous run"
rm -rf "${{ github.workspace }}"/*
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Download Desktop integration tests artifact
uses: actions/download-artifact@v3
with:
path: testapps
name: testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}
# Omit all of the prerequisites steps; we ensure that our self-hosted runners
# are configured with all prereqs already installed.
- name: Create keychain (macOS)
if: ${{ runner.os == 'macOS' }}
shell: bash
run: |
echo "Creating temporary keychain"
# Create a local keychain on Mac:
# Clean up previous temp keychain, if any.
security delete-keychain tmp-keychain 2> /dev/null || true
# Create temp keychain file and unlock it.
# (Avoid passing in -p on command line by using interactive mode.)
# Also set it to default settings so there is no unlock timeout.
security -i <<EOF
create-keychain -p ${{ secrets.TEST_SECRET }} tmp-keychain
set-keychain-settings tmp-keychain
unlock-keychain -p ${{ secrets.TEST_SECRET }} tmp-keychain
EOF
# Change the keychain list and default keychain to the temp keychain.
security list-keychains -d user -s tmp-keychain
security default-keychain -s tmp-keychain
- name: Restore google-services files
shell: bash
run: |
python scripts/gha/restore_secrets.py --passphrase_file=- --artifact testapps <<EOF
${{ secrets.TEST_SECRET }}
EOF
- name: Run Desktop integration tests on M1 Mac
if: ${{ matrix.os == 'macos-13' && matrix.arch == 'arm64' && matrix.runner_label == needs.check_and_prepare.outputs.runner_label_macos_arm64 }}
shell: bash
run: |
# This is an M1 Mac GitHub self-hosted runner.
# Use arch command to ensure that the app is running in the correct processor mode (arm64).
cmd_prefix='arch -arm64'
# If Firestore is included, use the emulator; otherwise just run the tests standalone.
if [[ "${{ needs.check_and_prepare.outputs.apis }}" == *"firestore"* ]]; then
# ARM Mac requires a firestore.json to specify the host as 127.0.0.1 rather than localhost.
# Otherwise the Firestore emulator cannot connect, probably because localhost is ipv6.
echo '{"emulators":{"firestore":{"port":"8080","host":"127.0.0.1"}}}' > firebase.json
echo "::warning ::Firestore emulator version: $(firebase --version)"
set -x
firebase emulators:exec --only firestore --project demo-example \
'python scripts/gha/desktop_tester.py --testapp_dir testapps --logfile_name "desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}" --cmd_prefix='"\"${cmd_prefix}\""
else
set -x
python scripts/gha/desktop_tester.py --testapp_dir testapps --logfile_name "desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}" --cmd_prefix="${cmd_prefix}"
fi
env:
USE_FIRESTORE_EMULATOR: true
- name: Delete keychain (macOS)
if: ${{ always() && runner.os == 'macOS' }}
shell: bash
run: |
# Remove the local keychain on Mac:
# Set back to the default login keychain.
security list-keychains -d user -s login.keychain
# Delete the temp keychain, if it exists.
security delete-keychain tmp-keychain || true
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
if [ ! -f testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch}}-${{ matrix.ssl_variant }}.log.json ]; then
mkdir -p testapps && echo "__SUMMARY_MISSING__" > testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch}}-${{ matrix.ssl_variant }}.log.json
fi
- name: Upload Desktop test results artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: log-artifact
path: testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize test results
if: ${{ !cancelled() }}
shell: bash
run: |
cat testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
- name: Clean up after this run
shell: bash
if: ${{ always() }}
run: |
echo "Cleaning up after this run"
rm -rf "${{ github.workspace }}"/*
test_android:
name: test-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}
needs: [check_and_prepare, build_android]
runs-on: ubuntu-20.04
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'Android') && needs.check_and_prepare.outputs.apis != '' && !cancelled()
strategy:
fail-fast: false
matrix:
build_os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }}
android_device: ${{ fromJson(needs.check_and_prepare.outputs.android_device) }}
test_type: ["gameloop"]
exclude:
- android_device: "android_target"
test_type: "uitest"
- android_device: "android_latest"
test_type: "uitest"
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Download Android integration tests artifact
uses: actions/download-artifact@v3
with:
path: testapps/testapps-android-${{ matrix.build_os }}
name: testapps-android-${{ matrix.build_os }}
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: Install prerequisites for testing
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 5
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p Android -t true
- name: Get Device Info
id: device-info
run: |
echo "device_type=$( python scripts/gha/print_matrix_configuration.py -k ${{ matrix.android_device }} -get_device_type)" >> $GITHUB_OUTPUT
echo "device=$( python scripts/gha/print_matrix_configuration.py -k ${{ matrix.android_device }} -get_ftl_device_list)" >> $GITHUB_OUTPUT
- name: Setup java 8 for test_simulator.py
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '8'
- name: Run Android integration tests on Emulator locally
timeout-minutes: 180
if: steps.device-info.outputs.device_type == 'virtual'
run: |
python scripts/gha/test_simulator.py --testapp_dir testapps \
--test_type "${{ matrix.test_type }}" \
--android_device "${{ matrix.android_device }}" \
--logfile_name "android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}" \
--ci
- id: ftl_test
if: steps.device-info.outputs.device_type == 'ftl'
uses: FirebaseExtended/github-actions/[email protected]
timeout-minutes: 240
with:
credentials_json: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_CREDENTIALS }}
testapp_dir: testapps
test_type: "game-loop"
test_devices: '${{ steps.device-info.outputs.device }}'
test_device_selection: random
max_attempts: 3
validator: ${GITHUB_WORKSPACE}/scripts/gha/integration_testing/ftl_gha_validator.py
additional_flags: '--client-details matrixLabel=android-${{ github.run_id }}-${{ matrix.build_os }}-${{ matrix.android_device }}'
- name: Read FTL Test Result
if: ${{ steps.device-info.outputs.device_type == 'ftl' && !cancelled() }}
shell: bash
run: |
python scripts/gha/read_ftl_test_result.py --test_result '${{ steps.ftl_test.outputs.test_summary }}' \
--output_path testapps/test-results-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}.log
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
# If testapps do not exist, then it's a build error not test error.
if [ -d "testapps/testapps-android-${{ matrix.build_os }}" ] && [ ! -f "testapps/test-results-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}.log.json" ]; then
mkdir -p testapps && echo "__SUMMARY_MISSING__" > "testapps/test-results-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}.log.json"
fi
- name: Upload Android test results artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: log-artifact
path: testapps/test-results-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload Android test video artifact
if: ${{ steps.device-info.outputs.device_type == 'virtual' && !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: mobile-simulator-test-video-artifact
path: testapps/video-*-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}.mp4
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload Android test logcat artifact
if: ${{ steps.device-info.outputs.device_type == 'virtual' && !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: mobile-simulator-test-logcat-artifact
path: testapps/logcat-*-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}.txt
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize test results
if: ${{ !cancelled() }}
shell: bash
run: |
cat "testapps/test-results-android-${{ matrix.build_os }}-${{ matrix.android_device }}-${{ matrix.test_type }}.log"
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
test_ios:
name: test-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}
needs: [check_and_prepare, build_ios]
runs-on: macos-13
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'iOS') && needs.check_and_prepare.outputs.apis != '' && !cancelled()
strategy:
fail-fast: false
matrix:
ios_device: ${{ fromJson(needs.check_and_prepare.outputs.ios_device) }}
test_type: ["gameloop"]
exclude:
- ios_device: "ios_min"
test_type: "uitest"
- ios_device: "ios_target"
test_type: "uitest"
- ios_device: "ios_latest"
test_type: "uitest"
build_os: [macos-13]
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Download iOS integration tests artifact
uses: actions/download-artifact@v3
with:
path: testapps/testapps-ios-${{ matrix.build_os }}
name: testapps-ios-${{ matrix.build_os }}
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: setup default Xcode version (macos)
if: ${{ runner.os == 'macOS' }}
run: |
sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
# Remove default Xcode version to prevent the wrong SDK from being used.
rm -rf /Applications/Xcode.app
- name: Install prerequisites for testing
uses: nick-invision/retry@v2
with:
timeout_minutes: 3
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p iOS -t true
- name: Device Info
id: device-info
run: |
echo "device_type=$( python scripts/gha/print_matrix_configuration.py -k ${{ matrix.ios_device }} -get_device_type)" >> $GITHUB_OUTPUT
echo "device=$( python scripts/gha/print_matrix_configuration.py -k ${{ matrix.ios_device }} -get_ftl_device_list)" >> $GITHUB_OUTPUT
- name: Set up Node (18)
uses: actions/setup-node@v3
with:
node-version: 18.x
- name: Setup java for Firestore emulator
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Firestore Emulator
if: steps.device-info.outputs.device_type == 'virtual' && contains(needs.check_and_prepare.outputs.apis, 'firestore')
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 5
max_attempts: 3
command: npm install firebase-tools
- name: Add firebase-tools to PATH
if: contains(needs.check_and_prepare.outputs.apis, 'firestore')
shell: bash
run: |
echo "$(npm root)" >> $GITHUB_PATH
echo "$(npm root)/.bin" >> $GITHUB_PATH
- name: Start Firestore Emulator
if: steps.device-info.outputs.device_type == 'virtual' && contains(needs.check_and_prepare.outputs.apis, 'firestore')
run: |
firebase emulators:start --only firestore --project demo-example &
- name: Create keychain (macOS Simulator)
if: ${{ runner.os == 'macOS' && steps.device-info.outputs.device_type == 'virtual'}}
shell: bash
run: |
echo "Creating temporary keychain"
# Create a local keychain on Mac:
# Clean up previous temp keychain, if any.
security delete-keychain tmp-keychain 2> /dev/null || true
# Create temp keychain file and unlock it.
# (Avoid passing in -p on command line by using interactive mode.)
# Also set it to default settings so there is no unlock timeout.
security -i <<EOF
create-keychain -p ${{ secrets.TEST_SECRET }} tmp-keychain
set-keychain-settings tmp-keychain
unlock-keychain -p ${{ secrets.TEST_SECRET }} tmp-keychain
EOF
# Change the keychain list and default keychain to the temp keychain.
security list-keychains -d user -s tmp-keychain
security default-keychain -s tmp-keychain
- name: Run iOS integration tests on Simulator locally
timeout-minutes: 180
if: steps.device-info.outputs.device_type == 'virtual'
run: |
python scripts/gha/test_simulator.py --testapp_dir testapps \
--test_type "${{ matrix.test_type }}" \
--ios_device "${{ matrix.ios_device }}" \
--logfile_name "ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}" \
--ci
- id: ftl_test
if: steps.device-info.outputs.device_type == 'ftl'
uses: FirebaseExtended/github-actions/[email protected]
timeout-minutes: 120
with:
credentials_json: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_CREDENTIALS }}
testapp_dir: testapps
test_type: "game-loop"
test_devices: '${{ steps.device-info.outputs.device }}'
test_device_selection: random
max_attempts: 3
validator: ${GITHUB_WORKSPACE}/scripts/gha/integration_testing/ftl_gha_validator.py
additional_flags: '--client-details matrixLabel=ios-${{ github.run_id }}-${{ matrix.build_os }}-${{ matrix.ios_device }}'
- name: Read FTL Test Result
if: ${{ steps.device-info.outputs.device_type == 'ftl' && !cancelled() }}
shell: bash
run: |
python scripts/gha/read_ftl_test_result.py --test_result '${{ steps.ftl_test.outputs.test_summary }}' \
--output_path testapps/test-results-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}.log
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
# If testapps do not exist, then it's a build error not test error.
if [ -d "testapps/testapps-ios-${{ matrix.build_os }}" ] && [ ! -f "testapps/test-results-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}.log.json" ]; then
mkdir -p testapps && echo "__SUMMARY_MISSING__" > "testapps/test-results-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}.log.json"
fi
- name: Delete keychain (macOS Simulator)
if: ${{ always() && runner.os == 'macOS' && steps.device-info.outputs.device_type == 'virtual' }}
shell: bash
run: |
# Remove the local keychain on Mac:
# Set back to the default login keychain.
security list-keychains -d user -s login.keychain
# Delete the temp keychain, if it exists.
security delete-keychain tmp-keychain || true
- name: Upload iOS test results artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: log-artifact
path: testapps/test-results-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload iOS test video artifact
if: ${{ steps.device-info.outputs.device_type == 'virtual' && !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: mobile-simulator-test-video-artifact
path: testapps/video-*-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}.mp4
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize test results
if: ${{ !cancelled() }}
shell: bash
run: |
cat "testapps/test-results-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}-${{ matrix.test_type }}.log"
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
test_tvos:
name: test-tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}
needs: [check_and_prepare, build_tvos]
runs-on: macos-13
if: contains(needs.check_and_prepare.outputs.matrix_platform, 'tvOS') && needs.check_and_prepare.outputs.apis != '' && !cancelled()
strategy:
fail-fast: false
matrix:
tvos_device: ${{ fromJson(needs.check_and_prepare.outputs.tvos_device) }}
build_os: [macos-13]
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Download tvOS integration tests artifact
uses: actions/download-artifact@v3
with:
path: testapps/testapps-tvos-${{ matrix.build_os }}
name: testapps-tvos-${{ matrix.build_os }}
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: setup default Xcode version (macos)
if: ${{ runner.os == 'macOS' }}
run: |
sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
# Remove default Xcode version to prevent the wrong SDK from being used.
rm -rf /Applications/Xcode.app
- name: Install prerequisites for testing
uses: nick-invision/retry@v2
with:
timeout_minutes: 3
max_attempts: 3
command: scripts/gha/install_test_workflow_prereqs.sh -p tvOS -t true
- name: Setup java for Firestore emulator
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Firestore Emulator
if: contains(needs.check_and_prepare.outputs.apis, 'firestore')
uses: nick-invision/retry@v2
with:
shell: bash
timeout_minutes: 5
max_attempts: 3
command: npm install firebase-tools
- name: Add firebase-tools to PATH
if: contains(needs.check_and_prepare.outputs.apis, 'firestore')
shell: bash
run: |
echo "$(npm root)" >> $GITHUB_PATH
echo "$(npm root)/.bin" >> $GITHUB_PATH
- name: Start Firestore Emulator
if: contains(needs.check_and_prepare.outputs.apis, 'firestore')
run: |
firebase emulators:start --only firestore --project demo-example &
- name: Create keychain (macOS Simulator)
if: ${{ runner.os == 'macOS' && steps.device-info.outputs.device_type == 'virtual'}}
shell: bash
run: |
echo "Creating temporary keychain"
# Create a local keychain on Mac:
# Clean up previous temp keychain, if any.
security delete-keychain tmp-keychain 2> /dev/null || true
# Create temp keychain file and unlock it.
# (Avoid passing in -p on command line by using interactive mode.)
# Also set it to default settings so there is no unlock timeout.
security -i <<EOF
create-keychain -p ${{ secrets.TEST_SECRET }} tmp-keychain
set-keychain-settings tmp-keychain
unlock-keychain -p ${{ secrets.TEST_SECRET }} tmp-keychain
EOF
# Change the keychain list and default keychain to the temp keychain.
security list-keychains -d user -s tmp-keychain
security default-keychain -s tmp-keychain
- name: Run tvOS integration tests on Simulator locally
timeout-minutes: 120
run: |
python scripts/gha/test_simulator.py --testapp_dir testapps \
--tvos_device "${{ matrix.tvos_device }}" \
--logfile_name "tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}" \
--ci
- name: Prepare results summary artifact
if: ${{ !cancelled() }}
shell: bash
run: |
# If testapps do not exist, then it's a build error not test error.
if [ -d "testapps/testapps-tvos-${{ matrix.build_os }}" ] && [ ! -f "testapps/test-results-tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}.log.json" ]; then
mkdir -p testapps && echo "__SUMMARY_MISSING__" > "testapps/test-results-tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}.log.json"
fi
- name: Delete keychain (macOS Simulator)
if: ${{ always() && runner.os == 'macOS' && steps.device-info.outputs.device_type == 'virtual' }}
shell: bash
run: |
# Remove the local keychain on Mac:
# Set back to the default login keychain.
security list-keychains -d user -s login.keychain
# Delete the temp keychain, if it exists.
security delete-keychain tmp-keychain || true
- name: Upload tvOS test results artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: log-artifact
path: testapps/test-results-tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}*
retention-days: ${{ env.artifactRetentionDays }}
- name: Upload tvOS test video artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: mobile-simulator-test-video-artifact
path: testapps/video-*-tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}.mp4
retention-days: ${{ env.artifactRetentionDays }}
- name: Download log artifacts
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage progress \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}}
- name: Summarize test results
if: ${{ !cancelled() }}
shell: bash
run: |
cat "testapps/test-results-tvos-${{ matrix.build_os }}-${{ matrix.tvos_device }}.log"
if [[ "${{ job.status }}" != "success" ]]; then
exit 1
fi
summarize_results:
name: "summarize-results"
needs: [check_and_prepare, test_desktop, test_desktop_custom_runners, test_android, test_ios, test_tvos]
runs-on: ubuntu-20.04
if: ${{ !cancelled() }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: Install python deps
run: pip install -r scripts/gha/python_requirements.txt
- name: Download log artifacts
uses: actions/download-artifact@v3
with:
path: test_results
name: log-artifact
# Use a different token to remove the "in-progress" label,
# to allow the removal to trigger the "Check Labels" workflow.
- name: Generate token for GitHub API
uses: tibdex/github-app-token@v1
id: generate-token
with:
app_id: ${{ secrets.WORKFLOW_TRIGGER_APP_ID }}
private_key: ${{ secrets.WORKFLOW_TRIGGER_APP_PRIVATE_KEY }}
- name: Update PR label and comment
if: ${{ needs.check_and_prepare.outputs.pr_number }}
shell: bash
run: |
python scripts/gha/it_workflow.py --stage end \
--token ${{github.token}} \
--issue_number ${{needs.check_and_prepare.outputs.pr_number}}\
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}} \
--new_token ${{steps.generate-token.outputs.token}}
- name: Update Daily Report
if: needs.check_and_prepare.outputs.trigger == 'scheduled_trigger'
shell: bash
run: |
if [[ "${{ github.event.inputs.test_pull_request }}" == "nightly-packaging" ]]; then
additional_flags=(--build_against sdk)
else
if [[ "${{ github.event.schedule }}" == "0 11 * * *" ]]; then
# at 3am PST/4am PDT. Running firestore desktop integration test aginst tip-of-tree ios repo
additional_flags=(--build_against tip)
else
additional_flags=(--build_against repo)
fi
fi
if [[ "${{ needs.check_and_prepare.outputs.apis }}" == "firestore" ]]; then
additional_flags+=(--build_apis firestore)
else
additional_flags+=(--build_apis all_except_firestore)
fi
python scripts/gha/it_workflow.py --stage report \
--token ${{github.token}} \
--actor ${{github.actor}} \
--commit ${{needs.check_and_prepare.outputs.github_ref}} \
--run_id ${{github.run_id}} \
${additional_flags[*]}
- name: Summarize results into GitHub log
run: python scripts/gha/summarize_test_results.py --dir test_results --github_log
attempt_retry:
name: "attempt-retry"
needs: [check_and_prepare, summarize_results]
runs-on: ubuntu-20.04
if: ${{ failure() && needs.check_and_prepare.outputs.trigger == 'scheduled_trigger' }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{needs.check_and_prepare.outputs.github_ref}}
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: ${{ env.pythonVersion }}
- name: Install python deps
run: pip install -r scripts/gha/python_requirements.txt
# The default token can't run workflows, so get an alternate token.
- name: Generate token for GitHub API
uses: tibdex/github-app-token@v1
id: generate-token
with:
app_id: ${{ secrets.WORKFLOW_TRIGGER_APP_ID }}
private_key: ${{ secrets.WORKFLOW_TRIGGER_APP_PRIVATE_KEY }}
- name: Retry failed tests
run: |
echo "::warning ::Attempting to retry failed tests"
python scripts/gha/trigger_workflow.py -t ${{ steps.generate-token.outputs.token }} \
-w retry-test-failures.yml \
-p run_id ${{ github.run_id }} \
-s 10 \
-A