Skip to content

chore: add test sharding to unit tests #17746

chore: add test sharding to unit tests

chore: add test sharding to unit tests #17746

Workflow file for this run

on:
pull_request:
branches:
- main
- preview
# Trigger workflow on GitHub merge queue events
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#merge_group
merge_group:
types: [checks_requested]
name: unittest
permissions:
contents: read
jobs:
initialize:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
is_full_run: ${{ steps.check-label.outputs.is_full_run }}
env:
MAX_SHARDS: 20
# Define weights for long-running unit tests to balance shard execution time
# Each weight is roughly 1 minute of expected execution time
# Default for unset packages is 1
PACKAGE_WEIGHTS: |
bigframes: 6
google-ai-generativelanguage: 4
google-auth: 5
google-cloud-compute: 12
google-cloud-compute-v1beta: 12
google-cloud-dialogflow: 6
google-cloud-dialogflow-cx: 6
google-cloud-discoveryengine: 8
google-cloud-retail: 5
google-shopping-merchant-accounts: 4
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for unit_test:all_packages label
id: check-label
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'unit_test:all_packages') }}" == "true" ]]; then
echo "is_full_run=true" >> $GITHUB_OUTPUT
else
echo "is_full_run=false" >> $GITHUB_OUTPUT
fi
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Get package shards
id: set-matrix
env:
BUILD_TYPE: presubmit
TARGET_BRANCH: ${{ github.base_ref || github.event.merge_group.base_ref }}
TEST_ALL_PACKAGES: ${{ steps.check-label.outputs.is_full_run }}
MAX_SHARDS: ${{ env.MAX_SHARDS }}
PACKAGE_WEIGHTS: ${{ env.PACKAGE_WEIGHTS }}
run: |
if [ -n "$TARGET_BRANCH" ]; then
git fetch origin "$TARGET_BRANCH" --deepen=200 || true
fi
python3 ci/get_package_shards.py
unit:
needs: initialize
if: needs.initialize.outputs.matrix != '[]' && needs.initialize.outputs.matrix != ''
runs-on: ubuntu-22.04
strategy:
fail-fast: true
matrix:
python: ['3.10', "3.11", "3.12", "3.13", "3.14"]
package_shard: ${{ fromJson(needs.initialize.outputs.matrix) }}
name: ${{ matrix.package_shard.is_sharded && format('unit ({0}, {1})', matrix.python, matrix.package_shard.name) || format('unit ({0})', matrix.python) }}
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
# Use a fetch-depth of 2 to avoid error `fatal: origin/main...HEAD: no merge base`
# See https://github.com/googleapis/google-cloud-python/issues/12013
# and https://github.com/actions/checkout#checkout-head.
with:
fetch-depth: 2
persist-credentials: false
- name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: ${{ matrix.python }}
cache: 'pip'
- name: Install nox
run: |
python -m pip install --upgrade setuptools pip wheel
python -m pip install nox
- name: Run unit tests for ${{ matrix.package_shard.description }}
env:
BUILD_TYPE: presubmit
TARGET_BRANCH: ${{ github.base_ref || github.event.merge_group.base_ref }}
TEST_TYPE: unit
PY_VERSION: ${{ matrix.python }}
PACKAGE_LIST: ${{ matrix.package_shard.packages }}
run: |
ci/run_conditional_tests.sh
- name: Upload coverage results
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: coverage-artifact-${{ matrix.python }}-${{ matrix.package_shard.index }}
path: .coverage.${{ matrix.python }}.*
include-hidden-files: true
all-tests:
needs: [initialize, unit]
if: always()
runs-on: ubuntu-latest
steps:
- name: Check unit test results
run: |
# 1. Check initialize job
if [[ "${{ needs.initialize.result }}" != "success" ]]; then
echo "Error: The initialize job status was: ${{ needs.initialize.result }}"
exit 1
fi
# 2. Check unit test shards
if [[ "${{ needs.unit.result }}" != "success" && "${{ needs.unit.result }}" != "skipped" ]]; then
echo "Unit tests failed"
exit 1
fi
echo "All unit tests passed or were skipped"
cover:
runs-on: ubuntu-latest
needs:
- unit
- initialize
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
# Use a fetch-depth of 2 to avoid error `fatal: origin/main...HEAD: no merge base`
# See https://github.com/googleapis/google-cloud-python/issues/12013
# and https://github.com/actions/checkout#checkout-head.
with:
fetch-depth: 2
persist-credentials: false
- name: Setup Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.10"
- name: Set number of files changes in packages directory
id: packages
env:
TEST_ALL_PACKAGES: ${{ needs.initialize.outputs.is_full_run }}
run: |
if [[ "${TEST_ALL_PACKAGES}" == "true" ]]; then
echo "num_files_changed=1" >> "$GITHUB_OUTPUT"
else
git diff HEAD~1 -- packages > /dev/null
num_files_changed=$(git diff HEAD~1 -- packages | wc -l | tr -d ' ')
echo "num_files_changed=${num_files_changed}" >> "$GITHUB_OUTPUT"
fi
- name: Install coverage
if: ${{ steps.packages.outputs.num_files_changed > 0 }}
run: |
python -m pip install --upgrade setuptools pip wheel
python -m pip install coverage
- name: Download coverage results
if: ${{ steps.packages.outputs.num_files_changed > 0 }}
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
path: /dev/shm/.coverage-results/
merge-multiple: true
- name: Report coverage results
if: ${{ steps.packages.outputs.num_files_changed > 0 }}
env:
# TODO: default to 100% coverage after next gapic-generator release
# https://github.com/googleapis/google-cloud-python/issues/17459
DEFAULT_FAIL_UNDER: 99
TEST_ALL_PACKAGES: ${{ needs.initialize.outputs.is_full_run }}
run: |
ci/report_coverage.sh