diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 5b8e9a6b2..4d5e33e00 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -46,6 +46,11 @@ env: pythonVersion: '3.7' 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: @@ -56,6 +61,9 @@ jobs: 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 }} @@ -63,6 +71,8 @@ jobs: 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 @@ -73,7 +83,7 @@ jobs: ### trigger value: manual_trigger, scheduled_trigger, label_trigger, postsubmit_trigger - id: set_outputs run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then if [[ "${{ github.event.inputs.test_pull_request }}" != "nightly-packaging" ]]; then # Triggered manually echo "::set-output name=trigger::manual_trigger" @@ -124,12 +134,12 @@ jobs: if: ${{ !steps.set_outputs.outputs.trigger }} uses: andymckay/cancel-action@0.2 - name: Wait for workflow cancellation - if: ${{ !steps.set_outputs.outputs.trigger }} + 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' + if: steps.set_outputs.outputs.trigger == 'label_trigger' uses: styfle/cancel-workflow-action@0.8.0 with: access_token: ${{ github.token }} @@ -151,14 +161,14 @@ jobs: command: pip install -r scripts/gha/requirements.txt - id: matrix_config run: | - if [[ "${{ steps.set_outputs.outputs.requested_tests }}" == "expanded" ]]; then + 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 + 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. + 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/${{github.event.pull_request.head.ref}} origin/${{github.event.pull_request.base.ref}} || true) # If origin/ is no longer valid, then just run all tests. @@ -174,7 +184,7 @@ jobs: 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="admob,analytics,auth,database,dynamic_links,functions,installations,messaging,remote_config,storage" - elif [[ "${{ github.event.schedule }}" == "0 10 * * *" ]]; then + elif [[ "${{ github.event.schedule }}" == "0 10 * * *" ]]; then # at 2am PST / 3am PDT. Running integration tests for firestore and generate test report apis="firestore" else @@ -183,11 +193,20 @@ jobs: echo "::set-output name=apis::${apis}" echo "::set-output name=matrix_platform::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k platform -o "${{github.event.inputs.platforms}}" --apis ${apis} )" echo "::set-output name=matrix_os::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k os -o "${{github.event.inputs.operating_systems}}")" - # If building against a packaged SDK, only use boringssl. + echo "::set-output name=matrix_arch_macos::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k architecture_macos)" + echo "::set-output name=matrix_arch_windows_linux::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k architecture_windows_linux)" + # 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 "::set-output name=matrix_arch_combined::${matrix_arch_combined_json}" + # 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 }}" - # Because the mobile tests require this value to be set to 'openssl', set it to 'openssl' here. It won't actually matter later. - echo "::set-output name=matrix_ssl::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k ssl_lib -o openssl )" + echo "::set-output name=matrix_ssl::$( python scripts/gha/print_matrix_configuration.py -w integration_tests ${TEST_MATRIX_PARAM} -k ssl_lib -o boringssl )" else echo "::set-output name=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}}" )" fi @@ -210,7 +229,7 @@ jobs: --run_id ${{github.run_id}} build_desktop: - name: build-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }} + 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). @@ -220,7 +239,30 @@ jobs: 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-latest + arch: arm64 + # Do not attempt to use x86 on Mac. + - os: macos-12 + 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-12 + ssl_variant: openssl + arch: arm64 steps: - name: setup Xcode version (macos) if: runner.os == 'macOS' @@ -275,10 +317,10 @@ jobs: - name: Install Desktop SDK & integration tests prerequisites uses: nick-invision/retry@v2 with: - timeout_minutes: 2 + timeout_minutes: 15 max_attempts: 3 command: | - python scripts/gha/install_prereqs_desktop.py --ssl '${{ matrix.ssl_variant }}' + python scripts/gha/install_prereqs_desktop.py --gha_build --arch '${{ matrix.arch }}' --ssl '${{ matrix.ssl_variant }}' pip install -r scripts/gha/requirements.txt python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" - name: Install OpenSSL (Windows) @@ -315,7 +357,7 @@ jobs: run_id: ${{ github.event.inputs.test_packaged_sdk }} - name: Build integration tests shell: bash - env: + env: CCACHE_DIR: ${{ github.workspace }}/ccache_dir run: | declare -a additional_flags @@ -336,36 +378,38 @@ jobs: 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.ssl_variant }}" \ + --artifact_name "desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}" \ --noadd_timestamp \ --short_output_paths \ + --gha_build \ + --arch ${{ matrix.arch }} \ ${additional_flags[*]} - name: Prepare results summary artifact if: ${{ !cancelled() }} shell: bash run: | - if [ ! -f build-results-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}.log.json ]; then + 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.ssl_variant }}.log.json + 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.ssl_variant }} - path: testapps-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }} + 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.ssl_variant }}* + path: build-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}* retention-days: ${{ env.artifactRetentionDays }} - name: Cleanup Local Copies of Uploaded Artifacts shell: bash run: | - rm -rf testapps-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }} + rm -rf testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }} - name: Set CLOUDSDK_PYTHON (Windows) shell: bash if: startsWith(matrix.os, 'windows') && !cancelled() @@ -399,7 +443,7 @@ jobs: if: ${{ !cancelled() }} shell: bash run: | - cat build-results-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}.log + cat build-results-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}.log if [[ "${{ job.status }}" != "success" ]]; then exit 1 fi @@ -486,6 +530,7 @@ jobs: --artifact_name "android-${{ matrix.os }}" \ --noadd_timestamp \ --short_output_paths \ + --gha_build \ ${additional_flags[*]} - name: Prepare results summary artifact if: ${{ !cancelled() }} @@ -606,6 +651,7 @@ jobs: --artifact_name "ios-${{ matrix.os }}" \ --noadd_timestamp \ --short_output_paths \ + --gha_build \ ${additional_flags[*]} - name: Prepare results summary artifact if: ${{ !cancelled() }} @@ -725,6 +771,7 @@ jobs: --artifact_name "tvos-${{ matrix.os }}" \ --noadd_timestamp \ --short_output_paths \ + --gha_build \ ${additional_flags[*]} - name: Prepare results summary artifact if: ${{ !cancelled() }} @@ -773,7 +820,7 @@ jobs: fi test_desktop: - name: test-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }} + 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() @@ -781,7 +828,32 @@ jobs: 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-latest + arch: arm64 + # Do not attempt to use x86 on Mac. + - os: macos-12 + 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-12 + arch: arm64 steps: - name: setup Xcode version (macos) if: runner.os == 'macOS' @@ -792,12 +864,19 @@ jobs: - name: Download Desktop integration tests artifact uses: actions/download-artifact@v3 with: - path: testapps/testapps-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }} - name: testapps-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }} + 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@v2 with: python-version: ${{ env.pythonVersion }} + - name: install platform support libraries for running + uses: nick-invision/retry@v2 + with: + timeout_minutes: 15 + max_attempts: 3 + command: python scripts/gha/install_prereqs_desktop.py --gha_build --running_only --arch '${{ matrix.arch }}' --ssl '${{ matrix.ssl_variant }}' + - name: Set up Node (12) uses: actions/setup-node@v2 with: @@ -813,31 +892,31 @@ jobs: shell: bash command: | pip install -r scripts/gha/requirements.txt - python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" --artifact "testapps/testapps-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}" + python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" --artifact "testapps/testapps-desktop-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ssl_variant }}" - 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.ssl_variant }}"' + 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.ssl_variant }}" + 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.ssl_variant }}" && ! -f testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}.log.json ]; then - mkdir -p testapps && echo "__SUMMARY_MISSING__" > testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}.log.json + # 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.ssl_variant }}* + 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() }} @@ -859,11 +938,163 @@ jobs: if: ${{ !cancelled() }} shell: bash run: | - cat testapps/test-results-desktop-${{ matrix.os }}-${{ matrix.ssl_variant }}.log + 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-12') && 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-latest + 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-12 + arch: x86 + # Don't run x64 tests on the Mac arm64 runner. + - os: macos-12 + 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-12 + 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@v2 + with: + ref: ${{needs.check_and_prepare.outputs.github_ref}} + - name: Download Desktop integration tests artifact + uses: actions/download-artifact@v2.0.8 + 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 < firebase.json + + 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@v2.2.2 + 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@v2.0.8 + 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 }} needs: [check_and_prepare, build_android] @@ -934,7 +1165,7 @@ jobs: if: ${{ !cancelled() }} shell: bash run: | - # If testapps do not exist, then it's a build error not test error. + # 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 }}.log.json" ]; then mkdir -p testapps && echo "__SUMMARY_MISSING__" > "testapps/test-results-android-${{ matrix.build_os }}-${{ matrix.android_device }}.log.json" fi @@ -1027,7 +1258,7 @@ jobs: uses: google-github-actions/setup-gcloud@v0 - 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 + timeout-minutes: 60 if: steps.get-device-type.outputs.device_type == 'real' run: | python scripts/gha/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" @@ -1040,7 +1271,7 @@ jobs: if: ${{ !cancelled() }} shell: bash run: | - # If testapps do not exist, then it's a build error not test error. + # 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 }}.log.json" ]; then mkdir -p testapps && echo "__SUMMARY_MISSING__" > "testapps/test-results-ios-${{ matrix.build_os }}-${{ matrix.ios_device }}.log.json" fi @@ -1124,7 +1355,7 @@ jobs: if: ${{ !cancelled() }} shell: bash run: | - # If testapps do not exist, then it's a build error not test error. + # 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 @@ -1162,7 +1393,7 @@ jobs: summarize_results: name: "summarize-results" - needs: [check_and_prepare, test_desktop, test_android, test_ios, test_tvos] + needs: [check_and_prepare, test_desktop, test_desktop_custom_runners, test_android, test_ios, test_tvos] runs-on: ubuntu-latest if: ${{ !cancelled() }} steps: diff --git a/scripts/gha/build_desktop.py b/scripts/gha/build_desktop.py index 0a0090f81..b8c1d9f70 100644 --- a/scripts/gha/build_desktop.py +++ b/scripts/gha/build_desktop.py @@ -57,48 +57,6 @@ def append_line_to_file(path, line): file.write("\n" + line + "\n") -def install_x86_support_libraries(gha_build=False): - """Install support libraries needed to build x86 on x86_64 hosts. - - Args: - gha_build: Pass in True if running on a GitHub runner; this will activate - workarounds that might be undesirable on a personal system (e.g. - downgrading Ubuntu packages). - """ - if utils.is_linux_os(): - packages = ['gcc-multilib', 'g++-multilib', 'libglib2.0-dev:i386', - 'libsecret-1-dev:i386', 'libpthread-stubs0-dev:i386', - 'libssl-dev:i386'] - if gha_build: - # Workaround for GitHub runners, which have an incompatibility between the - # 64-bit and 32-bit versions of the Ubuntu package libpcre2-8-0. Downgrade - # the installed 64-bit version of the library to get around this issue. - # This will presumably be fixed in a future Ubuntu update. (If you remove - # it, remove the workaround further down this function as well.) - packages = ['--allow-downgrades'] + packages + ['libpcre2-8-0=10.34-7'] - - # First check if these packages exist on the machine already - devnull = open(os.devnull, "w") - process = subprocess.run(["dpkg", "-s"] + packages, stdout=devnull, stderr=subprocess.STDOUT) - devnull.close() - if process.returncode != 0: - # This implies not all of the required packages are already installed on user's machine - # Install them. - utils.run_command(['dpkg', '--add-architecture', 'i386'], as_root=True, check=True) - utils.run_command(['apt', 'update'], as_root=True, check=True) - utils.run_command(['apt', 'install', '-V', '-y'] + packages, as_root=True, check=True) - - if gha_build: - # One more workaround: downgrading libpcre2-8-0 above may have uninstalled - # libsecret, which is required for the Linux build. Force it to be - # reinstalled, but do it as a separate command to ensure that held - # packages aren't modified. (Once the workaround above is removed, this can - # be removed as well.) - # Note: "-f" = "fix" - let apt do what it needs to do to fix dependencies. - utils.run_command(['apt', 'install', '-f', '-V', '-y', 'libsecret-1-dev'], - as_root=True, check=True) - - def _install_cpp_dependencies_with_vcpkg(arch, msvc_runtime_library, use_openssl=False): """Install packages with vcpkg. diff --git a/scripts/gha/build_testapps.py b/scripts/gha/build_testapps.py index e20326bad..1fea62107 100644 --- a/scripts/gha/build_testapps.py +++ b/scripts/gha/build_testapps.py @@ -73,14 +73,15 @@ """ +import attr import datetime +import json import os import platform import shutil import subprocess import sys -import json -import attr +import tempfile from absl import app from absl import flags @@ -107,7 +108,7 @@ _SUPPORTED_PLATFORMS = (_ANDROID, _IOS, _TVOS, _DESKTOP) # Architecture -_SUPPORTED_ARCHITECTURES = ("x64", "arm64") # TODO: add x86 +_SUPPORTED_ARCHITECTURES = ("x64", "x86", "arm64") # Values for iOS SDK flag (where the iOS app will run) _APPLE_SDK_DEVICE = "real" @@ -175,7 +176,8 @@ flags.DEFINE_string( "arch", "x64", - "(Desktop only) Which architecture to build: x64 (all) or arm64 (Mac only).") + "(Desktop only) Which architecture to build: x64 (all), x86 (Windows/Linux), " + "or arm64 (Mac only).") # Get the number of CPUs for the default value of FLAGS.jobs CPU_COUNT = os.cpu_count(); @@ -219,6 +221,10 @@ "Use short directory names for output paths. Useful to avoid hitting file " "path limits on Windows.") +flags.DEFINE_bool( + "gha_build", False, + "Set to true if this is a GitHub Actions build.") + def main(argv): if len(argv) > 1: raise app.UsageError("Too many command-line arguments.") @@ -261,7 +267,10 @@ def main(argv): if _DESKTOP in platforms and not FLAGS.packaged_sdk: vcpkg_arch = FLAGS.arch installer = os.path.join(repo_dir, "scripts", "gha", "build_desktop.py") - _run([sys.executable, installer, "--vcpkg_step_only", "--arch", vcpkg_arch]) + # --gha_build may be required to enable x86 Linux GitHub workarounds. + additional_flags = ["--gha_build"] if FLAGS.gha_build else [] + _run([sys.executable, installer, "--vcpkg_step_only", "--arch", vcpkg_arch] + + additional_flags) toolchain_file = os.path.join( repo_dir, "external", "vcpkg", "scripts", "buildsystems", "vcpkg.cmake") if utils.is_mac_os() and FLAGS.arch == "arm64": @@ -277,6 +286,23 @@ def main(argv): "-DFIREBASE_PYTHON_HOST_EXECUTABLE:FILEPATH=%s" % sys.executable, )) + if (_DESKTOP in platforms and FLAGS.packaged_sdk and + utils.is_linux_os() and FLAGS.arch == "x86"): + # Write out a temporary toolchain file to force 32-bit Linux builds, as + # the SDK-included toolchain file may not be present when building against + # the packaged SDK. + temp_toolchain_file = tempfile.NamedTemporaryFile("w+", suffix=".cmake") + temp_toolchain_file.writelines([ + 'set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")\n', + 'set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")\n', + 'set(CMAKE_LIBRARY_PATH "/usr/lib/i386-linux-gnu")\n', + 'set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} "/usr/include/i386-linux-gnu")\n']) + temp_toolchain_file.flush() + # Leave the file open, as it will be deleted on close, i.e. when this script exits. + # (On Linux, the file can be opened a second time by cmake while still open by + # this script) + cmake_flags.extend(["-DCMAKE_TOOLCHAIN_FILE=%s" % temp_toolchain_file.name]) + if FLAGS.cmake_flag: cmake_flags.extend(FLAGS.cmake_flag) @@ -466,11 +492,13 @@ def _build_desktop(sdk_dir, cmake_flags): cmake_configure_cmd = ["cmake", ".", "-DCMAKE_BUILD_TYPE=Debug", "-DFIREBASE_CPP_SDK_DIR=" + sdk_dir] if utils.is_windows_os(): - cmake_configure_cmd += ["-A", "x64"] + cmake_configure_cmd += ["-A", + "Win32" if FLAGS.arch == "x86" else FLAGS.arch] elif utils.is_mac_os(): # Ensure that correct Mac architecture is built. cmake_configure_cmd += ["-DCMAKE_OSX_ARCHITECTURES=%s" % ("arm64" if FLAGS.arch == "arm64" else "x86_64")] + _run(cmake_configure_cmd + cmake_flags) _run(["cmake", "--build", ".", "--config", "Debug"] + ["-j", str(FLAGS.jobs)] if FLAGS.jobs > 0 else []) diff --git a/scripts/gha/desktop_tester.py b/scripts/gha/desktop_tester.py index eb7e4806b..5ec302bcd 100644 --- a/scripts/gha/desktop_tester.py +++ b/scripts/gha/desktop_tester.py @@ -44,7 +44,9 @@ "logfile_name", "", "Create test log artifact test-results-$logfile_name.log." " logfile will be created and placed in testapp_dir.") - +flags.DEFINE_string( + "cmd_prefix", "", + "Prefix to include before the command when running each test") def main(argv): if len(argv) > 1: @@ -106,7 +108,7 @@ def run(self): os.chmod(self.testapp_path, 0o777) try: result = subprocess.run( - args=[self.testapp_path], + args=FLAGS.cmd_prefix.split() + [self.testapp_path], cwd=os.path.dirname(self.testapp_path), # Testapp uses CWD for config stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/scripts/gha/print_matrix_configuration.py b/scripts/gha/print_matrix_configuration.py index 4a4dc0597..f411a6d1c 100644 --- a/scripts/gha/print_matrix_configuration.py +++ b/scripts/gha/print_matrix_configuration.py @@ -128,6 +128,8 @@ "android_device": ["android_target", "android_latest", "emulator_target", "emulator_latest", "emulator_32bit"], "ios_device": ["ios_min", "ios_target", "ios_latest", "simulator_min", "simulator_target", "simulator_latest"], "tvos_device": ["tvos_simulator"], + "architecture_windows_linux": ["x64", "x86"], + "architecture_macos": ["x64", "arm64"], } }, "config": {