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
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@callstack/brownfield-example-android-app",
"@callstack/brownfield-example-ios-app",
"@callstack/brownfield-example-rn-app",
"@callstack/brownfield-example-rock-app",
"@callstack/brownfield-example-expo-app-54",
"@callstack/brownfield-example-expo-app-55",
"@callstack/brownfield-gradle-plugin-react"
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/androidapp-road-test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Package the given RN app as AAR, publish to Maven Local, and build

inputs:
flavor:
description: 'AndroidApp flavor to build (expo<version> or vanilla)'
description: 'AndroidApp flavor to build (expo<version>, vanilla or rock)'
required: true

rn-project-path:
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/appleapp-road-test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Package the given RN app as XCFramework, and build the correspondin

inputs:
variant:
description: 'AppleApp yarn command variant to run (expo or vanilla)'
description: 'AppleApp yarn command variant to run (expo, vanilla or rock)'
required: true

rn-project-path:
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ jobs:
rn-project-path: apps/ExpoApp${{ matrix.version }}
rn-project-maven-path: com/callstack/rnbrownfield/demo/expoapp${{ matrix.version }}/brownfieldlib

android-androidapp-rock:
name: Android road test (RNApp & AndroidApp - Rock)
runs-on: ubuntu-latest
needs: build-lint

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Run RockApp -> AndroidApp road test (Rock)
uses: ./.github/actions/androidapp-road-test
with:
flavor: rock
rn-project-path: apps/RockApp
rn-project-maven-path: com/callstack/rnbrownfield/demo/rockapp/brownfieldlib

android-androidapp-vanilla:
name: Android road test (RNApp & AndroidApp - Vanilla)
runs-on: ubuntu-latest
Expand Down Expand Up @@ -201,3 +217,18 @@ jobs:
with:
variant: expo${{ matrix.version }}
rn-project-path: apps/ExpoApp${{ matrix.version }}

