Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6ff87a3
ci: temp e2e workflow
MrMuzyk Oct 13, 2026
c5fa84d
Merge branch 'callstack:main' into main
MrMuzyk Oct 16, 2026
4feac60
feat: repack e2e tests
MrMuzyk Oct 13, 2026
e0a0ea5
Merge branch 'main' into e2e-ci
MrMuzyk Oct 19, 2026
0254419
fix: CR fixes
MrMuzyk Oct 19, 2026
da3f15e
fix: pin ruby
MrMuzyk Oct 19, 2026
53bca6d
fix: warn
MrMuzyk Oct 19, 2026
62fd861
fix: cr fixes v2
MrMuzyk Oct 20, 2026
31c9af0
feat: More features in MF2 test app
MrMuzyk Oct 23, 2026
b8b4207
Merge branch 'main' of github.com:MrMuzyk/repack into e2e-ci
MrMuzyk Oct 23, 2026
144812f
fix: lock
MrMuzyk Oct 23, 2026
e010c48
Merge branch 'e2e-ci' of github.com:MrMuzyk/repack into add-more-feat…
MrMuzyk Oct 23, 2026
46a7e94
feat: plugins
MrMuzyk Oct 26, 2026
dde9e4c
fix: prettier
MrMuzyk Oct 26, 2026
f84e401
Merge branch 'main' of github.com:MrMuzyk/repack into add-more-featur…
MrMuzyk Oct 26, 2026
4354599
fix: ids
MrMuzyk Oct 26, 2026
1612757
feat: assets tests
MrMuzyk Oct 27, 2026
e78ecbc
fix: prettier
MrMuzyk Oct 27, 2026
1ffeb98
feat: svgr
MrMuzyk Oct 28, 2026
9139910
fix: configs
MrMuzyk Oct 28, 2026
cae130c
feat: design doc and some cleanup of duplicated tests
MrMuzyk Oct 28, 2026
5bb638f
fix: final touches
MrMuzyk Oct 29, 2026
d2074ff
fix: timeout as android is slower
MrMuzyk Oct 29, 2026
351a1ef
fix: reduce motion warning
MrMuzyk Oct 29, 2026
746a7d5
fix: failing android run
MrMuzyk Oct 30, 2026
66a9047
fix: added some missing debugging logs and fixed some minor stuff
MrMuzyk Oct 30, 2026
26e17ef
feat: Update tester-expo app and cover it with e2e tests
MrMuzyk Nov 3, 2026
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
238 changes: 238 additions & 0 deletions .github/workflows/e2e-expo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
name: e2e (Expo)

on:
pull_request:
paths-ignore:
- 'website/**'
- '**/*.md'
push:
branches: [main]
paths-ignore:
- 'website/**'
- '**/*.md'
workflow_dispatch:

# one run per PR; a new push cancels the older one
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name != 'push' }}

# keep it read-only
permissions:
contents: read

env:
E2E_TELEMETRY_DISABLED: '1'

jobs:
android:
name: e2e-expo (Android)
runs-on: ubuntu-latest
timeout-minutes: 45

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2

- name: Setup workspace
uses: ./.github/actions/setup-pnpm-node
with:
node-version: '24.22.1'

- name: Setup Java
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # tag=v6.0.1
with:
distribution: temurin
java-version: '17'

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Build workspace packages
run: pnpm --filter tester-expo... --filter tester-expo-widget... --filter tester-federation-v2... build

# android/ is generated, never committed
- name: Generate native project
run: pnpm --filter tester-expo exec expo prebuild --platform android --no-install

# nohup/disown: the runner kills step processes at the end
- name: Start dev servers
run: |
nohup pnpm --filter tester-expo repack:start > /tmp/host.log 2>&1 &
disown
nohup pnpm --filter tester-expo-widget repack:start:remote > /tmp/expo-widget.log 2>&1 &
disown
nohup pnpm --filter tester-federation-v2 start:expo-host-widget > /tmp/ordinary-widget.log 2>&1 &
disown
timeout 180 sh -c 'until [ "$(curl -sf localhost:8081/status)" = "packager-status:running" ] && [ "$(curl -sf localhost:8082/status)" = "packager-status:running" ] && [ "$(curl -sf localhost:8083/status)" = "packager-status:running" ]; do sleep 2; done'

# ask for the bundles now so the servers compile them — they only build on first request
- name: Warm all compilers
run: |
curl -sf --max-time 300 -o /dev/null 'http://localhost:8081/index.bundle?platform=android&dev=true&lazy=true&minify=false&app=com.callstack.repackexpo&modulesOnly=false&runModule=true'
curl -sf --max-time 300 -o /dev/null 'http://localhost:8082/android/mf-manifest.json'
curl -sf --max-time 300 -o /dev/null 'http://localhost:8083/android/mf-manifest.json'
echo 'All three served; compilers are warm.'

