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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/qa-android-critical-flow-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ on:
- alpha beta
- staging compat
- experimental
- column-1
- column-2
- column-3
- debug
- fdroid
- production
Expand Down Expand Up @@ -243,8 +240,6 @@ jobs:
contents: write

env:
AWS_REGION: eu-west-1
OP_VAULT: "Test Automation"
FLAVORS_CONFIG_PATH: "/etc/android-qa/flavors.json"
DEVICE_GROUPS_JSON: ${{ vars.ANDROID_DEVICE_GROUPS_JSON }}

Expand All @@ -253,6 +248,10 @@ jobs:
shell: bash

steps:
- name: Register log masks
run: |
echo "::add-mask::eu-west-1"

- name: Checkout (with submodules)
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
Expand All @@ -276,7 +275,7 @@ jobs:
run: make qa-ui-setup cmd=ensure-required-tools

# Flavor resolution is runner-driven (from /etc/android-qa/flavors.json), not hardcoded in repo.
# This bash subcommand exports S3_FOLDER, APP_ID, and PACKAGES_TO_UNINSTALL for downstream steps.
# Keep app install data job-wide, but pass the S3 folder only to the download step.
- name: Resolve flavor (runner config)
id: resolve_flavor
env:
Expand All @@ -298,6 +297,7 @@ jobs:
IS_UPGRADE: ${{ needs.validate-and-resolve-inputs.outputs.resolvedIsUpgrade }}
OLD_BUILD_NUMBER: ${{ needs.validate-and-resolve-inputs.outputs.resolvedOldBuildNumber }}
S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
S3_FOLDER: ${{ steps.resolve_flavor.outputs.s3Folder }}
run: make qa-ui-setup cmd=download-apks

# Select device(s): use input device when provided, otherwise auto-pick.
Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/qa-android-ui-test-manual-deflake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ jobs:
actions: read

env:
AWS_REGION: eu-west-1
OP_VAULT: "Test Automation"
FLAVORS_CONFIG_PATH: "/etc/android-qa/flavors.json"
DEVICE_GROUPS_JSON: ${{ vars.ANDROID_DEVICE_GROUPS_JSON }}

Expand All @@ -95,6 +93,10 @@ jobs:
shell: bash

steps:
- name: Register log masks
run: |
echo "::add-mask::eu-west-1"

# Mirror qa-android-critical-flow-tests.yml runner setup so manual
# deflake executes in the same QA office runner environment.
- name: Checkout (with submodules)
Expand Down Expand Up @@ -181,9 +183,10 @@ jobs:
RERUN_FAILED_COUNT: ${{ steps.validate_deflake_input.outputs.rerunFailedCount }}
run: make qa-ui-validate cmd=validate-rerun-inputs

# Reuse the same flavor resolver and APK download path so the deflake run
# stays aligned with qa-android-critical-flow-tests.yml app setup.
# Reuse the same flavor resolver and pass its S3 folder output into the APK
# download step so deflake stays aligned with qa-android-critical-flow-tests.yml.
- name: Resolve flavor (runner config)
id: resolve_flavor
env:
FLAVOR_INPUT: ${{ steps.validate_deflake_input.outputs.flavor }}
run: make qa-ui-setup cmd=resolve-flavor
Expand All @@ -202,6 +205,7 @@ jobs:
IS_UPGRADE: ${{ steps.validate_deflake_input.outputs.isUpgrade }}
OLD_BUILD_NUMBER: ${{ steps.validate_deflake_input.outputs.oldBuildNumber }}
S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
S3_FOLDER: ${{ steps.resolve_flavor.outputs.s3Folder }}
run: make qa-ui-setup cmd=download-apks

# Keep device selection and app installation identical to the selected run
Expand Down
12 changes: 10 additions & 2 deletions scripts/qa/android-ui/resolve_flavor.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,16 @@
print("ERROR: GITHUB_ENV not set", file=sys.stderr)
sys.exit(1)

output_path = os.environ.get("GITHUB_OUTPUT")
if not output_path:
print("ERROR: GITHUB_OUTPUT not set", file=sys.stderr)
sys.exit(1)

with open(env_path, "a", encoding="utf-8") as handle:
# Export variables used by downstream setup/install workflow steps.
handle.write(f"S3_FOLDER={s3}\n")
# Only keep install-related values job-wide.
handle.write(f"APP_ID={app}\n")
handle.write("PACKAGES_TO_UNINSTALL=" + " ".join(pkgs) + "\n")

with open(output_path, "a", encoding="utf-8") as handle:
# Only the download step needs the resolved S3 folder.
handle.write(f"s3Folder={s3}\n")
33 changes: 32 additions & 1 deletion scripts/qa/android-ui/run_ui_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,26 @@ device_reported_zero_tests() {
local log_file="${LOG_DIR}/attempt-${attempt}-instrument-${serial}.log"
[[ -f "${log_file}" ]] || return 1

# Zero-test shards are valid for filtered/sharded runs and should not fail the pull step.
# A device shard can legitimately run zero tests after filtering or sharding.
# In that case it will not produce Allure results, so the pull step should not fail.
grep -qE 'INSTRUMENTATION_STATUS: numtests=0|OK \(0 tests\)|No tests found' "${log_file}"
}

# Treat a zero-test attempt as valid only when every device log for that
# attempt explicitly reported zero tests.
attempt_reported_zero_tests() {
local attempt="$1"
shift
local devices=("$@")
[[ ${#devices[@]} -gt 0 ]] || return 1

for serial in "${devices[@]}"; do
if ! device_reported_zero_tests "${attempt}" "${serial}"; then
return 1
fi
done
}

pull_allure_results_for_attempt() {
local attempt="$1"
shift
Expand Down Expand Up @@ -641,6 +657,21 @@ while true; do
extract_failed_ids "${attempt}" "${attempt_failed_file}" "${attempt_executed_file}"
executed_count="$(wc -l < "${attempt_executed_file}" | tr -d ' ')"
if (( executed_count == 0 )); then
# During reruns, a shard can legitimately end up with no tests assigned.
# Only treat that as valid when every device log explicitly reported
# zero tests and the instrumentation command itself did not fail.
if ! attempt_uses_selector_mode "${attempt}" && attempt_reported_zero_tests "${attempt}" "${attempt_devices[@]}"; then
if (( attempt_worker_failed != 0 )); then
echo "ERROR: Attempt ${attempt} reported zero tests but instrumentation failed."
exit 1
fi
echo "Attempt ${attempt} executed zero tests across all shards."
if [[ ! -f "${first_failed_file}" ]]; then
cp "${attempt_failed_file}" "${first_failed_file}"
fi
current_failed_file="${attempt_failed_file}"
break
fi
echo "ERROR: Attempt ${attempt} produced no identifiable executed tests."
exit 1
fi
Expand Down
Loading