Skip to content
Draft
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
70 changes: 59 additions & 11 deletions .github/workflows/e2e-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
uses: ./.github/workflows/skip-ci-noauth.yml
secrets: inherit
metrics:
runs-on: ${{ matrix.runs-on }}
runs-on: ${{ matrix.runner_provider == 'bitrise' && fromJSON('["bitrise_pool_name:tahoe"]') || matrix.runs-on }}
continue-on-error: ${{ matrix.runner_provider == 'bitrise' }}
needs: [diff_check, detect-changes, auth_token_check]
if: ${{ needs.diff_check.outputs.skip_ci != 'true' && needs.auth_token_check.outputs.skip_ci != 'true' && !startsWith(github.ref, 'refs/heads/release/') }}
env:
Expand All @@ -52,7 +53,8 @@
matrix:
rn-architecture: ['legacy', 'new']
platform: ["ios", "android"]
runner_provider: ["cirrus", "bitrise"]
include:

Check warning on line 57 in .github/workflows/e2e-v2.yml

View check run for this annotation

@sentry/warden / warden: code-review

`max-parallel: 2` can be consumed by queued unprovisioned bitrise jobs, starving cirrus work

The `metrics` job sets `max-parallel: 2` to stay under Sauce Labs' 3-session limit. With the new `runner_provider` dimension, the iOS matrix now creates 2 bitrise jobs (one per `rn-architecture`) that target the unprovisioned `bitrise_pool_name:tahoe` runner. GitHub Actions counts jobs that are dispatched-but-queued (waiting for a runner) against `max-parallel`. If GitHub schedules the 2 bitrise iOS jobs first, they can occupy both parallel slots while sitting in the queue indefinitely (no runner exists), preventing the executable cirrus iOS/Android jobs from starting until the queued jobs time out. `continue-on-error: true` handles eventual failure but does not relieve the wall-clock blocking while the bitrise jobs wait. Note: scheduling order is non-deterministic, so this starvation will not occur on every run.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max-parallel: 2 can be consumed by queued unprovisioned bitrise jobs, starving cirrus work

The metrics job sets max-parallel: 2 to stay under Sauce Labs' 3-session limit. With the new runner_provider dimension, the iOS matrix now creates 2 bitrise jobs (one per rn-architecture) that target the unprovisioned bitrise_pool_name:tahoe runner. GitHub Actions counts jobs that are dispatched-but-queued (waiting for a runner) against max-parallel. If GitHub schedules the 2 bitrise iOS jobs first, they can occupy both parallel slots while sitting in the queue indefinitely (no runner exists), preventing the executable cirrus iOS/Android jobs from starting until the queued jobs time out. continue-on-error: true handles eventual failure but does not relieve the wall-clock blocking while the bitrise jobs wait. Note: scheduling order is non-deterministic, so this starvation will not occur on every run.

Evidence
  • e2e-v2.yml metrics job sets max-parallel: 2 with matrix runner_provider: ["cirrus", "bitrise"] and excludes only android+bitrise, yielding 2 bitrise iOS jobs (one per rn-architecture).
  • runs-on resolves to ["bitrise_pool_name:tahoe"] for bitrise jobs, an unprovisioned pool per the PR description, so those jobs queue with no runner to pick them up.
  • The per-platform skip is implemented as step-level if: conditions (e.g. platform-check), not a job-level gate, so all matrix jobs (including bitrise) are still created and occupy scheduling slots.
  • GitHub Actions counts dispatched-but-queued jobs against max-parallel; if the 2 bitrise jobs are scheduled first they fill both slots until they time out, blocking cirrus jobs that could actually run.

Identified by Warden code-review · CY2-CUC

- platform: ios
runs-on: ["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]
name: iOS
Expand All @@ -61,6 +63,9 @@
runs-on: ["ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04", "runner_group_id:10"]
name: Android
appPlain: performance-tests/TestAppPlain/android/app/build/outputs/apk/release/app-release.apk
exclude:
- platform: android
runner_provider: bitrise
steps:
- name: Check if platform is needed
id: platform-check
Expand Down Expand Up @@ -113,8 +118,23 @@
if: ${{ steps.platform-check.outputs.skip != 'true' }}
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6

- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
- uses: actions/cache@v4
name: Cache Ruby
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.platform == 'ios' }}
with:
path: |
~/.rbenv/versions
~/.rbenv/cache
key: ruby-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.ruby-version') }}

- name: Install Ruby (Bitrise)
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.platform == 'ios' && matrix.runner_provider == 'bitrise' }}
run: |
brew upgrade ruby-build
rbenv install -s

- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.platform == 'ios' && matrix.runner_provider != 'bitrise' }}
with:
ruby-version: '3.3.0'