- name: Check shared versions are real semver
run: |
for p in 8081 8082; do
M=$(curl -sf --retry 3 --retry-delay 2 "http://localhost:$p/android/mf-manifest.json") || { echo "::error::port $p: mf-manifest.json not served"; exit 1; }
[ "$(jq '.shared | length' <<<"$M")" -gt 0 ] || { echo "::error::port $p: manifest has no shared entries"; exit 1; }
BAD=$(jq -r '.shared[] | select((.version // "") | test("^[0-9]+\\.[0-9]+\\.[0-9]+") | not) | "\(.name): \(.version)"' <<<"$M")
[ -z "$BAD" ] || { echo "::error::port $p has non-semver shared versions: $BAD"; exit 1; }
done

- name: Build Android app
working-directory: apps/tester-expo/android
run: ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86_64

# expose dev servers to the emulator, install the APK, run the tests
- name: Run e2e on an emulator
uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # tag=v2.38.0
with:
api-level: 35
target: google_apis
arch: x86_64
profile: pixel_7
avd-name: e2e
disable-animations: false
working-directory: apps/tester-expo
script: |
adb shell settings put global hide_error_dialogs 1
for i in 1 2 3; do adb shell "uiautomator dump /sdcard/d.xml >/dev/null && grep -q aerr_ /sdcard/d.xml" && { echo 'ANR dialog on screen, clearing it'; adb shell am force-stop com.google.android.apps.nexuslauncher; }; sleep 2; done
adb reverse tcp:8081 tcp:8081
adb reverse tcp:8082 tcp:8082
adb reverse tcp:8083 tcp:8083
adb reverse --list
adb reverse --list | grep -q 'tcp:8081' || { echo '::error::adb reverse missing for tcp:8081'; exit 1; }
adb reverse --list | grep -q 'tcp:8082' || { echo '::error::adb reverse missing for tcp:8082'; exit 1; }
adb reverse --list | grep -q 'tcp:8083' || { echo '::error::adb reverse missing for tcp:8083'; exit 1; }
adb install -r -g android/app/build/outputs/apk/debug/app-debug.apk || { echo '::error::adb install failed'; exit 1; }
E2E_DEVICE="${ANDROID_SERIAL:-$(adb get-serialno)}" pnpm exec e2e run --target android --reporter list,junit; ec=$?; adb logcat -d -v time > .e2e/logcat.txt 2>&1; exit $ec

- name: Collect dev server logs
if: ${{ !cancelled() }}
working-directory: apps/tester-expo
run: |
mkdir -p .e2e
cp /tmp/host.log /tmp/expo-widget.log /tmp/ordinary-widget.log .e2e/

- name: Upload e2e artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1
with:
name: e2e-expo-android
path: apps/tester-expo/.e2e
include-hidden-files: true
if-no-files-found: warn
retention-days: 7

- name: Show dev server logs
if: ${{ !cancelled() }}
run: tail -n 80 /tmp/host.log /tmp/expo-widget.log /tmp/ordinary-widget.log

# main + dispatch only
ios:
name: e2e-expo (iOS)
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: macos-15
timeout-minutes: 45

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2

- name: Setup workspace
uses: ./.github/actions/setup-pnpm-node
with:
node-version: '24.22.1'

- name: Build workspace packages
run: pnpm --filter tester-expo... --filter tester-expo-widget... --filter tester-federation-v2... build

- name: Start dev servers
run: |
nohup pnpm --filter tester-expo repack:start > /tmp/host.log 2>&1 &
disown
nohup pnpm --filter tester-expo-widget repack:start:remote > /tmp/expo-widget.log 2>&1 &
disown
nohup pnpm --filter tester-federation-v2 start:expo-host-widget > /tmp/ordinary-widget.log 2>&1 &
disown
for p in 8081 8082 8083; do curl -sf --retry 90 --retry-delay 2 --retry-all-errors --retry-connrefused -o /dev/null "http://localhost:$p/status"; done

- name: Warm all compilers
run: |
curl -sf --max-time 300 -o /dev/null 'http://localhost:8081/index.bundle?platform=ios&dev=true&lazy=true&minify=false&app=com.callstack.repackexpo&modulesOnly=false&runModule=true'
curl -sf --max-time 300 -o /dev/null 'http://localhost:8082/ios/mf-manifest.json'
curl -sf --max-time 300 -o /dev/null 'http://localhost:8083/ios/mf-manifest.json'
echo 'All three served; compilers are warm.'

