mattermost-mobile-upstream/.github/workflows/compatibility-matrix-testing.yml
yasser khan bcac248ec0
feat(e2e): Integrate TSIO reporting (#9925)
Retire legacy maestro per-platform contexts from cancel-e2e-runs and
document the canonical PR, master, and CMT status context mapping.
Wire Detox + Maestro (PR/main/CMT) into Test System IO with a single
commit status (e2e/mobile; CMT uses e2e/compatibility-matrix-testing)
and groups mobile-pr / mobile-main / cmt-mobile.

Upload shard results with correct framework labels, merge Jest shards
into TSIO Detox shape, stub missing/dead shards as failures, and post
channel summaries after status settles. Matterwick MASTER is treated as
MAIN for mobile-main routing.

Also harden report/fail paths, stage Maestro screenshots per flow for
TSIO galleries, fix a few Detox setup/testID issues, and skip known
platform flakes so the pipeline stays actionable while TSIO lands.
2026-07-23 06:43:28 +00:00

493 lines
20 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Compatibility Matrix Testing
on:
workflow_dispatch:
inputs:
CMT_MATRIX:
description: "A JSON object representing the testing matrix"
required: true
type: string
MOBILE_VERSION:
description: "The mattermost mobile version to test"
required: true
# Cancel overlapping CMT runs for the same ref; matterwick cleans up cancelled servers via workflow_run completed.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
calculate-commit-hash:
runs-on: ubuntu-24.04
outputs:
MOBILE_SHA: ${{ steps.repo.outputs.MOBILE_SHA }}
steps:
- name: cmt/checkout-mobile
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
ref: ${{ inputs.MOBILE_VERSION }}
- name: cmt/calculate-mattermost-sha
id: repo
run: echo "MOBILE_SHA=$(git rev-parse HEAD)" >> ${GITHUB_OUTPUT}
# Phase 5 — computes the TSIO composite identity for this CMT run and the
# per-group totals. Detox runs the FULL CMT_MATRIX (all server versions) across
# 3 platforms (ios/android/ipad) → total = 3 × (#servers). Maestro runs only
# the latest server version(s) across 2 platforms (ios/android) → total =
# 2 × (#latest servers). The orchestrator (update-final-status) and the
# per-platform uploads both consume these outputs.
cmt-identity:
name: Calculate CMT TSIO composite identity
runs-on: ubuntu-24.04
permissions:
contents: read
needs:
- calculate-commit-hash
outputs:
composite-identity-json: ${{ steps.id.outputs.composite-identity-json }}
tsio-config: ${{ steps.id.outputs.tsio-config }}
total-reports-expected: ${{ steps.id.outputs.total-reports-expected }}
steps:
- id: id
env:
CMT_MATRIX: ${{ inputs.CMT_MATRIX }}
GITHUB_REPOSITORY: ${{ github.repository }}
MM_SHA: ${{ needs.calculate-commit-hash.outputs.MOBILE_SHA }}
MOBILE_VERSION: ${{ inputs.MOBILE_VERSION }}
run: |
DETOX_SERVERS=$(echo "$CMT_MATRIX" | jq '.server | length')
MAESTRO_SERVERS=$(echo "$CMT_MATRIX" | jq '[.server[] | select(.latest == true)] | length')
if [ "$MAESTRO_SERVERS" -eq 0 ]; then MAESTRO_SERVERS=1; fi
DETOX_TOTAL=$(( 3 * DETOX_SERVERS ))
MAESTRO_TOTAL=$(( 2 * MAESTRO_SERVERS ))
TOTAL=$(( DETOX_TOTAL + MAESTRO_TOTAL ))
echo "total-reports-expected=$TOTAL" >> "$GITHUB_OUTPUT"
BRANCH=$(echo "$MOBILE_VERSION" | sed 's#^refs/heads/##; s#^refs/tags/##')
BASE=$(jq -nc \
--arg repo "$GITHUB_REPOSITORY" --arg sha "$MM_SHA" --arg run_id "$GITHUB_RUN_ID" \
--arg attempt "$GITHUB_RUN_ATTEMPT" --arg branch "$BRANCH" \
'{repository:$repo, commit_sha:$sha, gh_run_id:$run_id, gh_run_attempt:$attempt, branch:$branch, name:"mobile-release", run_group:"mobile-release", framework:"detox"}')
echo "composite-identity-json=$BASE" >> "$GITHUB_OUTPUT"
TSIO_CONFIG=$(jq -nc --argjson identity "$BASE" --argjson total "$TOTAL" \
'{composite_identity: $identity, total_reports_expected: $total}')
echo "tsio-config=$TSIO_CONFIG" >> "$GITHUB_OUTPUT"
update-initial-status:
runs-on: ubuntu-24.04
permissions:
contents: read
statuses: write
needs:
- calculate-commit-hash
- cmt-identity
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ inputs.MOBILE_VERSION }}
persist-credentials: false
# Pending status uses the TSIO display URL (report fills in as shards upload).
- name: Build TSIO report URL
id: tsio-url
env:
IDENTITY: ${{ needs.cmt-identity.outputs.composite-identity-json }}
run: |
URL=$(jq -nr --argjson id "$IDENTITY" --arg base "https://test-io.test.mattermost.com" '
($id.repository | split("/") | .[-1]) as $repo
| ($id.branch // "main"
| sub("^refs/heads/"; "")
| sub("^refs/tags/"; "")
| gsub("/"; "~")) as $branch
| ($id.commit_sha[0:7]) as $sha
| ($id.run_group // $id.name // "mobile-release") as $name
| "\($base)/reports/\($repo|@uri)/\($branch|@uri)/\($sha)/\($name|@uri)?gh_run_id=\($id.gh_run_id)"
')
echo "target_url=$URL" >> "$GITHUB_OUTPUT"
- uses: ./.github/actions/update-commit-status
if: ${{ needs.calculate-commit-hash.outputs.MOBILE_SHA != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
repository_full_name: ${{ github.repository }}
commit_sha: ${{ needs.calculate-commit-hash.outputs.MOBILE_SHA }}
context: e2e/compatibility-matrix-testing
description: "Compatibility Matrix Testing for ${{ inputs.MOBILE_VERSION }} version"
status: pending
target_url: ${{ steps.tsio-url.outputs.target_url }}
# Maestro only runs against the latest server version; matrix filtering happens here since job-level if: can't access matrix.
prepare-maestro-matrix:
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.filter.outputs.matrix }}
steps:
- name: Filter CMT matrix to latest server only
id: filter
env:
CMT_MATRIX: ${{ inputs.CMT_MATRIX }}
run: |
matrix=$(echo "$CMT_MATRIX" | jq -c '{server: [.server[] | select(.latest == true)]}')
if [ "$(echo "$matrix" | jq '.server | length')" -eq 0 ]; then
matrix=$(echo "$CMT_MATRIX" | jq -c '{server: [.server[-1]]}')
fi
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
# Input follows the below schema
# {
# "server": [
# {
# "version": "9.6.1",
# "url": "https://delivery-cmt-8467830017-9-6-1.test.mattermost.cloud/"
# },
# {
# "version": "9.5.2",
# "url": "https://delivery-cmt-8467830017-9-5-2.test.mattermost.cloud/"
# }
# ]
# }
build-ios-simulator:
# macos-14 predates Xcode 26 and has none pre-installed, so prepare-ios-build's
# Xcode 26 requirement always fails here. e2e-detox-pr.yml and
# e2e-maestro-template.yml already build on macos-26 successfully — match that.
runs-on: macos-26
needs:
- update-initial-status
permissions:
contents: read
actions: write
steps:
- name: Checkout Repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
ref: ${{ inputs.MOBILE_VERSION }}
- name: Prepare iOS Build
uses: ./.github/actions/prepare-ios-build
- name: Build iOS Simulator
env:
TAG: "${{ inputs.MOBILE_VERSION }}"
GITHUB_TOKEN: "${{ secrets.MM_MOBILE_GITHUB_TOKEN }}"
run: bundle exec fastlane ios simulator --env ios.simulator
working-directory: ./fastlane
- name: Upload iOS Simulator Build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-*.app.zip
build-android-apk:
runs-on: ubuntu-latest-8-cores
needs:
- update-initial-status
permissions:
contents: read
actions: write
env:
ORG_GRADLE_PROJECT_jvmargs: -Xmx8g
steps:
- name: Prune Docker to free up space
run: docker system prune -af
- name: Checkout Repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
ref: ${{ inputs.MOBILE_VERSION }}
- name: Prepare Android Build
uses: ./.github/actions/prepare-android-build
env:
STORE_FILE: ${{ secrets.MM_MOBILE_STORE_FILE }}
STORE_ALIAS: ${{ secrets.MM_MOBILE_STORE_ALIAS }}
STORE_PASSWORD: ${{ secrets.MM_MOBILE_STORE_PASSWORD }}
MATTERMOST_BUILD_GH_TOKEN: ${{ secrets.MATTERMOST_BUILD_GH_TOKEN }}
- name: Detox build
run: |
cd detox
npm ci --prefer-offline --no-audit --no-fund
npm run e2e:android-build
- name: Upload Android Build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: android-build-files-${{ github.run_id }}
# Match e2e-detox-pr.yml's glob shape exactly: the wildcard must start
# right after "build/" so upload-artifact only strips "android/app/build/"
# and preserves the outputs/apk/... subtree. e2e-android-template.yml's
# Download APK artifact step (shared by PR + CMT) expects that shape.
path: "android/app/build/**/*"
build-android-apk-maestro:
runs-on: ubuntu-latest-8-cores
needs:
- update-initial-status
permissions:
contents: read
actions: write
env:
ORG_GRADLE_PROJECT_jvmargs: -Xmx8g
steps:
- name: Prune Docker to free up space
run: docker system prune -af
- name: Checkout Repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
ref: ${{ inputs.MOBILE_VERSION }}
- name: Prepare Android Build
uses: ./.github/actions/prepare-android-build
env:
STORE_FILE: ${{ secrets.MM_MOBILE_STORE_FILE }}
STORE_ALIAS: ${{ secrets.MM_MOBILE_STORE_ALIAS }}
STORE_PASSWORD: ${{ secrets.MM_MOBILE_STORE_PASSWORD }}
MATTERMOST_BUILD_GH_TOKEN: ${{ secrets.MATTERMOST_BUILD_GH_TOKEN }}
- name: Build Maestro Android APK
uses: ./.github/actions/build-android-maestro-apk
- name: Upload Maestro Android Build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: android-maestro-build-files-${{ github.run_id }}
path: android/app/build/outputs/apk/release/
# latest entry runs full suite, older entries run smoke only. Job-level if: can't conditionally skip matrix legs, so inputs vary instead.
detox-e2e:
name: mobile-cmt-ios${{ matrix.server.latest && '-full' || '-smoke' }}-${{ matrix.server.version }}
permissions:
contents: read
# nested template mints an OIDC token for the TSIO upload.
id-token: write
actions: read
uses: ./.github/workflows/e2e-ios-template.yml
needs:
- build-ios-simulator
- cmt-identity
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.CMT_MATRIX) }}
secrets:
MM_MOBILE_E2E_ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
MM_MOBILE_E2E_ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
MM_MOBILE_E2E_ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
MM_MOBILE_E2E_ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX: ${{ secrets.MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX }}
MM_MOBILE_E2E_WEBHOOK_URL: ${{ secrets.MM_MOBILE_E2E_WEBHOOK_URL }}
MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
with:
tsio-config: ${{ needs.cmt-identity.outputs.tsio-config }}
tsio-shard-name: detox-ios-Server_${{ matrix.server.version }}
run-type: "RELEASE"
MM_TEST_SERVER_URL: ${{ matrix.server.url }}
MOBILE_VERSION: ${{ inputs.MOBILE_VERSION }}
search_path: ${{ matrix.server.latest && 'detox/e2e/test' || 'detox/e2e/test/products/channels/smoke_test' }}
parallelism: ${{ matrix.server.latest && '10' || '1' }}
artifact_run_id: ${{ github.run_id }}
detox-ipad-e2e:
name: mobile-cmt-ipad-${{ matrix.server.version }}
permissions:
contents: read
id-token: write
actions: read
uses: ./.github/workflows/e2e-ios-template.yml
needs:
- build-ios-simulator
- cmt-identity
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.CMT_MATRIX) }}
secrets:
MM_MOBILE_E2E_ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
MM_MOBILE_E2E_ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
MM_MOBILE_E2E_ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
MM_MOBILE_E2E_ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX: ${{ secrets.MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX }}
MM_MOBILE_E2E_WEBHOOK_URL: ${{ secrets.MM_MOBILE_E2E_WEBHOOK_URL }}
MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
with:
tsio-config: ${{ needs.cmt-identity.outputs.tsio-config }}
tsio-shard-name: detox-ipad-Server_${{ matrix.server.version }}
run-type: "RELEASE"
MM_TEST_SERVER_URL: ${{ matrix.server.url }}
MOBILE_VERSION: ${{ inputs.MOBILE_VERSION }}
ios_device_name: "iPad Pro 13-inch (M5)"
ios_device_os_name: "iOS 26.2"
search_path: "detox/e2e/test/products/channels/ipad"
parallelism: "1"
detox_config: "ios.ipad.debug"
artifact_run_id: ${{ github.run_id }}
# Maestro runs only against the latest server version (no smoke-on-older variant).
maestro-ios-e2e:
name: mobile-cmt-maestro-ios-${{ matrix.server.version }}
permissions:
contents: read
id-token: write
actions: read
uses: ./.github/workflows/e2e-maestro-template.yml
needs:
- build-ios-simulator
- prepare-maestro-matrix
- cmt-identity
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare-maestro-matrix.outputs.matrix) }}
secrets:
MM_MOBILE_E2E_ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
MM_MOBILE_E2E_ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
MM_MOBILE_E2E_ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
MM_MOBILE_E2E_ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
with:
tsio-config: ${{ needs.cmt-identity.outputs.tsio-config }}
tsio-shard-name: maestro-ios-Server_${{ matrix.server.version }}
platform: ios
run-type: "RELEASE"
MM_TEST_SERVER_URL: ${{ matrix.server.url }}
MOBILE_VERSION: ${{ inputs.MOBILE_VERSION }}
record_tests_in_zephyr: true
artifact_run_id: ${{ github.run_id }}
detox-android-e2e:
name: mobile-cmt-android${{ matrix.server.latest && '-full' || '-smoke' }}-${{ matrix.server.version }}
permissions:
contents: read
id-token: write
actions: read
uses: ./.github/workflows/e2e-android-template.yml
needs:
- build-android-apk
- cmt-identity
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.CMT_MATRIX) }}
secrets:
MM_MOBILE_E2E_ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
MM_MOBILE_E2E_ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
MM_MOBILE_E2E_ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
MM_MOBILE_E2E_ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX: ${{ secrets.MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX }}
MM_MOBILE_E2E_WEBHOOK_URL: ${{ secrets.MM_MOBILE_E2E_WEBHOOK_URL }}
MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
with:
tsio-config: ${{ needs.cmt-identity.outputs.tsio-config }}
tsio-shard-name: detox-android-Server_${{ matrix.server.version }}
run-android-tests: true
run-type: "RELEASE"
MM_TEST_SERVER_URL: ${{ matrix.server.url }}
MOBILE_VERSION: ${{ inputs.MOBILE_VERSION }}
search_path: ${{ matrix.server.latest && 'detox/e2e/test' || 'detox/e2e/test/products/channels/smoke_test' }}
parallelism: ${{ matrix.server.latest && '10' || '1' }}
artifact_run_id: ${{ github.run_id }}
# Maestro runs only against the latest server version (no smoke-on-older variant).
maestro-android-e2e:
name: mobile-cmt-maestro-android-${{ matrix.server.version }}
permissions:
contents: read
id-token: write
actions: read
uses: ./.github/workflows/e2e-maestro-template.yml
needs:
- build-android-apk-maestro
- prepare-maestro-matrix
- cmt-identity
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare-maestro-matrix.outputs.matrix) }}
secrets:
MM_MOBILE_E2E_ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
MM_MOBILE_E2E_ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
MM_MOBILE_E2E_ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
MM_MOBILE_E2E_ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
with:
tsio-config: ${{ needs.cmt-identity.outputs.tsio-config }}
tsio-shard-name: maestro-android-Server_${{ matrix.server.version }}
platform: android
run-type: "RELEASE"
MM_TEST_SERVER_URL: ${{ matrix.server.url }}
MOBILE_VERSION: ${{ inputs.MOBILE_VERSION }}
artifact_run_id: ${{ github.run_id }}
record_tests_in_zephyr: true
update-final-status:
runs-on: ubuntu-24.04
if: always()
permissions:
contents: read
# posts the combined commit status.
statuses: write
# mints the OIDC token used to recover the TSIO report group ids.
id-token: write
actions: read
needs:
- cmt-identity
- calculate-commit-hash
- detox-e2e
- detox-android-e2e
- detox-ipad-e2e
- maestro-ios-e2e
- maestro-android-e2e
steps:
- name: Sparse checkout TSIO status utility
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ inputs.MOBILE_VERSION }}
persist-credentials: false
sparse-checkout: |
detox/utils/tsio-report-status.js
detox/utils/cmt-channel-notify.js
detox/utils/cli-args.js
- name: Post TSIO commit status from unified CMT report group
env:
GITHUB_TOKEN: ${{ github.token }}
COMPOSITE_IDENTITY: ${{ needs.cmt-identity.outputs.composite-identity-json }}
TOTAL_REPORTS_EXPECTED: ${{ needs.cmt-identity.outputs.total-reports-expected }}
# Incoming webhook for the Mobile CMT/RC results channel (separate from
# PR MM_MOBILE_E2E_WEBHOOK_URL and main MM_E2E_MASTER_HEALTH_WEBHOOK_URL).
# Optional — when unset, TSIO status still flips and channel notify is skipped.
MATTERMOST_CMT_WEBHOOK_URL: ${{ secrets.MM_E2E_RELEASE_WEBHOOK_URL }}
run: |
set +e
UPSTREAM="true"
for r in "${{ needs.detox-e2e.result }}" "${{ needs.detox-android-e2e.result }}" "${{ needs.detox-ipad-e2e.result }}" "${{ needs.maestro-ios-e2e.result }}" "${{ needs.maestro-android-e2e.result }}"; do
case "$r" in
success|skipped) ;;
*) UPSTREAM="false" ;;
esac
done
node detox/utils/tsio-report-status.js \
--composite-identity="$COMPOSITE_IDENTITY" \
--total-reports-expected="$TOTAL_REPORTS_EXPECTED" \
--github-token="$GITHUB_TOKEN" \
--context="e2e/compatibility-matrix-testing" \
--upstream-succeeded="$UPSTREAM" \
--poll-attempts=24
RC=$?
echo "tsio-report-status exit=$RC upstream_succeeded=$UPSTREAM"
if [ "$RC" -ne 0 ] && [ "$UPSTREAM" = "true" ]; then
echo "::error::TSIO reported test failures (exit $RC) with all upstream jobs succeeded."
exit 1
fi
exit 0
# Instance cleanup is handled by matterwick on workflow_run completed.