Expand Down Expand Up @@ -215,8 +235,9 @@
sauce-key: ${{ secrets.SAUCE_ACCESS_KEY }}

react-native-build:
name: Build RN ${{ matrix.rn-version }} ${{ matrix.rn-architecture }} ${{ matrix.engine }} ${{ matrix.platform }} ${{ matrix.build-type }} ${{ matrix.ios-use-frameworks }}
runs-on: ${{ matrix.runs-on }}
name: Build RN ${{ matrix.rn-version }} ${{ matrix.rn-architecture }} ${{ matrix.engine }} ${{ matrix.platform }} ${{ matrix.build-type }} ${{ matrix.ios-use-frameworks }} on ${{matrix.runner_provider}}
runs-on: ${{ matrix.runner_provider == 'bitrise' && fromJSON(format('["bitrise_pool_name:{0}"]', matrix.macos_version)) || matrix.runs-on }}
continue-on-error: ${{ matrix.runner_provider == 'bitrise' }}
needs: [diff_check, detect-changes, auth_token_check]
if: ${{ needs.diff_check.outputs.skip_ci != 'true' && needs.auth_token_check.outputs.skip_ci != 'true' && !startsWith(github.ref, 'refs/heads/release/') }}
env:
Expand All @@ -235,17 +256,21 @@
build-type: ['production']
ios-use-frameworks: ['no', 'static', 'dynamic']
engine: ['hermes']
runner_provider: ['cirrus', 'bitrise']
include:
# Use Xcode 16 for older RN versions
- platform: ios
rn-version: '0.71.19'
runs-on: ["ghcr.io/cirruslabs/macos-sequoia-xcode:16.4", "runner_group_id:10"]
macos_version: sequoia
# Use Xcode 26 for newer RN versions (0.83.0)
- platform: ios
rn-version: '0.85.1'
runs-on: ["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]
macos_version: tahoe
- platform: android
runs-on: ["ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04", "runner_group_id:10"]
macos_version: none
exclude:
# exclude all rn versions lower than 0.80.0 for new architecture
- rn-version: '0.71.19'
Expand All @@ -270,6 +295,9 @@
- rn-version: '0.82.1'
platform: 'ios'
ios-use-frameworks: 'dynamic'
# only run bitrise for macOS (iOS) jobs
- platform: 'android'
runner_provider: 'bitrise'

steps:
- name: Check if platform is needed
Expand Down Expand Up @@ -348,8 +376,23 @@
if: ${{ steps.platform-check.outputs.skip != 'true' }}
run: yarn install

- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
- uses: actions/cache@v4
name: Cache Ruby
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.platform == 'ios' }}
with:
path: |
~/.rbenv/versions
~/.rbenv/cache
key: ruby-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.ruby-version') }}

- name: Install Ruby (Bitrise)
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.platform == 'ios' && matrix.runner_provider == 'bitrise' }}
run: |
brew upgrade ruby-build
rbenv install -s

- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.platform == 'ios' && matrix.runner_provider != 'bitrise' }}
with:
ruby-version: '3.3.0'

Expand All @@ -365,25 +408,26 @@
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.build-type == 'production' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-app-package
name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-${{ matrix.runner_provider }}-app-package
path: dev-packages/e2e-tests/RnDiffApp.ap*
retention-days: 1