ios-appleapp-rock:
name: iOS road test (RNApp & AppleApp - Rock)
runs-on: macos-26
needs: build-lint

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Run RNApp -> AppleApp road test (Rock)
uses: ./.github/actions/appleapp-road-test
with:
variant: rock
rn-project-path: apps/RockApp
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ We use [changesets](https://github.com/changesets/changesets) to make it easier
- `build:example:ios-consumer:expo55` - builds the example native iOS consumer app (`apps/AppleApp`) consuming the Expo 55 RN app (`apps/ExpoApp55`) artifact
- `build:example:ios-consumer:expo54` - builds the example native iOS consumer app (`apps/AppleApp`) consuming the Expo 54 RN app (`apps/ExpoApp54`) artifact
- `build:example:ios-consumer:vanilla` - builds the example native iOS consumer (`apps/AppleApp`) app's flavor consuming the vanilla RN app (`apps/RNApp`) artifact
- `build:example:ios-consumer:rock` - builds the example native iOS consumer (`apps/AppleApp`) app's flavor consuming the vanilla RN app (`apps/RNApp`) artifact

## Example app tests

Expand All @@ -51,6 +52,7 @@ Per example app (run from the repo root):
| `yarn workspace @callstack/brownfield-example-rn-app test` | Plain React Native (`apps/RNApp`) |
| `yarn workspace @callstack/brownfield-example-expo-app-54 test` | Expo SDK 54 (`apps/ExpoApp54`) |
| `yarn workspace @callstack/brownfield-example-expo-app-55 test` | Expo SDK 55 (`apps/ExpoApp55`) |
| `yarn workspace @callstack/brownfield-example-rock-app test` | Rock (`apps/RockApp`) |

Package-level scripts (`yarn test` inside `apps/RNApp`, `apps/ExpoApp54`, or `apps/ExpoApp55`) invoke Jest with each app’s `jest.config.js`.

Expand Down
4 changes: 4 additions & 0 deletions apps/AndroidApp/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ android {
create("vanilla") {
dimension = "app"
}
create("rock") {
dimension = "app"
}
}

buildTypes {
Expand Down Expand Up @@ -74,6 +77,7 @@ dependencies {
add("expo55Implementation", libs.brownfieldlib.expo55)
add("expo54Implementation", libs.brownfieldlib.expo54)
add("vanillaImplementation", libs.brownfieldlib.vanilla)
add("rockImplementation", libs.brownfieldlib.rock)

implementation(libs.androidx.fragment.compose)
testImplementation(libs.junit)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.callstack.brownfield.android.example

typealias BrownfieldStore = com.callstack.rnbrownfield.demo.rockapp.BrownfieldStore
typealias User = com.callstack.rnbrownfield.demo.rockapp.User
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.callstack.brownfield.android.example

object ReactNativeConstants {
const val MAIN_MODULE_NAME = "RockApp"
const val APP_NAME = "Android"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.callstack.brownfield.android.example

import android.content.res.Configuration

typealias ReactNativeHostManager = com.callstack.rnbrownfield.demo.rockapp.ReactNativeHostManager

fun ReactNativeHostManager.onConfigurationChanged(application: android.app.Application, newConfig: Configuration) {
// no-op that is prepared to match of the Expo ReactNativeHostManager
}
1 change: 1 addition & 0 deletions apps/AndroidApp/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref =
brownfieldlib-expo55 = { module = "com.callstack.rnbrownfield.demo.expoapp55:brownfieldlib", version.ref = "brownfieldlib" }
brownfieldlib-expo54 = { module = "com.callstack.rnbrownfield.demo.expoapp54:brownfieldlib", version.ref = "brownfieldlib" }
brownfieldlib-vanilla = { module = "com.rnapp:brownfieldlib", version.ref = "brownfieldlib" }
brownfieldlib-rock = { module = "com.callstack.rnbrownfield.demo.rockapp:brownfieldlib", version.ref = "brownfieldlib" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
Expand Down
3 changes: 2 additions & 1 deletion apps/AndroidApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"build:example:android-consumer:expo": "./gradlew assembleExpo55Release",
"build:example:android-consumer:expo55": "./gradlew assembleExpo55Release",
"build:example:android-consumer:expo54": "./gradlew assembleExpo54Release",
"build:example:android-consumer:vanilla": "./gradlew assembleVanillaRelease"
"build:example:android-consumer:vanilla": "./gradlew assembleVanillaRelease",
"build:example:android-consumer:rock": "./gradlew assembleRockRelease"
}
}
31 changes: 31 additions & 0 deletions apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,32 @@
};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
7B1E0C002F50633300CB6364 /* Embed Rock runtime frameworks */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/embed-rock-runtime-frameworks.sh",
"$(SRCROOT)/package",
);
name = "Embed Rock runtime frameworks";
outputFileListPaths = (
);
outputPaths = (
"$(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)/React.framework",
"$(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)/ReactNativeDependencies.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/bash;
shellScript = "\"${SRCROOT}/embed-rock-runtime-frameworks.sh\"\n";
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXFileReference section */
614525D32F922C01003775A1 /* Brownie.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Brownie.xcframework; path = package/Brownie.xcframework; sourceTree = "<group>"; };
614B238D2F50633200CB6363 /* BrownfieldLib.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = BrownfieldLib.xcframework; path = package/BrownfieldLib.xcframework; sourceTree = "<group>"; };
Expand Down Expand Up @@ -110,6 +136,7 @@
793C76A42EEBF938008A2A34 /* Frameworks */,
793C76A52EEBF938008A2A34 /* Resources */,
798DE8D92F0EC98E00CFC6F3 /* Embed Frameworks */,
7B1E0C002F50633300CB6364 /* Embed Rock runtime frameworks */,
);
buildRules = (
);
Expand Down Expand Up @@ -308,6 +335,7 @@
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist";
Expand Down Expand Up @@ -355,6 +383,7 @@
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist";
Expand Down Expand Up @@ -520,6 +549,7 @@
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist";
Expand Down Expand Up @@ -567,6 +597,7 @@
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2640"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "793C76A62EEBF938008A2A34"
BuildableName = "Brownfield Apple App.app"
BlueprintName = "Brownfield Apple App"
ReferencedContainer = "container:Brownfield Apple App.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug Expo"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug Expo"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
queueDebuggingEnableBacktraceRecording = "Yes">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "793C76A62EEBF938008A2A34"
BuildableName = "Brownfield Apple App.app"
BlueprintName = "Brownfield Apple App"
ReferencedContainer = "container:Brownfield Apple App.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release Expo"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "793C76A62EEBF938008A2A34"
BuildableName = "Brownfield Apple App.app"
BlueprintName = "Brownfield Apple App"
ReferencedContainer = "container:Brownfield Apple App.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug Expo">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release Expo"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ struct ContentView: View {
NavigationView {

VStack(spacing: 16) {
GreetingCard(name: "iOS Expo")
GreetingCard(name: "iOS Rock")

MessagesView()

ReactNativeView(
moduleName: "main",
moduleName: "RockApp",
initialProperties: [
"nativeOsVersionLabel":
"\(UIDevice.current.systemName) \(UIDevice.current.systemVersion)"
Expand Down
77 changes: 77 additions & 0 deletions apps/AppleApp/embed-rock-runtime-frameworks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
#
# Run Script Build Phase invoked by the "Brownfield Apple App" target after
# the standard "Embed Frameworks" phase.
#
# When the host RN project is RockApp, the dynamic BrownfieldLib.dylib
# produced by `rock package:ios` has @rpath load commands for
# React.framework and ReactNativeDependencies.framework. They must be
# embedded in the .app bundle or the app crashes on launch with
# "Library not loaded: @rpath/React.framework/React".
#
# `prepareXCFrameworks.js --appName RockApp` drops these xcframeworks into
# `package/`. For Vanilla / Expo flavors they are absent (React core is
# statically linked into BrownfieldLib), so this script is a no-op then.
Comment on lines +3 to +14
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This should already be happening

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We can remove - already addressed in merged #323


set -euo pipefail

PACKAGE_DIR="${SRCROOT}/package"
DEST_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"

EXTRA_XCFRAMEWORKS=(
"React.xcframework"
"ReactNativeDependencies.xcframework"
)

if [[ "${PLATFORM_NAME}" == iphonesimulator* || "${PLATFORM_NAME}" == macosx* ]]; then
PRIMARY_SLICE="ios-arm64_x86_64-simulator"
FALLBACK_SLICES=("ios-arm64-simulator")
else
PRIMARY_SLICE="ios-arm64"
FALLBACK_SLICES=("ios-arm64_x86_64-maccatalyst")
fi

resolve_slice_dir() {
local xcframework_path="$1"
for candidate in "${PRIMARY_SLICE}" "${FALLBACK_SLICES[@]}"; do
if [[ -d "${xcframework_path}/${candidate}" ]]; then
echo "${xcframework_path}/${candidate}"
return 0
fi
done
return 1
}

mkdir -p "${DEST_DIR}"

for xcframework in "${EXTRA_XCFRAMEWORKS[@]}"; do
XC_PATH="${PACKAGE_DIR}/${xcframework}"
if [[ ! -d "${XC_PATH}" ]]; then
echo "note: ${xcframework} not present in ${PACKAGE_DIR}, skipping (expected for Vanilla/Expo flavors)"
continue
fi

framework_name="$(basename "${xcframework}" .xcframework)"
if ! slice_dir="$(resolve_slice_dir "${XC_PATH}")"; then
echo "warning: no compatible slice for platform ${PLATFORM_NAME} in ${xcframework}; skipping"
continue
fi

src_framework="${slice_dir}/${framework_name}.framework"
if [[ ! -d "${src_framework}" ]]; then
echo "warning: ${src_framework} is missing; skipping"
continue
fi

dest_framework="${DEST_DIR}/${framework_name}.framework"
echo "Embedding ${framework_name}.framework from ${slice_dir}"
rm -rf "${dest_framework}"
cp -R "${src_framework}" "${dest_framework}"

if [[ "${EXPANDED_CODE_SIGN_IDENTITY:-}" != "" ]]; then
/usr/bin/codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" \
${OTHER_CODE_SIGN_FLAGS:-} \
--preserve-metadata=identifier,entitlements,flags \
"${dest_framework}"
fi
done
1 change: 1 addition & 0 deletions apps/AppleApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build:example:ios-consumer:expo54": "node prepareXCFrameworks.js --appName ExpoApp54 && yarn internal::build::common -scheme \"Brownfield Apple App Expo\" -configuration Release",
"build:example:ios-consumer:expo55": "node prepareXCFrameworks.js --appName ExpoApp55 && yarn internal::build::common -scheme \"Brownfield Apple App Expo\" -configuration Release",
"build:example:ios-consumer:vanilla": "node prepareXCFrameworks.js --appName RNApp && yarn internal::build::common -scheme \"Brownfield Apple App Vanilla\" -configuration \"Release Vanilla\"",
"build:example:ios-consumer:rock": "node prepareXCFrameworks.js --appName RockApp && yarn internal::build::common -scheme \"Brownfield Apple App Rock\" -configuration \"Release Vanilla\"",
"internal::build::common": "xcodebuild -project \"Brownfield Apple App.xcodeproj\" -sdk iphonesimulator build CODE_SIGNING_ALLOWED=NO -derivedDataPath ./build"
},
"devDependencies": {
Expand Down
Loading