- name: Check shared versions are real semver
run: |
for p in 8081 8082; do
M=$(curl -sf --retry 3 --retry-delay 2 "http://localhost:$p/ios/mf-manifest.json") || { echo "::error::port $p: mf-manifest.json not served"; exit 1; }
[ "$(jq '.shared | length' <<<"$M")" -gt 0 ] || { echo "::error::port $p: manifest has no shared entries"; exit 1; }
BAD=$(jq -r '.shared[] | select((.version // "") | test("^[0-9]+\\.[0-9]+\\.[0-9]+") | not) | "\(.name): \(.version)"' <<<"$M")
[ -z "$BAD" ] || { echo "::error::port $p has non-semver shared versions: $BAD"; exit 1; }
done

# SIM_RUNTIME_PREFIX is tied to the runner image
- name: Boot simulator
env:
SIM_RUNTIME_PREFIX: com.apple.CoreSimulator.SimRuntime.iOS-18-
SIM_DEVICE: iPhone 16
run: |
RT=$(xcrun simctl list runtimes -j | jq -r --arg prefix "$SIM_RUNTIME_PREFIX" '.runtimes | map(select(.isAvailable and (.identifier | startswith($prefix)))) | sort_by(.version) | last | .identifier')
echo "using $RT"
[ "$RT" != "null" ] && [ -n "$RT" ]
xcrun simctl create e2e "$SIM_DEVICE" "$RT"
xcrun simctl boot e2e
xcrun simctl bootstatus e2e -b

# ios/ is generated, never committed
- name: Generate native project
run: pnpm --filter tester-expo exec expo prebuild --platform ios --no-install

# CocoaPods needs a UTF-8 locale
- name: Build iOS app
working-directory: apps/tester-expo/ios
env:
LANG: en_US.UTF-8
LC_ALL: en_US.UTF-8
run: pod install && xcodebuild -workspace RepackExpoTester.xcworkspace -scheme RepackExpoTester -configuration Debug -destination 'generic/platform=iOS Simulator' -derivedDataPath build CODE_SIGNING_ALLOWED=NO ARCHS=arm64 build

- name: Run e2e
working-directory: apps/tester-expo
env:
E2E_DEVICE: e2e
run: |
xcrun simctl install booted ios/build/Build/Products/Debug-iphonesimulator/*.app
pnpm exec e2e run --target ios --reporter list,junit

- name: Collect dev server logs
if: ${{ !cancelled() }}
working-directory: apps/tester-expo
run: |
mkdir -p .e2e
cp /tmp/host.log /tmp/expo-widget.log /tmp/ordinary-widget.log .e2e/
xcrun simctl spawn booted log show --style compact --last 30m \
--predicate 'process == "RepackExpoTester"' \
> .e2e/ios-syslog.txt 2>&1 || true

- name: Upload e2e artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1
with:
name: e2e-expo-ios
path: apps/tester-expo/.e2e
include-hidden-files: true
if-no-files-found: warn
retention-days: 7

- name: Show dev server logs
if: ${{ !cancelled() }}
run: tail -n 80 /tmp/host.log /tmp/expo-widget.log /tmp/ordinary-widget.log
17 changes: 7 additions & 10 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@ name: e2e

on:
pull_request:
paths:
- 'apps/tester-federation-v2/**'
- 'packages/**'
- 'pnpm-lock.yaml'
- '.github/workflows/e2e.yml'
paths-ignore:
- 'website/**'
- '**/*.md'
push:
branches: [main]
paths:
- 'apps/tester-federation-v2/**'
- 'packages/**'
- 'pnpm-lock.yaml'
- '.github/workflows/e2e.yml'
paths-ignore:
- 'website/**'
- '**/*.md'
workflow_dispatch:

# one run per PR; a new push cancels the older one
Expand Down Expand Up @@ -98,6 +94,7 @@ jobs:
arch: x86_64
profile: pixel_7
avd-name: e2e
disable-animations: false
working-directory: apps/tester-federation-v2
script: |
adb shell settings put global hide_error_dialogs 1
Expand Down
1 change: 1 addition & 0 deletions agent_context/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ works, and is kept in sync with the implementation as it evolves.
| Folder | Topic |
| --- | --- |
| [rspackv2-jul2026](./rspackv2-jul2026/design.md) | Dual Rspack 1.x/2.x support |
| [e2e-oct2026](./e2e-oct2026/design.md) | e2e tests on an emulator, on CI |
Loading