- name: Upload logs
if: ${{ always() && steps.platform-check.outputs.skip != 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: rn-build-logs-${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}
name: rn-build-logs-${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-${{ matrix.runner_provider }}
path: dev-packages/e2e-tests/react-native-versions/${{ matrix.rn-version }}/RnDiffApp/ios/*.log

react-native-test:
name:
Test RN ${{ matrix.rn-version }} ${{ matrix.rn-architecture }} ${{ matrix.engine }} ${{ matrix.platform }} ${{
matrix.build-type }} ${{ matrix.ios-use-frameworks }}
matrix.build-type }} ${{ matrix.ios-use-frameworks }} on ${{matrix.runner_provider}}
needs: [react-native-build, diff_check, detect-changes]
if: ${{ needs.diff_check.outputs.skip_ci != 'true' }}

runs-on: ${{ matrix.runs-on }}
runs-on: ${{ matrix.runner_provider == 'bitrise' && fromJSON('["bitrise_pool_name:tahoe"]') || matrix.runs-on }}
continue-on-error: ${{ matrix.runner_provider == 'bitrise' }}
strategy:
fail-fast: false # keeps matrix running if one fails
matrix:
Expand All @@ -393,12 +437,16 @@
build-type: ['production']
ios-use-frameworks: ['no'] # test only no frameworks
engine: ['hermes']
runner_provider: ['cirrus', 'bitrise']
include:
- platform: ios
rn-version: '0.85.1'
runs-on: ["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]
- platform: android
runs-on: ["ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04", "runner_group_id:10"]
exclude:
- platform: android
runner_provider: bitrise

steps:
- name: Check if platform is needed
Expand Down Expand Up @@ -438,7 +486,7 @@
if: ${{ steps.platform-check.outputs.skip != 'true' && matrix.build-type == 'production' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-app-package
name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-${{ matrix.runner_provider }}-app-package
path: dev-packages/e2e-tests

- name: Enable Corepack
Expand Down Expand Up @@ -538,6 +586,6 @@
if: ${{ always() && steps.platform-check.outputs.skip != 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-logs
name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.engine }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks }}-${{ matrix.runner_provider }}-logs
path: |
./dev-packages/e2e-tests/maestro-logs
24 changes: 22 additions & 2 deletions .github/workflows/native-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@
caller_ref: ${{ github.ref }}

test-ios:
name: ios
runs-on: ["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]
name: ios on ${{matrix.runner_provider}}
runs-on: ${{ matrix.runner_provider == 'bitrise' && fromJSON('["bitrise_pool_name:tahoe"]') || fromJSON('["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]') }}
continue-on-error: ${{ matrix.runner_provider == 'bitrise' }}
needs: [diff_check, detect-changes]
if: ${{ needs.diff_check.outputs.skip_ci != 'true' && needs.detect-changes.outputs.needs_ios == 'true' }}
strategy:
fail-fast: false
matrix:
runner_provider: ["cirrus", "bitrise"]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6

Expand All @@ -51,7 +56,22 @@
- name: Install SDK JS Dependencies
run: yarn install

- uses: actions/cache@v4
name: Cache Ruby
with:
path: |

Check warning on line 62 in .github/workflows/native-tests.yml

View check run for this annotation

@sentry/warden / warden: find-bugs

New `actions/cache@v4` steps use floating version tag instead of pinned commit SHA

The newly added `Cache Ruby` steps reference `actions/cache@v4` without a commit SHA, while every other action reference in these workflows (e.g. `actions/cache@27d5ce7f…`, `actions/checkout@df4cb1c…`) uses a pinned SHA. A tag mutation or compromise of the `v4` ref could execute arbitrary code on the runner with access to the environment, including secrets like `SENTRY_AUTH_TOKEN` and signing credentials (`MATCH_PASSWORD`, `MATCH_GIT_PRIVATE_KEY`).
~/.rbenv/versions
~/.rbenv/cache
key: ruby-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.ruby-version') }}

- name: Install Ruby (Bitrise)
if: matrix.runner_provider == 'bitrise'
run: |
brew upgrade ruby-build
rbenv install -s

- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
if: matrix.runner_provider != 'bitrise'
with:
ruby-version: '3.3.0'
env:
Expand Down
25 changes: 22 additions & 3 deletions .github/workflows/sample-application-expo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ jobs:
caller_ref: ${{ github.ref }}

build-ios:
name: Build ios ${{ matrix.build-type }} ${{ matrix.ios-use-frameworks }}
runs-on: ["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]
name: Build ios ${{ matrix.build-type }} ${{ matrix.ios-use-frameworks }} on ${{matrix.runner_provider}}
runs-on: ${{ matrix.runner_provider == 'bitrise' && fromJSON('["bitrise_pool_name:tahoe"]') || fromJSON('["ghcr.io/cirruslabs/macos-tahoe-xcode:26.2.0", "runner_group_id:10"]') }}
continue-on-error: ${{ matrix.runner_provider == 'bitrise' }}
needs: [diff_check, detect-changes]
if: >-
${{
Expand All @@ -51,6 +52,7 @@ jobs:
matrix:
ios-use-frameworks: ['no-frameworks', 'dynamic-frameworks']
build-type: ['dev', 'production']
runner_provider: ['cirrus', 'bitrise']
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6

Expand All @@ -64,7 +66,24 @@ jobs:
cache: 'yarn'
cache-dependency-path: yarn.lock

- uses: actions/cache@v4
name: Cache Ruby
with:
path: |
~/.rbenv/versions
~/.rbenv/cache
key: ruby-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.ruby-version') }}

- name: Install Ruby (Bitrise)
if: matrix.runner_provider == 'bitrise'
working-directory: samples/expo
run: |
brew upgrade ruby-build
rbenv install -s
bundle install

- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
if: matrix.runner_provider != 'bitrise'
with:
working-directory: samples/expo
ruby-version: '3.3.0' # based on what is used in the sample
Expand Down Expand Up @@ -129,7 +148,7 @@ jobs:
if: ${{ always() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: build-sample-expo-ios-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-logs
name: build-sample-expo-ios-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-${{ matrix.runner_provider }}-logs
path: samples/expo/ios/*.log

build-android:
Expand Down
Loading
Loading