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
1 change: 1 addition & 0 deletions .github/workflows/buildAdHoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ jobs:
mobile-expensify-ref: ${{ inputs.MOBILE_EXPENSIFY_REF }}
pull-request-number: ${{ inputs.APP_PR_NUMBER }}
force-native-build: ${{ inputs.FORCE_NATIVE_BUILD }}
download-dsyms: 'true'
secrets: inherit

buildWeb:
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/buildIOS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ on:
description: Force a full native build, bypassing Rock remote cache
type: string
default: 'false'
download-dsyms:
description: Download the prebuilt react-native dSYMs so Sentry can symbolicate its native frames. Off by default - it adds two large downloads per build.
type: string
default: 'false'

outputs:
IOS_VERSION:
Expand All @@ -51,6 +55,7 @@ jobs:
runs-on: blacksmith-12vcpu-macos-latest
env:
PULL_REQUEST_NUMBER: ${{ inputs.pull-request-number }}
RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS: ${{ inputs.download-dsyms == 'true' && '1' || '0' }}
outputs:
IOS_VERSION: ${{ steps.getIOSVersion.outputs.IOS_VERSION }}
ROCK_ARTIFACT_URL: ${{ steps.set-artifact-url.outputs.ARTIFACT_URL }}
Expand Down Expand Up @@ -112,6 +117,19 @@ jobs:
- name: Install New Expensify Gems
run: bundle install

- name: Resolve react-native artifact version
id: resolve-rn-artifacts
run: |
VERSION=$(bun scripts/artifacts-utils/resolve-artifacts.ts --platform=ios --hybrid=true --new-dot-root="$GITHUB_WORKSPACE" | jq -r '.version // "source"')
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"

- name: Cache react-native artifacts
# v5.0.1
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
with:
path: ~/Library/Caches/Expensify/react-native-artifacts
key: ${{ runner.os }}-rn-artifacts-react-hybrid-${{ steps.resolve-rn-artifacts.outputs.VERSION }}

- name: Cache Pod dependencies
# v5.0.1
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ jobs:
with:
ref: ${{ needs.prep.outputs.DEPLOY_SHA }}
variant: Release
download-dsyms: 'true'
secrets: inherit

iosUploadTestflight:
Expand Down
4 changes: 2 additions & 2 deletions scripts/artifacts-utils/android/ExpensiUtils.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ ext.ExpensiUtils = new Object() {
}

// Returns [buildFromSource, version, githubUsername, githubToken]; any failure -> build from source.
Map resolveArtifacts(String packageName, String newDotRootDir, boolean isHybrid) {
Map resolveArtifacts(String newDotRootDir, boolean isHybrid) {
def cmd = [
"bun", "${newDotRootDir}/scripts/artifacts-utils/resolve-artifacts.ts",
"--platform=android", "--package=${packageName}", "--hybrid=${isHybrid}", "--new-dot-root=${newDotRootDir}"
"--platform=android", "--hybrid=${isHybrid}", "--new-dot-root=${newDotRootDir}"
]
try {
def result = runCommand(cmd, 120, new File(newDotRootDir))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ settings.extensions.configure(PatchedArtifactsConfig) { config ->
config.packageName = getProperty('patchedArtifacts.packageName')

def isHybrid = config.packageName == 'react-hybrid'
def resolution = ExpensiUtils.resolveArtifacts(config.packageName, getNewDotRootDir().toString(), isHybrid)
def resolution = ExpensiUtils.resolveArtifacts(getNewDotRootDir().toString(), isHybrid)
config.version = resolution.version
config.buildFromSource = resolution.buildFromSource

Expand Down
7 changes: 3 additions & 4 deletions scripts/artifacts-utils/ios/patched_ios_artifacts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ def self.log(message, level = :info)

def self.setup
is_hybrid = ENV['IS_HYBRID_APP'] == 'true'
package_name = is_hybrid ? 'react-hybrid' : 'react-standalone'

# Manual escape hatch: force a full from-source build (e.g. to unblock a prebuild issue).
build_from_source = ENV['BUILD_RN_FROM_SOURCE'] == '1'
# The escape hatch short-circuits before anything touches the network: no resolver, no prefetch.
resolution = build_from_source ? {'buildFromSource' => true, 'version' => nil} : prefetch(resolve(package_name, is_hybrid))
resolution = build_from_source ? {'buildFromSource' => true, 'version' => nil} : prefetch(resolve(is_hybrid))

# A single decision drives both prebuilt flags, so we never land in a mixed
# prebuilt-deps / source-core state (which desyncs the CocoaPods sandbox).
Expand Down Expand Up @@ -181,10 +180,10 @@ def self.download_and_verify(url, destination, github_token)
destination
end

def self.resolve(package_name, is_hybrid)
def self.resolve(is_hybrid)
cmd = [
'bun', File.join(NEW_DOT_ROOT, 'scripts/artifacts-utils/resolve-artifacts.ts'),
'--platform=ios', "--package=#{package_name}", "--hybrid=#{is_hybrid}", "--new-dot-root=#{NEW_DOT_ROOT}"
'--platform=ios', "--hybrid=#{is_hybrid}", "--new-dot-root=#{NEW_DOT_ROOT}"
]
# stdout is pure JSON; the resolver logs to stderr.
output = IO.popen(cmd, chdir: NEW_DOT_ROOT, &:read)
Expand Down
7 changes: 4 additions & 3 deletions scripts/artifacts-utils/resolve-artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@ import resolveArtifacts from './lib/artifactsResolver';
*
* Usage:
* bun scripts/artifacts-utils/resolve-artifacts.ts \
* --platform=ios --package=react-hybrid --hybrid=true --new-dot-root=.
* --platform=ios --hybrid=true --new-dot-root=.
*
* Prints the result as JSON to stdout (logs go to stderr) and always exits 0.
*/
const args = parseCommandLineArguments();
const platform = args.platform;
const packageName = args.package ?? '';
const isHybrid = args.hybrid === 'true';
const packageName = isHybrid ? 'react-hybrid' : 'react-standalone';

if (platform !== 'ios' && platform !== 'android') {
process.stderr.write(`[PatchedArtifacts] Invalid or missing --platform "${platform ?? ''}" (expected "ios" or "android"); building from source.\n`);
process.stdout.write(JSON.stringify({buildFromSource: true, version: null, packageName, artifactId: ''}));
process.exit(0);
}

const options = {packageName, newDotRoot: args['new-dot-root'] ?? '.', isHybrid: args.hybrid === 'true'};
const options = {packageName, newDotRoot: args['new-dot-root'] ?? '.', isHybrid};
const resolution = platform === 'ios' ? resolveArtifacts({...options, platform: 'ios'}) : resolveArtifacts({...options, platform: 'android'});

resolution
Expand Down
Loading