diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index f0b3bf8c71..31972cf325 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -13,6 +13,7 @@ on: env: CCACHE_DIR: ${{ github.workspace }}/ccache_dir GITHUB_TOKEN: ${{ github.token }} + xcodeVersion: "12.4" # Only affects Mac runners, and only for prerequisites. jobs: prepare_matrix: @@ -46,6 +47,10 @@ jobs: architecture: ${{ fromJson(needs.prepare_matrix.outputs.matrix_architecture) }} python_version: ${{ fromJson(needs.prepare_matrix.outputs.matrix_python_version) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer + - name: Store git credentials for all git commands # Forces all git commands to use authenticated https, to prevent throttling. shell: bash diff --git a/.github/workflows/cpp-packaging.yml b/.github/workflows/cpp-packaging.yml index 45e1228657..822278125f 100644 --- a/.github/workflows/cpp-packaging.yml +++ b/.github/workflows/cpp-packaging.yml @@ -32,9 +32,9 @@ env: demumbleVer: "1.1.0" # Use SHA256 for hashing files. hashCommand: "sha256sum" - # Xcode version 12.2 is the version we build the SDK with. + # Xcode version 12.4 is the version we build the SDK with. # Our MacOS runners will use the version in /Applications/Xcode_${xcodeVersion}.app - xcodeVersion: "12.2" + xcodeVersion: "12.4" # LLVM version with ARM MachO support has no version number yet. llvmVer: "5f187f0afaad33013ba03454c4749d99b1362534" GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml index 291ab1cac2..6502d5c0db 100644 --- a/.github/workflows/desktop.yml +++ b/.github/workflows/desktop.yml @@ -74,9 +74,13 @@ jobs: architecture: "x86" # Xcode excludes -- allow only one on osx and linux - os: ubuntu-latest - xcode_version: "12.4" + xcode_version: "11.7" - os: windows-latest - xcode_version: "12.4" + xcode_version: "11.7" + - os: ubuntu-latest + xcode_version: "12.5.1" + - os: windows-latest + xcode_version: "12.5.1" # arm64 is only for macos - os: ubuntu-latest architecture: "arm64" diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index eaaf4441f4..60ebc97529 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -62,6 +62,7 @@ jobs: 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 }} steps: @@ -144,7 +145,12 @@ jobs: with: python-version: ${{ env.pythonVersion }} - name: Install python deps - run: pip install -r scripts/gha/requirements.txt + uses: nick-invision/retry@v2 + with: + timeout_minutes: 1 + max_attempts: 3 + shell: bash + command: pip install -r scripts/gha/requirements.txt - id: matrix_config run: | if [[ "${{ steps.set_outputs.outputs.requested_tests }}" == "expanded" ]]; then @@ -182,6 +188,7 @@ jobs: 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 "::set-output name=mobile_test_on::${mobile_test_on}" echo "::set-output name=android_device::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k android_device -t ${mobile_test_on} )" + echo "::set-output name=xcode_version::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k xcode_version)" echo "::set-output name=ios_device::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k ios_device -t ${mobile_test_on} )" echo "::set-output name=tvos_device::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k tvos_device -t ${mobile_test_on} )" - name: Update PR label and comment @@ -208,6 +215,9 @@ jobs: os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }} ssl_variant: ${{ fromJson(needs.check_and_prepare.outputs.matrix_ssl) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -255,30 +265,40 @@ jobs: # homebrew. This prevents errors arising from the shut down of # binutils, used by older version of homebrew for hosting packages. brew update - - name: Install SDK Desktop prerequisites - run: | - python scripts/gha/install_prereqs_desktop.py - - name: Prepare for integration tests - run: | - pip install -r scripts/gha/requirements.txt - python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" + - name: Install Desktop SDK & integration tests prerequisites + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + max_attempts: 3 + command: | + python scripts/gha/install_prereqs_desktop.py + pip install -r scripts/gha/requirements.txt + python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" - name: Install OpenSSL (Windows) - if: matrix.ssl_variant == 'openssl' && - startsWith(matrix.os, 'windows') - run: | - choco install openssl -r + if: matrix.ssl_variant == 'openssl' && startsWith(matrix.os, 'windows') + uses: nick-invision/retry@v2 + with: + timeout_minutes: 4 + max_attempts: 3 + shell: bash + command: choco install openssl -r - name: Install OpenSSL (macOS) - if: matrix.ssl_variant == 'openssl' && - startsWith(matrix.os, 'macos') - run: | - brew install openssl - # brew won't overwrite MacOS system default OpenSSL, so force it here. - echo "OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" >> $GITHUB_ENV + if: matrix.ssl_variant == 'openssl' && startsWith(matrix.os, 'macos') + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + max_attempts: 3 + command: | + brew install openssl + # brew won't overwrite MacOS system default OpenSSL, so force it here. + echo "OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" >> $GITHUB_ENV - name: Install OpenSSL (Linux) - if: matrix.ssl_variant == 'openssl' && - startsWith(matrix.os, 'ubuntu') - run: | - sudo apt install openssl + if: matrix.ssl_variant == 'openssl' && startsWith(matrix.os, 'ubuntu') + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + max_attempts: 3 + command: sudo apt install openssl - name: Fetch prebuilt packaged SDK from previous run uses: dawidd6/action-download-artifact@v2 if: ${{ github.event.inputs.test_packaged_sdk != '' }} @@ -387,6 +407,9 @@ jobs: matrix: os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -421,14 +444,16 @@ jobs: # homebrew. This prevents errors arising from the shut down of # binutils, used by older version of homebrew for hosting packages. brew update - - name: Install SDK Android prerequisites - shell: bash - run: | - build_scripts/android/install_prereqs.sh - - name: Prepare for integration tests - run: | - pip install -r scripts/gha/requirements.txt - python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" + - name: Install Android SDK & integration tests prerequisites + uses: nick-invision/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 3 + shell: bash + command: | + build_scripts/android/install_prereqs.sh + pip install -r scripts/gha/requirements.txt + python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" - name: Fetch prebuilt packaged SDK from previous run uses: dawidd6/action-download-artifact@v2 if: ${{ github.event.inputs.test_packaged_sdk != '' }} @@ -508,6 +533,9 @@ jobs: strategy: fail-fast: false steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -533,12 +561,15 @@ jobs: # homebrew. This prevents errors arising from the shut down of # binutils, used by older version of homebrew for hosting packages. brew update - - name: Install SDK iOS prerequisites - run: build_scripts/ios/install_prereqs.sh - - name: Prepare for integration tests - run: | - pip install -r scripts/gha/requirements.txt - python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" + - name: Install iOS SDK & integration tests prerequisites + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + max_attempts: 3 + command: | + build_scripts/ios/install_prereqs.sh + pip install -r scripts/gha/requirements.txt + python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" - name: Fetch prebuilt packaged SDK from previous run uses: dawidd6/action-download-artifact@v2 if: ${{ github.event.inputs.test_packaged_sdk != '' }} @@ -619,6 +650,9 @@ jobs: strategy: fail-fast: false steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -638,12 +672,15 @@ jobs: # homebrew. This prevents errors arising from the shut down of # binutils, used by older version of homebrew for hosting packages. brew update - - name: Install SDK tvOS prerequisites - run: build_scripts/tvos/install_prereqs.sh - - name: Prepare for integration tests - run: | - pip install -r scripts/gha/requirements.txt - python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" + - name: Install tvOS SDK & integration tests prerequisites + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + max_attempts: 3 + command: | + build_scripts/tvos/install_prereqs.sh + pip install -r scripts/gha/requirements.txt + python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" - name: Fetch prebuilt packaged SDK from previous run uses: dawidd6/action-download-artifact@v2 if: ${{ github.event.inputs.test_packaged_sdk != '' }} @@ -726,6 +763,9 @@ jobs: os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }} ssl_variant: ${{ fromJson(needs.check_and_prepare.outputs.matrix_ssl) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -746,9 +786,14 @@ jobs: run: | npm install -g firebase-tools - name: Setup integration test deps - run: | - pip install -r scripts/gha/requirements.txt - python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" --artifact testapps + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + max_attempts: 3 + shell: bash + command: | + pip install -r scripts/gha/requirements.txt + python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" --artifact testapps - name: Run Desktop integration tests run: firebase emulators:exec --only firestore --project demo-example 'python scripts/gha/desktop_tester.py --testapp_dir testapps --logfile_name "desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}"' env: @@ -802,6 +847,9 @@ jobs: build_os: ${{ fromJson(needs.check_and_prepare.outputs.matrix_os) }} android_device: ${{ fromJson(needs.check_and_prepare.outputs.android_device) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -815,7 +863,12 @@ jobs: with: python-version: ${{ env.pythonVersion }} - name: Install python deps - run: pip install -r scripts/gha/requirements.txt + uses: nick-invision/retry@v2 + with: + timeout_minutes: 1 + max_attempts: 3 + shell: bash + command: pip install -r scripts/gha/requirements.txt - id: get-device-type run: | echo "::set-output name=device_type::$( python scripts/gha/print_matrix_configuration.py -d -k ${{ matrix.android_device }} )" @@ -840,6 +893,7 @@ jobs: if: steps.get-device-type.outputs.device_type == 'real' uses: google-github-actions/setup-gcloud@master - name: Run Android integration tests on Real Device via FTL + timeout-minutes: 60 if: steps.get-device-type.outputs.device_type == 'real' run: | python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" @@ -896,6 +950,9 @@ jobs: matrix: ios_device: ${{ fromJson(needs.check_and_prepare.outputs.ios_device) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -909,7 +966,11 @@ jobs: with: python-version: ${{ env.pythonVersion }} - name: Install python deps - run: pip install -r scripts/gha/requirements.txt + uses: nick-invision/retry@v2 + with: + timeout_minutes: 1 + max_attempts: 3 + command: pip install -r scripts/gha/requirements.txt - id: get-device-type run: | echo "::set-output name=device_type::$( python scripts/gha/print_matrix_configuration.py -d -k ${{ matrix.ios_device }} )" @@ -934,6 +995,8 @@ jobs: if: steps.get-device-type.outputs.device_type == 'real' uses: google-github-actions/setup-gcloud@master - name: Run iOS integration tests on Real Device via FTL + # max 3 retry and 10m timeout for each testapp, plus other steps + timeout-minutes: 60 if: steps.get-device-type.outputs.device_type == 'real' run: | python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" @@ -990,6 +1053,9 @@ jobs: matrix: tvos_device: ${{ fromJson(needs.check_and_prepare.outputs.tvos_device) }} steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ fromJson(needs.check_and_prepare.outputs.xcode_version)[0] }}.app/Contents/Developer - uses: actions/checkout@v2 with: ref: ${{needs.check_and_prepare.outputs.github_ref}} @@ -1003,7 +1069,11 @@ jobs: with: python-version: ${{ env.pythonVersion }} - name: Install python deps - run: pip install -r scripts/gha/requirements.txt + uses: nick-invision/retry@v2 + with: + timeout_minutes: 1 + max_attempts: 3 + command: pip install -r scripts/gha/requirements.txt - name: Setup Firebase Emulators run: | npm install -g firebase-tools diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index 956f1e092d..6200df50d6 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -25,7 +25,7 @@ env: jobs: update_dependencies: name: update-deps - runs-on: ubuntu-latest + runs-on: macos-latest steps: - name: Get token for firebase-workflow-trigger uses: tibdex/github-app-token@v1 @@ -77,7 +77,51 @@ jobs: fi # iOS: Update Firestore external version to match Firestore Cocoapod version. firestore_version=$(grep "pod 'Firebase/Firestore'" ios_pod/Podfile | sed "s/.*'\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)'.*/\1/") + echo "Setting Firestore external version to ${firestore_version}" sed -i~ "s/^set(version [^)]*)/set(version CocoaPods-${firestore_version})/i" cmake/external/firestore.cmake + # iOS: Update Analytics header files, used for generating constants. + analytics_version=$(grep "pod 'Firebase/Analytics'" ios_pod/Podfile | sed "s/.*'\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)'.*/\1/") + if [[ "$(uname)" == "Darwin"* ]]; then + echo "Updating Analytics iOS headers from version ${analytics_version}" + # Unfortunately we can't just download these headers from GitHub, as + # Analytics is closed-source. If it becomes open-source, we could just + # download the header files from the iOS SDK's release branch. So instead, + # download the Firebase Analytics cocoapod (via a stub project) and get the + # header from there. This will only work on macOS. + podtmp="$(mktemp -d)" + cd "${podtmp}" + # Generate a Podfile for Firebase/Analytics. Use the Specs.git + # source to avoid any propagation delays due to CocoaPods mirror. + echo "source 'https://github.com/CocoaPods/Specs.git'" > Podfile + echo "platform :ios, '14.0'" >> Podfile + echo "pod 'Firebase/Analytics', '${analytics_version}'" >> Podfile + pod repo update + pod install || true # ignore error since there is no Xcode project + declare -a header_dirs + # Get all of the framework header directories from the xcframework. + header_dirs=(Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.xcframework/*/FirebaseAnalytics.framework/Headers) + # Just use the first directory found, the headers should be the same across + # all of the frameworks. + header_dir="${header_dirs[0]}" + cd - + cd analytics/ios_headers + for ios_header in *.h; do + # Each file in this directory matches a file in the Analytics iOS SDK. + cp -vf "${podtmp}/${header_dir}/${ios_header}" . + # If the file doesn't have a Google copyright, add one. + if ! grep -q "^// Copyright [0-9]* Google LLC" "${ios_header}"; then + copyright_line="// Copyright $(date +%Y) Google LLC\n" + else + copyright_line= + fi + # Add a note to each file about its source. + sed -i~ "s|^/// @file|${copyright_line}\n// Copied from Firebase Analytics iOS SDK ${analytics_version}.\n\n/// @file|" "${ios_header}" + rm -f "${ios_header}~" # remove backup file that sed generated + python ../../scripts/format_code.py --f "${ios_header}" + done + cd - + rm -rf "${podtmp}" + fi elif [[ ${{ github.event.inputs.updateAndroid }} -eq 1 ]]; then # Update Android only echo "Updating Android dependencies only" diff --git a/Android/firebase_dependencies.gradle b/Android/firebase_dependencies.gradle index 95d9b96617..f23d3d5875 100644 --- a/Android/firebase_dependencies.gradle +++ b/Android/firebase_dependencies.gradle @@ -23,7 +23,7 @@ def firebaseDependenciesMap = [ 'analytics' : ['com.google.firebase:firebase-analytics:20.0.0', 'com.google.android.gms:play-services-base:17.6.0'], 'auth' : ['com.google.firebase:firebase-auth:21.0.1'], - 'database' : ['com.google.firebase:firebase-database:20.0.2'], + 'database' : ['com.google.firebase:firebase-database:20.0.3'], 'dynamic_links' : ['com.google.firebase:firebase-dynamic-links:21.0.0'], 'firestore' : ['com.google.firebase:firebase-firestore:24.0.0'], 'functions' : ['com.google.firebase:firebase-functions:20.0.1'], @@ -36,7 +36,7 @@ def firebaseDependenciesMap = [ 'androidx.core:core:1.6.0-alpha03', 'com.google.flatbuffers:flatbuffers-java:1.12.0', 'com.google.android.gms:play-services-base:17.6.0'], - 'performance' : ['com.google.firebase:firebase-perf:20.0.3'], + 'performance' : ['com.google.firebase:firebase-perf:20.0.4'], 'remote_config' : ['com.google.firebase:firebase-config:21.0.1', 'com.google.android.gms:play-services-base:17.6.0'], 'storage' : ['com.google.firebase:firebase-storage:20.0.0'], diff --git a/README.md b/README.md index 97acfa2a24..d9efcfe5a5 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Firebase C++ SDK can be found at . 1. [Prerequisites](#prerequisites) 1. [Prerequisites for Desktop](#prerequisites-for-desktop) 1. [Prerequisites for Android](#prerequisites-for-android) - 1. [Prerequisites for iOS](#prerequisites-for-ios) + 1. [Prerequisites for iOS/tvOS](#prerequisites-for-iostvos) 1. [Building](#building) 1. [Building with CMake](#building-with-cmake) 1. [Building with CMake for iOS](#building-with-cmake-for-ios) diff --git a/admob/integration_test/Podfile b/admob/integration_test/Podfile index 7afa05803d..26c0b4bd4d 100644 --- a/admob/integration_test/Podfile +++ b/admob/integration_test/Podfile @@ -3,8 +3,8 @@ platform :ios, '10.0' # Firebase AdMob test application. target 'integration_test' do - pod 'Firebase/Analytics', '8.9.1' pod 'Google-Mobile-Ads-SDK', '8.12.0' + pod 'Firebase/Analytics', '8.10.0' end post_install do |installer| diff --git a/analytics/integration_test/Podfile b/analytics/integration_test/Podfile index f20470cf19..f94cbf93b2 100644 --- a/analytics/integration_test/Podfile +++ b/analytics/integration_test/Podfile @@ -5,12 +5,12 @@ platform :ios, '10.0' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Analytics', '8.9.1' + pod 'Firebase/Analytics', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Analytics', '8.9.1' + pod 'Firebase/Analytics', '8.10.0' end post_install do |installer| diff --git a/analytics/ios_headers/FIREventNames.h b/analytics/ios_headers/FIREventNames.h index f7984ca777..1ee46f94e9 100644 --- a/analytics/ios_headers/FIREventNames.h +++ b/analytics/ios_headers/FIREventNames.h @@ -1,19 +1,6 @@ -// Copyright 2018 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 -// -// http://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. - -// These headers are copied from the public Firebase Analytics iOS Headers -// and are used to generate appropriate C++ Header. +// Copyright 2021 Google LLC + +// Copied from Firebase Analytics iOS SDK 8.10.0. /// @file FIREventNames.h /// diff --git a/analytics/ios_headers/FIRParameterNames.h b/analytics/ios_headers/FIRParameterNames.h index 6047f5684a..656592bad6 100644 --- a/analytics/ios_headers/FIRParameterNames.h +++ b/analytics/ios_headers/FIRParameterNames.h @@ -1,19 +1,6 @@ -// Copyright 2018 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 -// -// http://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. - -// These headers are copied from the public Firebase Analytics iOS Headers -// and are used to generate appropriate C++ Header. +// Copyright 2021 Google LLC + +// Copied from Firebase Analytics iOS SDK 8.10.0. /// @file FIRParameterNames.h /// diff --git a/analytics/ios_headers/FIRUserPropertyNames.h b/analytics/ios_headers/FIRUserPropertyNames.h index b00ff72a35..1573d323e6 100644 --- a/analytics/ios_headers/FIRUserPropertyNames.h +++ b/analytics/ios_headers/FIRUserPropertyNames.h @@ -1,19 +1,6 @@ -// Copyright 2018 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 -// -// http://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. +// Copyright 2021 Google LLC -// These headers are copied from the public Firebase Analytics iOS Headers -// and are used to generate appropriate C++ Header. +// Copied from Firebase Analytics iOS SDK 8.10.0. /// @file FIRUserPropertyNames.h /// diff --git a/app/integration_test/Podfile b/app/integration_test/Podfile index 98bf026181..9516eaa1e5 100644 --- a/app/integration_test/Podfile +++ b/app/integration_test/Podfile @@ -4,7 +4,7 @@ platform :ios, '10.0' # Firebase App test application. target 'integration_test' do - pod 'Firebase/Analytics', '8.9.1' + pod 'Firebase/Analytics', '8.10.0' end post_install do |installer| diff --git a/app/src/invites/ios/invites_ios_startup.mm b/app/src/invites/ios/invites_ios_startup.mm index 98d12c131f..4ae901d57a 100644 --- a/app/src/invites/ios/invites_ios_startup.mm +++ b/app/src/invites/ios/invites_ios_startup.mm @@ -284,7 +284,8 @@ static void HookAppDelegateMethods(Class clazz) { // http://www.opensource.apple.com/source/objc4/objc4-274/runtime/objc-runtime.m) @implementation UIApplication (FIRFBI) + (void)load { - ::firebase::LogDebug("Loading UIApplication FIRFBI category"); + // C++ constructors may not be called yet so call NSLog rather than LogDebug. + NSLog(@"Loading UIApplication category for Firebase App"); ::firebase::util::ForEachAppDelegateClass(^(Class clazz) { ::firebase::invites::HookAppDelegateMethods(clazz); }); diff --git a/app/src/util_ios.h b/app/src/util_ios.h index f059e3953a..f0a6f97520 100644 --- a/app/src/util_ios.h +++ b/app/src/util_ios.h @@ -195,8 +195,8 @@ NSMutableArray *StringVectorToNSMutableArray( // Convert a NSArray into a vector of strings. Asserts if a non NSString // object is found in the array. -void NSArrayOfNSStringToVectorOfString(NSArray* array, - std::vector* string_vector); +void NSArrayOfNSStringToVectorOfString(NSArray *array, + std::vector *string_vector); // Convert a string map to NSDictionary. NSDictionary *StringMapToNSDictionary( diff --git a/app/src/util_ios.mm b/app/src/util_ios.mm index 8be02dd709..02cfa44b83 100644 --- a/app/src/util_ios.mm +++ b/app/src/util_ios.mm @@ -161,21 +161,20 @@ void ForEachAppDelegateClass(void (^block)(Class)) { return array; } -void NSArrayOfNSStringToVectorOfString(NSArray* array, std::vector* string_vector) { +void NSArrayOfNSStringToVectorOfString(NSArray *array, std::vector *string_vector) { string_vector->reserve(array.count); for (id object in array) { - if(![object isKindOfClass:[NSString class]]) { + if (![object isKindOfClass:[NSString class]]) { FIREBASE_ASSERT_MESSAGE(false, "Object in Array is not of type NSString"); } else { - string_vector->push_back(NSStringToString((NSString*)object)); + string_vector->push_back(NSStringToString((NSString *)object)); } } } -NSMutableArray* StdVectorToNSMutableArray(const std::vector& vector) { - NSMutableArray* array = - [[NSMutableArray alloc] initWithCapacity:vector.size()]; - for (auto& variant : vector) { +NSMutableArray *StdVectorToNSMutableArray(const std::vector &vector) { + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:vector.size()]; + for (auto &variant : vector) { [array addObject:VariantToId(variant)]; } return array; diff --git a/auth/integration_test/Podfile b/auth/integration_test/Podfile index c9edd7e731..646249fb32 100644 --- a/auth/integration_test/Podfile +++ b/auth/integration_test/Podfile @@ -4,12 +4,12 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Auth', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Auth', '8.10.0' end post_install do |installer| diff --git a/build_scripts/android/install_prereqs.sh b/build_scripts/android/install_prereqs.sh index ff2744a323..ffc601da2d 100755 --- a/build_scripts/android/install_prereqs.sh +++ b/build_scripts/android/install_prereqs.sh @@ -82,7 +82,7 @@ if [[ -z "${NDK_ROOT}" || -z $(grep "Pkg\.Revision = 16\." "${NDK_ROOT}/source.p sleep 300 done set -e - (cd /tmp && unzip -q android-ndk-r16b.zip && rm -f android-ndk-r16b.zip) + (cd /tmp && unzip -oq android-ndk-r16b.zip && rm -f android-ndk-r16b.zip) echo "NDK r16b has been downloaded into /tmp/android-ndk-r16b" fi fi diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 93c028a4c6..c8c79277cd 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -18,7 +18,7 @@ if(TARGET firestore) return() endif() -set(version CocoaPods-8.9.1) +set(version CocoaPods-8.10.0) ExternalProject_Add( firestore diff --git a/cpp_sdk_version.json b/cpp_sdk_version.json index 9b0c5a3f4c..2fd5b216a1 100644 --- a/cpp_sdk_version.json +++ b/cpp_sdk_version.json @@ -1,5 +1,5 @@ { - "released": "8.7.0", - "stable": "8.7.0", - "head": "8.7.0" + "released": "8.8.0", + "stable": "8.8.0", + "head": "8.8.0" } diff --git a/database/database_resources/build.gradle b/database/database_resources/build.gradle index a551f918b5..79fc3c5947 100644 --- a/database/database_resources/build.gradle +++ b/database/database_resources/build.gradle @@ -46,7 +46,7 @@ android { dependencies { implementation 'com.google.firebase:firebase-analytics:20.0.0' - implementation 'com.google.firebase:firebase-database:20.0.2' + implementation 'com.google.firebase:firebase-database:20.0.3' //implementation project(':app:app_resources') } diff --git a/database/integration_test/Podfile b/database/integration_test/Podfile index 537250365e..7672648950 100644 --- a/database/integration_test/Podfile +++ b/database/integration_test/Podfile @@ -4,14 +4,14 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Database', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Database', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Database', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Database', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end post_install do |installer| diff --git a/dynamic_links/integration_test/Podfile b/dynamic_links/integration_test/Podfile index cf816a15ba..bd4fa91270 100644 --- a/dynamic_links/integration_test/Podfile +++ b/dynamic_links/integration_test/Podfile @@ -4,7 +4,7 @@ platform :ios, '10.0' # Firebase Dynamic Links test application. target 'integration_test' do - pod 'Firebase/DynamicLinks', '8.9.1' + pod 'Firebase/DynamicLinks', '8.10.0' end post_install do |installer| diff --git a/firestore/integration_test/Podfile b/firestore/integration_test/Podfile index 8f6c480069..a5b5157c59 100644 --- a/firestore/integration_test/Podfile +++ b/firestore/integration_test/Podfile @@ -4,14 +4,14 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Firestore', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Firestore', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Firestore', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Firestore', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end post_install do |installer| diff --git a/firestore/integration_test_internal/Podfile b/firestore/integration_test_internal/Podfile index a3ae5900ab..58aa86499b 100644 --- a/firestore/integration_test_internal/Podfile +++ b/firestore/integration_test_internal/Podfile @@ -4,14 +4,14 @@ platform :ios, '10.0' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Firestore', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Firestore', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Firestore', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Firestore', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end post_install do |installer| diff --git a/functions/integration_test/Podfile b/functions/integration_test/Podfile index 66c869036f..978b196c7c 100644 --- a/functions/integration_test/Podfile +++ b/functions/integration_test/Podfile @@ -4,14 +4,14 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Functions', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Functions', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Functions', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Functions', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end post_install do |installer| diff --git a/installations/integration_test/Podfile b/installations/integration_test/Podfile index c56fc5db83..6c1819626c 100644 --- a/installations/integration_test/Podfile +++ b/installations/integration_test/Podfile @@ -4,8 +4,8 @@ platform :ios, '10.0' # Firebase Installations test application. target 'integration_test' do - pod 'Firebase/Analytics', '8.9.1' - pod 'Firebase/Installations', '8.9.1' + pod 'Firebase/Analytics', '8.10.0' + pod 'Firebase/Installations', '8.10.0' end post_install do |installer| diff --git a/ios_pod/Podfile b/ios_pod/Podfile index 2322224758..085dfe3266 100644 --- a/ios_pod/Podfile +++ b/ios_pod/Podfile @@ -2,19 +2,19 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' target 'GetPods' do - pod 'Firebase/Core', '8.9.1' + pod 'Firebase/Core', '8.10.0' pod 'Google-Mobile-Ads-SDK', '8.12.0' - pod 'Firebase/Analytics', '8.9.1' - pod 'Firebase/Auth', '8.9.1' - pod 'Firebase/Crashlytics', '8.9.1' - pod 'Firebase/Database', '8.9.1' - pod 'Firebase/DynamicLinks', '8.9.1' - pod 'Firebase/Firestore', '8.9.1' - pod 'Firebase/Functions', '8.9.1' - pod 'Firebase/Installations', '8.9.1' - pod 'Firebase/Messaging', '8.9.1' - pod 'Firebase/RemoteConfig', '8.9.1' - pod 'Firebase/Storage', '8.9.1' + pod 'Firebase/Analytics', '8.10.0' + pod 'Firebase/Auth', '8.10.0' + pod 'Firebase/Crashlytics', '8.10.0' + pod 'Firebase/Database', '8.10.0' + pod 'Firebase/DynamicLinks', '8.10.0' + pod 'Firebase/Firestore', '8.10.0' + pod 'Firebase/Functions', '8.10.0' + pod 'Firebase/Installations', '8.10.0' + pod 'Firebase/Messaging', '8.10.0' + pod 'Firebase/RemoteConfig', '8.10.0' + pod 'Firebase/Storage', '8.10.0' end diff --git a/messaging/integration_test/Podfile b/messaging/integration_test/Podfile index 3215a8b9e5..c4c7cbed79 100644 --- a/messaging/integration_test/Podfile +++ b/messaging/integration_test/Podfile @@ -4,12 +4,12 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Messaging', '8.9.1' + pod 'Firebase/Messaging', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Messaging', '8.9.1' + pod 'Firebase/Messaging', '8.10.0' end post_install do |installer| diff --git a/release_build_files/Android/firebase_dependencies.gradle b/release_build_files/Android/firebase_dependencies.gradle index 689d8c6513..71a0cedc89 100644 --- a/release_build_files/Android/firebase_dependencies.gradle +++ b/release_build_files/Android/firebase_dependencies.gradle @@ -23,7 +23,7 @@ def firebaseDependenciesMap = [ 'analytics' : ['com.google.firebase:firebase-analytics:20.0.0', 'com.google.android.gms:play-services-base:17.6.0'], 'auth' : ['com.google.firebase:firebase-auth:21.0.1'], - 'database' : ['com.google.firebase:firebase-database:20.0.2'], + 'database' : ['com.google.firebase:firebase-database:20.0.3'], 'dynamic_links' : ['com.google.firebase:firebase-dynamic-links:21.0.0'], 'firestore' : ['com.google.firebase:firebase-firestore:24.0.0'], 'functions' : ['com.google.firebase:firebase-functions:20.0.1'], @@ -36,7 +36,7 @@ def firebaseDependenciesMap = [ 'androidx.core:core:1.6.0-alpha03', 'com.google.flatbuffers:flatbuffers-java:1.12.0', 'com.google.android.gms:play-services-base:17.6.0'], - 'performance' : ['com.google.firebase:firebase-perf:20.0.3'], + 'performance' : ['com.google.firebase:firebase-perf:20.0.4'], 'remote_config' : ['com.google.firebase:firebase-config:21.0.1', 'com.google.android.gms:play-services-base:17.6.0'], 'storage' : ['com.google.firebase:firebase-storage:20.0.0'], diff --git a/release_build_files/readme.md b/release_build_files/readme.md index 6f173209ad..5c5f47a951 100644 --- a/release_build_files/readme.md +++ b/release_build_files/readme.md @@ -140,7 +140,7 @@ Firebase Realtime Database | libfirebase_database.a | | libfirebase_app.a | | com.google.firebase:firebase-analytics:20.0.0 | | (Maven package) -| | com.google.firebase:firebase-database:20.0.2 +| | com.google.firebase:firebase-database:20.0.3 | | (Maven package) | | com.google.firebase:firebase-auth:21.0.1 | | (Maven package) @@ -180,46 +180,46 @@ Feature | Required Frameworks and Cocoapods -------------------------- | --------------------------------------- Firebase AdMob | firebase_admob.xcframework | | firebase.xcframework -| | Firebase/Analytics Cocoapod (8.9.1) +| | Firebase/Analytics Cocoapod (8.10.0) | | Google-Mobile-Ads-SDK Cocoapod (7.69.0-cppsdk) Firebase Analytics | firebase_analytics.xcframework | | firebase.xcframework -| | Firebase/Analytics Cocoapod (8.9.1) +| | Firebase/Analytics Cocoapod (8.10.0) Firebase Authentication | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Dynamic Links | firebase_dynamic_links.xcframework | | firebase.xcframework -| | Firebase/DynamicLinks Cocoapod (8.9.1) +| | Firebase/DynamicLinks Cocoapod (8.10.0) Cloud Firestore | firebase_firestore.xcframework | | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Firestore Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Firestore Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Functions | firebase_functions.xcframework | | firebase_auth.xcframework (optional) | | firebase.xcframework -| | Firebase/Functions Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Functions Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Installations | firebase_installations.xcframework | | firebase.xcframework -| | FirebaseInstallations Cocoapod (8.9.0) +| | FirebaseInstallations Cocoapod (8.10.0) Firebase Cloud Messaging | firebase_messaging.xcframework | | firebase.xcframework -| | Firebase/Messaging Cocoapod (8.9.1) +| | Firebase/Messaging Cocoapod (8.10.0) Firebase Realtime Database | firebase_database.xcframework | | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Database Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Database Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Remote Config | firebase_remote_config.xcframework | | firebase.xcframework -| | Firebase/RemoteConfig Cocoapod (8.9.1) +| | Firebase/RemoteConfig Cocoapod (8.10.0) Firebase Storage | firebase_storage.xcframework | | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Storage Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Storage Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Important: Each version of the Firebase C++ SDK supports a specific version of the Firebase iOS SDK. Please ensure that you reference the Cocoapod versions @@ -240,46 +240,46 @@ Feature | Required Libraries and Cocoapods -------------------------- | ----------------------------------------- Firebase AdMob | libfirebase_admob.a | | libfirebase_app.a -| | Firebase/Analytics Cocoapod (8.9.1) +| | Firebase/Analytics Cocoapod (8.10.0) | | Google-Mobile-Ads-SDK Cocoapod (7.69.0-cppsdk) Firebase Analytics | libfirebase_analytics.a | | libfirebase_app.a -| | Firebase/Analytics Cocoapod (8.9.1) +| | Firebase/Analytics Cocoapod (8.10.0) Firebase Authentication | libfirebase_auth.a | | libfirebase_app.a -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Dynamic Links | libfirebase_dynamic_links.a | | libfirebase_app.a -| | Firebase/DynamicLinks Cocoapod (8.9.1) +| | Firebase/DynamicLinks Cocoapod (8.10.0) Cloud Firestore | libfirebase_firestore.a | | libfirebase_app.a | | libfirebase_auth.a -| | Firebase/Firestore Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Firestore Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Functions | libfirebase_functions.a | | libfirebase_app.a | | libfirebase_auth.a (optional) -| | Firebase/Functions Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Functions Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Installations | libfirebase_installations.a | | libfirebase_app.a -| | FirebaseInstallations Cocoapod (8.9.0) +| | FirebaseInstallations Cocoapod (8.10.0) Firebase Cloud Messaging | libfirebase_messaging.a | | libfirebase_app.a -| | Firebase/CloudMessaging Cocoapod (8.9.1) +| | Firebase/CloudMessaging Cocoapod (8.10.0) Firebase Realtime Database | libfirebase_database.a | | libfirebase_app.a | | libfirebase_auth.a -| | Firebase/Database Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Database Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Firebase Remote Config | libfirebase_remote_config.a | | libfirebase_app.a -| | Firebase/RemoteConfig Cocoapod (8.9.1) +| | Firebase/RemoteConfig Cocoapod (8.10.0) Firebase Storage | libfirebase_storage.a | | libfirebase_app.a | | libfirebase_auth.a -| | Firebase/Storage Cocoapod (8.9.1) -| | Firebase/Auth Cocoapod (8.9.1) +| | Firebase/Storage Cocoapod (8.10.0) +| | Firebase/Auth Cocoapod (8.10.0) Important: Each version of the Firebase C++ SDK supports a specific version of the Firebase iOS SDK. Please ensure that you reference the Cocoapod versions @@ -371,7 +371,7 @@ Firebase Installations (stub) | firebase_installations.framework Firebase Cloud Messaging (stub) | firebase_messaging.framework | | firebase.framework -The provided libraries have been tested using Xcode 12.2. When building C++ +The provided libraries have been tested using Xcode 12.4. When building C++ desktop apps on OS X, you will need to link the `gssapi_krb5` and `pthread` system libraries, as well as the `CoreFoundation`, `Foundation`, `GSS`, and `Security` OS X system frameworks (consult your compiler documentation for more @@ -568,19 +568,32 @@ code. ## Release Notes ### Next Release +- Changes + - General (iOS): Fixed an intermittent crash on iOS 15 caused by + constructing C++ objects during Objective-C's `+load` method. + ([#706](https://github.com/firebase/firebase-cpp-sdk/pull/706)) + ([#783](https://github.com/firebase/firebase-cpp-sdk/pull/783)) + +### 8.8.0 - Changes - General: Fixed a data race that could manifest as null pointer dereference in `FutureBase::Release()`. ([#747](https://github.com/firebase/firebase-cpp-sdk/pull/747)) + - General (iOS): iOS SDKs are now built using Xcode 12.4. + - General (Desktop): macOS SDKs are now built using Xcode 12.4. - Auth (Desktop): Fixed a crash in `error_code()` when a request is cancelled or times out. ([#737](https://github.com/firebase/firebase-cpp-sdk/issues/737)) + - Firestore: Fix "unaligned pointers" build error on macOS Monterey + ([#712](https://github.com/firebase/firebase-cpp-sdk/issues/712)). - Messaging (Android): Fixed crash during termination. ([#739](https://github.com/firebase/firebase-cpp-sdk/pull/739)) ([#745](https://github.com/firebase/firebase-cpp-sdk/pull/745)) - Messaging (Android): Fixed crash during initialization. ([#760](https://github.com/firebase/firebase-cpp-sdk/pull/760)) - + - Remote Config (Desktop): Fixed cache expiration time value used by + `RemoteConfig::FetchAndActivate()`. + ([#767](https://github.com/firebase/firebase-cpp-sdk/pull/767)) ### 8.7.0 - Changes diff --git a/remote_config/integration_test/Podfile b/remote_config/integration_test/Podfile index 56d7d7e0f7..da69fed41a 100644 --- a/remote_config/integration_test/Podfile +++ b/remote_config/integration_test/Podfile @@ -4,12 +4,12 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/RemoteConfig', '8.9.1' + pod 'Firebase/RemoteConfig', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/RemoteConfig', '8.9.1' + pod 'Firebase/RemoteConfig', '8.10.0' end post_install do |installer| diff --git a/remote_config/src/desktop/remote_config_desktop.cc b/remote_config/src/desktop/remote_config_desktop.cc index 7e0bafdd03..624a77ebd5 100644 --- a/remote_config/src/desktop/remote_config_desktop.cc +++ b/remote_config/src/desktop/remote_config_desktop.cc @@ -140,7 +140,8 @@ Future RemoteConfigInternal::FetchAndActivate() { future_impl_.SafeAlloc(kRemoteConfigFnFetchAndActivate); cache_expiration_in_seconds_ = - config_settings_.minimum_fetch_interval_in_milliseconds; + config_settings_.minimum_fetch_interval_in_milliseconds / + ::firebase::internal::kMillisecondsPerSecond; uint64_t milliseconds_since_epoch = std::chrono::duration_cast( diff --git a/scripts/gha/build_testapps.py b/scripts/gha/build_testapps.py index 6887441c63..25b28c1cf8 100644 --- a/scripts/gha/build_testapps.py +++ b/scripts/gha/build_testapps.py @@ -114,6 +114,8 @@ _APPLE_SDK_SIMULATOR = "virtual" _SUPPORTED_APPLE_SDK = (_APPLE_SDK_DEVICE, _APPLE_SDK_SIMULATOR) +_DEFAULT_RUN_TIMEOUT_SECONDS = 4800 # 1 hour 20 min + FLAGS = flags.FLAGS flags.DEFINE_string( @@ -637,7 +639,7 @@ def _run_setup_script(root_dir, testapp_dir): _run([sys.executable, script_path, testapp_dir]) -def _run(args, timeout=2400, capture_output=False, text=None, check=True): +def _run(args, timeout=_DEFAULT_RUN_TIMEOUT_SECONDS, capture_output=False, text=None, check=True): """Executes a command in a subprocess.""" logging.info("Running in subprocess: %s", " ".join(args)) return subprocess.run( diff --git a/scripts/gha/integration_testing/test_validation.py b/scripts/gha/integration_testing/test_validation.py index 15f0a7c399..a3699b5d22 100644 --- a/scripts/gha/integration_testing/test_validation.py +++ b/scripts/gha/integration_testing/test_validation.py @@ -150,6 +150,7 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" successes = [] failures = [] errors = [] + success_testapp_paths = set() for test in tests: results = validate_results(test.logs, platform) @@ -160,6 +161,7 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" failures.append(test_result_pair) else: successes.append(test_result_pair) + success_testapp_paths.add(test.testapp_path) # First log the successes, then the failures and errors, then the summary. # This way, debugging will involve checking the summary at the bottom, @@ -174,6 +176,11 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" for test, _ in errors: logging.info("%s didn't finish normally.\n%s", test.testapp_path, test.logs) + # Testapps that failed first, but succeed after retry. (max 3 retry) + flaky_testapps = [] + failures_exclude_flakiness = [] + errors_exclude_flakiness = [] + # The summary is much more terse, to minimize the time it takes to understand # what went wrong, without necessarily providing full debugging context. summary = [] @@ -184,7 +191,12 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" if errors: summary.append("\n%d TESTAPPS EXPERIENCED ERRORS:" % len(errors)) for test, results in errors: - summary.append("%s:" % test.testapp_path) + summary.append("\n%s:" % test.testapp_path) + if test.testapp_path in success_testapp_paths: + summary.append("THIS TESTAPP IS FLAKY") + flaky_testapps.append((test, results)) + else: + errors_exclude_flakiness.append((test, results)) if hasattr(test, "ftl_link") and test.ftl_link: summary.append("ftl_link: %s" % test.ftl_link) if hasattr(test, "raw_result_link") and test.raw_result_link: @@ -198,7 +210,12 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" if failures: summary.append("\n%d TESTAPPS FAILED:" % len(failures)) for test, results in failures: - summary.append(test.testapp_path) + summary.append("\n%s:" % test.testapp_path) + if test.testapp_path in success_testapp_paths: + summary.append("THIS TESTAPP IS FLAKY") + flaky_testapps.append((test, results)) + else: + failures_exclude_flakiness.append((test, results)) if hasattr(test, "ftl_link") and test.ftl_link: summary.append("ftl_link: %s" % test.ftl_link) if hasattr(test, "raw_result_link") and test.raw_result_link: @@ -208,29 +225,37 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" "%d TESTAPPS TOTAL: %d PASSES, %d FAILURES, %d ERRORS" % (len(tests), len(successes), len(failures), len(errors))) + if len(flaky_testapps) > 0 and len(flaky_testapps) == len(failures) + len(errors): + logging.info("All failures and errors are due to flakiness.") + summary.append("ALL THE FOLLOWING FAILURES AND ERRORS ARE DUE TO FLAKINESS:(") + # summary_json format: # { "type": "test", # "testapps": [testapp], - # "errors": {testapp:{"log": error_log, "ftl_link": ftl_link, "raw_result_link": raw_result_link}}, - # "failures": {testapp:{"log": error_log, "ftl_link": ftl_link, "raw_result_link": raw_result_link, - # "failed_tests": {falied_test: test_log}}}}} + # "errors": {testapp:{"logs": [error_log], "ftl_links": [ftl_link], "raw_result_links": [raw_result_link]}}, + # "failures": {testapp:{"logs": [error_log], "ftl_links": [ftl_link], "raw_result_links": [raw_result_link], + # "failed_tests": {failed_test: test_log}}}, + # "flakiness": {testapp:{"logs": [error_log], "ftl_links": [ftl_link], "raw_result_links": [raw_result_link], + # "flaky_tests": {flaky_test: test_log}}}} summary_json = {} summary_json["type"] = "test" summary_json["testapps"] = [get_name(test.testapp_path) for test in tests] - summary_json["errors"] = {get_name(test.testapp_path):{"logs": results.summary} for (test, results) in errors} - for (test, results) in errors: + summary_json["errors"] = {get_name(test.testapp_path):{"logs": [], "ftl_links": [], "raw_result_links": []} for (test, _) in errors_exclude_flakiness} + for (test, results) in errors_exclude_flakiness: testapp = get_name(test.testapp_path) + summary_json["errors"][testapp]["logs"].append(results.summary) if hasattr(test, "ftl_link") and test.ftl_link: - summary_json["errors"][testapp]["ftl_link"] = test.ftl_link + summary_json["errors"][testapp]["ftl_links"].append(test.ftl_link) if hasattr(test, "raw_result_link") and test.raw_result_link: - summary_json["errors"][testapp]["raw_result_link"] = test.raw_result_link - summary_json["failures"] = {get_name(test.testapp_path):{"logs": results.summary, "failed_tests": dict()} for (test, results) in failures} - for (test, results) in failures: + summary_json["errors"][testapp]["raw_result_links"].append(test.raw_result_link) + summary_json["failures"] = {get_name(test.testapp_path):{"logs": [], "ftl_links": [], "raw_result_links": [], "failed_tests": dict()} for (test, _) in failures_exclude_flakiness} + for (test, results) in failures_exclude_flakiness: testapp = get_name(test.testapp_path) + summary_json["failures"][testapp]["logs"].append(results.summary) if hasattr(test, "ftl_link") and test.ftl_link: - summary_json["failures"][testapp]["ftl_link"] = test.ftl_link + summary_json["failures"][testapp]["ftl_links"].append(test.ftl_link) if hasattr(test, "raw_result_link") and test.raw_result_link: - summary_json["failures"][testapp]["raw_result_link"] = test.raw_result_link + summary_json["failures"][testapp]["raw_result_links"].append(test.raw_result_link) failed_tests = re.findall(r"\[ FAILED \] (.+)[.](.+)", results.summary) for failed_test in failed_tests: failed_test = failed_test[0] + "." + failed_test[1] @@ -238,6 +263,22 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" failure_log = re.search(pattern, test.logs, re.MULTILINE | re.DOTALL) summary_json["failures"][testapp]["failed_tests"][failed_test] = failure_log.group() summary.append("\n%s FAILED:\n%s\n" % (failed_test, failure_log.group())) + summary_json["flakiness"] = {get_name(test.testapp_path):{"logs": [], "ftl_links": [], "raw_result_links": [], "flaky_tests": dict()} for (test, _) in flaky_testapps} + for (test, results) in flaky_testapps: + testapp = get_name(test.testapp_path) + summary_json["flakiness"][testapp]["logs"].append(results.summary) + if hasattr(test, "ftl_link") and test.ftl_link: + summary_json["flakiness"][testapp]["ftl_links"].append(test.ftl_link) + if hasattr(test, "raw_result_link") and test.raw_result_link: + summary_json["flakiness"][testapp]["raw_result_links"].append(test.raw_result_link) + flaky_tests = re.findall(r"\[ FAILED \] (.+)[.](.+)", results.summary) + for flaky_test in flaky_tests: + flaky_test = flaky_test[0] + "." + flaky_test[1] + pattern = fr'\[ RUN \] {flaky_test}(.*?)\[ FAILED \] {flaky_test}' + failure_log = re.search(pattern, test.logs, re.MULTILINE | re.DOTALL) + if failure_log: + summary_json["flakiness"][testapp]["flaky_tests"][flaky_test] = failure_log.group() + summary.append("\n%s FAILED:\n%s\n" % (flaky_test, failure_log.group())) with open(os.path.join(summary_dir, file_name+".json"), "a") as f: f.write(json.dumps(summary_json, indent=2)) @@ -245,7 +286,11 @@ def summarize_test_results(tests, platform, summary_dir, file_name="summary.log" summary = "\n".join(summary) write_summary(summary_dir, summary, file_name) - return 0 if len(tests) == len(successes) else 1 + # success or only flakiness + if len(tests) == len(successes) or len(flaky_testapps) == len(failures) + len(errors): + return 0 + else: + return 1 def write_summary(testapp_dir, summary, file_name="summary.log"): diff --git a/scripts/gha/it_workflow.py b/scripts/gha/it_workflow.py index d978e2beb2..bd47266d87 100644 --- a/scripts/gha/it_workflow.py +++ b/scripts/gha/it_workflow.py @@ -60,13 +60,17 @@ _LABEL_SUCCEED = "tests: succeeded" _COMMENT_TITLE_PROGESS = "### ⏳  Integration test in progress...\n" +_COMMENT_TITLE_PROGESS_FLAKY = "### Integration test with FLAKINESS (but still ⏳  in progress)\n" _COMMENT_TITLE_PROGESS_FAIL = "### ❌  Integration test FAILED (but still ⏳  in progress)\n" +_COMMENT_TITLE_FLAKY = "### Integration test with FLAKINESS (succeeded after retry)\n" _COMMENT_TITLE_FAIL = "### ❌  Integration test FAILED\n" _COMMENT_TITLE_SUCCEED = "### ✅  Integration test succeeded!\n" -_COMMENT_TITLE_FAIL_SDK = "\n***\n### ❌  Integration test FAILED (build against SDK)\n" -_COMMENT_TITLE_SUCCEED_SDK = "\n***\n### ✅  Integration test succeeded! (build against SDK)\n" -_COMMENT_TITLE_FAIL_REPO = "### ❌  Integration test FAILED (build against repo)\n" -_COMMENT_TITLE_SUCCEED_REPO = "### ✅  Integration test succeeded! (build against repo)\n" +_COMMENT_TITLE_FLAKY_SDK = "\n***\n### [build against SDK] Integration test with FLAKINESS (succeeded after retry)\n" +_COMMENT_TITLE_FAIL_SDK = "\n***\n### ❌  [build against SDK] Integration test FAILED\n" +_COMMENT_TITLE_SUCCEED_SDK = "\n***\n### ✅  [build against SDK] Integration test succeeded!\n" +_COMMENT_TITLE_FLAKY_REPO = "### [build against repo] Integration test with FLAKINESS (succeeded after retry)\n" +_COMMENT_TITLE_FAIL_REPO = "### ❌  [build against repo] Integration test FAILED\n" +_COMMENT_TITLE_SUCCEED_REPO = "### ✅  [build against repo] Integration test succeeded!\n" _COMMENT_FLAKY_TRACKER = "\n\nAdd flaky tests to **[go/fpl-cpp-flake-tracker](http://go/fpl-cpp-flake-tracker)**\n" @@ -136,12 +140,19 @@ def test_start(token, issue_number, actor, commit, run_id): def test_progress(token, issue_number, actor, commit, run_id): """In PR, when some test failed, update failure info and add label \"tests: failed\"""" - log_summary = _get_summary_talbe(token, run_id) - if log_summary == 0: + success_or_only_flakiness, log_summary = _get_summary_table(token, run_id) + if success_or_only_flakiness and not log_summary: + # succeeded (without flakiness) return else: - github.add_label(token, issue_number, _LABEL_FAILED) - comment = (_COMMENT_TITLE_PROGESS_FAIL + + if success_or_only_flakiness: + # all failures/errors are due to flakiness (succeeded after retry) + title = _COMMENT_TITLE_PROGESS_FLAKY + else: + # failures/errors still exist after retry + title = _COMMENT_TITLE_PROGESS_FAIL + github.add_label(token, issue_number, _LABEL_FAILED) + comment = (title + _get_description(actor, commit, run_id) + log_summary + _COMMENT_FLAKY_TRACKER + @@ -153,16 +164,24 @@ def test_end(token, issue_number, actor, commit, run_id, new_token): """In PR, when some test end, update Test Result Report and update label: add \"tests: failed\" if test failed, add label \"tests: succeeded\" if test succeed""" - log_summary = _get_summary_talbe(token, run_id) - if log_summary == 0: + success_or_only_flakiness, log_summary = _get_summary_table(token, run_id) + if success_or_only_flakiness and not log_summary: + # succeeded (without flakiness) github.add_label(token, issue_number, _LABEL_SUCCEED) comment = (_COMMENT_TITLE_SUCCEED + _get_description(actor, commit, run_id) + _COMMENT_SUFFIX) _update_comment(token, issue_number, comment) else: - github.add_label(token, issue_number, _LABEL_FAILED) - comment = (_COMMENT_TITLE_FAIL + + if success_or_only_flakiness: + # all failures/errors are due to flakiness (succeeded after retry) + title = _COMMENT_TITLE_FLAKY + github.add_label(token, issue_number, _LABEL_SUCCEED) + else: + # failures/errors still exist after retry + title = _COMMENT_TITLE_FAIL + github.add_label(token, issue_number, _LABEL_FAILED) + comment = (title + _get_description(actor, commit, run_id) + log_summary + _COMMENT_FLAKY_TRACKER + @@ -180,12 +199,18 @@ def test_report(token, actor, commit, run_id, build_against): issue_number = _get_issue_number(token, _REPORT_TITLE, _REPORT_LABEL) previous_comment = github.get_issue_body(token, issue_number) [previous_comment_repo, previous_comment_sdk] = previous_comment.split(_COMMENT_SUFFIX) - log_summary = _get_summary_talbe(token, run_id) - if log_summary == 0: + success_or_only_flakiness, log_summary = _get_summary_table(token, run_id) + if success_or_only_flakiness and not log_summary: + # succeeded (without flakiness) title = _COMMENT_TITLE_SUCCEED_REPO if build_against==_BUILD_AGAINST_REPO else _COMMENT_TITLE_SUCCEED_SDK comment = title + _get_description(actor, commit, run_id) else: - title = _COMMENT_TITLE_FAIL_REPO if build_against==_BUILD_AGAINST_REPO else _COMMENT_TITLE_FAIL_SDK + if success_or_only_flakiness: + # all failures/errors are due to flakiness (succeeded after retry) + title = _COMMENT_TITLE_FLAKY_REPO if build_against==_BUILD_AGAINST_REPO else _COMMENT_TITLE_FLAKY_SDK + else: + # failures/errors still exist after retry + title = _COMMENT_TITLE_FAIL_REPO if build_against==_BUILD_AGAINST_REPO else _COMMENT_TITLE_FAIL_SDK comment = title + _get_description(actor, commit, run_id) + log_summary + _COMMENT_FLAKY_TRACKER if build_against==_BUILD_AGAINST_REPO: @@ -239,16 +264,10 @@ def _get_datetime(): return pst_now.strftime("%a %b %e %H:%M %Z %G") -def _get_summary_talbe(token, run_id): +def _get_summary_table(token, run_id): """Test Result Report Body, which is failed test table with markdown format""" - # artifact_id only exist after workflow finishs running - # Thus, "down artifact" logic is in the workflow - # artifact_id = _get_artifact_id(token, run_id, _LOG_ARTIFACT_NAME) - # artifact_path = _LOG_ARTIFACT_NAME + ".zip" - # github.download_artifact(token, artifact_id, artifact_path) - # shutil.unpack_archive(artifact_path, _LOG_OUTPUT_DIR) - summary_talbe = summarize.summarize_logs(dir=_LOG_OUTPUT_DIR, markdown=True) - return summary_talbe + # return (success_or_only_flakiness, failed_test_summary_table) + return summarize.summarize_logs(dir=_LOG_OUTPUT_DIR, markdown=True) def _get_artifact_id(token, run_id, name): diff --git a/scripts/gha/print_matrix_configuration.py b/scripts/gha/print_matrix_configuration.py index 3801c84400..ce3d4cec2d 100644 --- a/scripts/gha/print_matrix_configuration.py +++ b/scripts/gha/print_matrix_configuration.py @@ -76,12 +76,12 @@ "build_type": ["Release", "Debug"], "architecture": ["x64", "x86", "arm64"], "msvc_runtime": ["static","dynamic"], - "xcode_version": ["12.2"], + "xcode_version": ["12.4"], "python_version": ["3.7"], EXPANDED_KEY: { "os": ["ubuntu-latest", "macos-latest", "windows-latest"], - "xcode_version": ["11.7", "12.2", "12.5"], + "xcode_version": ["11.7", "12.4", "12.5.1"], } } }, @@ -112,7 +112,7 @@ "msvc_runtime": ["dynamic"], "cpp_compiler_windows": ["VisualStudio2019"], "cpp_compiler_linux": ["clang-11.0"], - "xcode_version": ["12"], + "xcode_version": ["12.4"], # only the first one is used "ndk_version": ["r22b"], "platform_version": ["28"], "build_tools_version": ["28.0.3"], @@ -138,10 +138,10 @@ "ios": { "matrix": { - "xcode_version": ["12"], + "xcode_version": ["12.4"], EXPANDED_KEY: { - "xcode_version": ["12", "12.4"] + "xcode_version": ["12.4", "12.5.1"] } } }, @@ -161,19 +161,19 @@ TEST_DEVICES = { "android_min": {"type": "real", "model":"Nexus10", "version":"19"}, - "android_target": {"type": "real", "model":"blueline", "version":"28"}, - "android_latest": {"type": "real", "model":"flame", "version":"29"}, + "android_target": {"type": "real", "model":"gts4lltevzw", "version":"28"}, + "android_latest": {"type": "real", "model":"redfin", "version":"30"}, "emulator_min": {"type": "virtual", "image":"system-images;android-18;google_apis;x86"}, "emulator_target": {"type": "virtual", "image":"system-images;android-28;google_apis;x86_64"}, "emulator_latest": {"type": "virtual", "image":"system-images;android-30;google_apis;x86_64"}, "emulator_32bit": {"type": "virtual", "image":"system-images;android-30;google_apis;x86"}, "ios_min": {"type": "real", "model":"iphone8", "version":"11.4"}, "ios_target": {"type": "real", "model":"iphone8plus", "version":"12.0"}, - "ios_latest": {"type": "real", "model":"iphone11", "version":"13.6"}, + "ios_latest": {"type": "real", "model":"iphone11pro", "version":"14.7"}, "simulator_min": {"type": "virtual", "name":"iPhone 6", "version":"11.4"}, "simulator_target": {"type": "virtual", "name":"iPhone 8", "version":"12.0"}, "simulator_latest": {"type": "virtual", "name":"iPhone 11", "version":"14.4"}, - "tvos_simulator": {"type": "virtual", "name":"Apple TV", "version":"14.0"}, + "tvos_simulator": {"type": "virtual", "name":"Apple TV", "version":"14.3"}, } diff --git a/scripts/gha/summarize_test_results.py b/scripts/gha/summarize_test_results.py index 8344cbaf94..c33cd9579d 100644 --- a/scripts/gha/summarize_test_results.py +++ b/scripts/gha/summarize_test_results.py @@ -200,23 +200,24 @@ def summarize_logs(dir, markdown=False, github_log=False): test_log_name_re = re.escape( os.path.join(dir,TEST_FILE_PATTERN)).replace("\\*", "(.*)") - any_failures = False + success_or_only_flakiness = True log_data = {} # log_data format: # { testapps: {"build": [configs]}, # {"test": {"errors": [configs]}, - # {"failures": {failed_test: [configs]}}}} + # {"failures": {failed_test: [configs]}}, + # {"flakiness": {flaky_test: [configs]}}}} for build_log_file in build_log_files: configs = get_configs_from_file_name(build_log_file, build_log_name_re) with open(build_log_file, "r") as log_reader: log_text = log_reader.read() if "__SUMMARY_MISSING__" in log_text: - any_failures = True + success_or_only_flakiness = False log_data.setdefault(MISSING_LOG, {}).setdefault("build", []).append(configs) else: log_reader_data = json.loads(log_text) - for (testapp, error) in log_reader_data["errors"].items(): - any_failures = True + for (testapp, _) in log_reader_data["errors"].items(): + success_or_only_flakiness = False log_data.setdefault(testapp, {}).setdefault("build", []).append(configs) for test_log_file in test_log_files: @@ -224,26 +225,32 @@ def summarize_logs(dir, markdown=False, github_log=False): with open(test_log_file, "r") as log_reader: log_text = log_reader.read() if "__SUMMARY_MISSING__" in log_text: - any_failures = True + success_or_only_flakiness = False log_data.setdefault(MISSING_LOG, {}).setdefault("test", {}).setdefault("errors", []).append(configs) else: log_reader_data = json.loads(log_text) - for (testapp, error) in log_reader_data["errors"].items(): - any_failures = True + for (testapp, _) in log_reader_data["errors"].items(): + success_or_only_flakiness = False log_data.setdefault(testapp, {}).setdefault("test", {}).setdefault("errors", []).append(configs) for (testapp, failures) in log_reader_data["failures"].items(): - for (test, failure) in failures["failed_tests"].items(): - any_failures = True + for (test, _) in failures["failed_tests"].items(): + success_or_only_flakiness = False log_data.setdefault(testapp, {}).setdefault("test", {}).setdefault("failures", {}).setdefault(test, []).append(configs) - + for (testapp, flakiness) in log_reader_data["flakiness"].items(): + if flakiness["flaky_tests"].items(): + for (test, _) in flakiness["flaky_tests"].items(): + log_data.setdefault(testapp, {}).setdefault("test", {}).setdefault("flakiness", {}).setdefault(test, []).append(configs) + else: + log_data.setdefault(testapp, {}).setdefault("test", {}).setdefault("flakiness", {}).setdefault("CRASH/TIMEOUT", []).append(configs) + + if success_or_only_flakiness and not log_data: + # No failures and no flakiness occurred, nothing to log. + return (success_or_only_flakiness, None) + + # if failures (include flakiness) exist: # log_results format: # { testapps: {configs: [failed tests]} } log_results = reorganize_log(log_data) - - if not any_failures: - # No failures occurred, nothing to log. - return(0) - log_lines = [] if markdown: log_lines = print_markdown_table(log_results) @@ -255,7 +262,7 @@ def summarize_logs(dir, markdown=False, github_log=False): log_summary = "\n".join(log_lines) print(log_summary) - return log_summary + return (success_or_only_flakiness, log_summary) def get_configs_from_file_name(file_name, file_name_re): @@ -293,6 +300,13 @@ def reorganize_log(log_data): all_configs = [["TEST"], ["FAILURE"], [CAPITALIZATIONS[platform]]] all_configs.extend(config) log_results.setdefault(testapp, {}).setdefault(flat_config(all_configs), []).append(test) + for (test, configs) in errors.get("test",{}).get("flakiness",{}).items(): + combined_configs = combine_configs(configs) + for (platform, configs) in combined_configs.items(): + for config in configs: + all_configs = [["TEST"], ["FLAKINESS"], [CAPITALIZATIONS[platform]]] + all_configs.extend(config) + log_results.setdefault(testapp, {}).setdefault(flat_config(all_configs), []).append(test) return log_results diff --git a/scripts/gha/test_lab.py b/scripts/gha/test_lab.py index e3c16e80d9..7e288427a1 100644 --- a/scripts/gha/test_lab.py +++ b/scripts/gha/test_lab.py @@ -28,7 +28,7 @@ Usage: - python test_lab.py --testapp_dir ~/testapps --code_platform unity \ + python test_lab.py --testapp_dir ~/testapps --code_platform cpp \ --key_file scripts/gha-encrypted/gcs_key_file.json This will recursively search ~/testapps for apks and ipas, @@ -189,13 +189,7 @@ def main(argv): results_dir=gcs_base_dir + "/" + name)) logging.info("Sending testapps to FTL") - threads = [] - for test in tests: - thread = threading.Thread(target=test.run) - threads.append(thread) - thread.start() - for thread in threads: - thread.join() + tests = _run_test_on_ftl(tests, []) # Useful diagnostic information to debug unexpected errors involving things # not being where they're supposed to be. This will show everything generated @@ -212,6 +206,37 @@ def main(argv): extra_info=" (ON REAL DEVICE VIA FTL)") +def _run_test_on_ftl(tests, tested_tests, retry=3): + threads = [] + for test in tests: + logging.info("Start running testapp: %s" % test.testapp_path) + thread = threading.Thread(target=test.run) + threads.append(thread) + thread.start() + tested_tests.append(test) + for thread in threads: + thread.join() + + if retry > 1: + failed_tests = [] + for test in tests: + result = test_validation.validate_results(test.logs, test_validation.CPP) + if not result.complete or result.fails != 0: + logging.info("Failure(s) occurred, testapp: %s" % test.testapp_path) + failed_test = Test( + device=test.device, + platform=test.platform, + testapp_path=test.testapp_path, + results_dir=test.results_dir + "retry") + failed_tests.append(failed_test) + + if failed_tests: + logging.info("Failure(s) occurred, retrying test(s) on FTL.") + return _run_test_on_ftl(failed_tests, tested_tests, retry=retry-1) + + return tested_tests + + def _install_gcloud_beta(): """Install Google Cloud beta components for iOS integration tests.""" subprocess.run( @@ -294,7 +319,7 @@ def _gcloud_command(self): "--app", self.testapp_path, "--results-bucket", gcs.PROJECT_ID, "--results-dir", self.results_dir, - "--timeout", "900s" + "--timeout", "600s" ] def _get_testapp_log_text_from_gcs(self): diff --git a/scripts/gha/trigger_workflow.py b/scripts/gha/trigger_workflow.py index f1726f2339..569a30aaf6 100644 --- a/scripts/gha/trigger_workflow.py +++ b/scripts/gha/trigger_workflow.py @@ -81,7 +81,7 @@ def main(): workflow_url = 'https://github.com/firebase/firebase-cpp-sdk/actions/runs/%s' % (run_id) else: # Couldn't get a run ID, use a generic URL. - workflow_url = '/%s/actions/workflows/%s?query=%s+%s' % ( + workflow_url = '%s/actions/workflows/%s?query=%s+%s' % ( github.GITHUB_API_URL, args.workflow, urllib.parse.quote('event:workflow_dispatch', safe=''), urllib.parse.quote('branch:'+args.branch, safe='')) diff --git a/storage/integration_test/Podfile b/storage/integration_test/Podfile index a2c0c96d6e..692a43764f 100644 --- a/storage/integration_test/Podfile +++ b/storage/integration_test/Podfile @@ -4,14 +4,14 @@ source 'https://github.com/CocoaPods/Specs.git' target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Storage', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Storage', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Storage', '8.9.1' - pod 'Firebase/Auth', '8.9.1' + pod 'Firebase/Storage', '8.10.0' + pod 'Firebase/Auth', '8.10.0' end post_install do |installer|