From 854f0b749e4f2e91dac46e01aa48509a2784c2c6 Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Wed, 24 Jun 2026 12:06:03 +0200 Subject: [PATCH 01/13] integrate proxy server --- .../facebook/react/utils/DependencyUtils.kt | 9 ++++ .../react/utils/DependencyUtilsTest.kt | 51 +++++++++++++++++++ packages/react-native/package.json | 2 +- .../react-native/scripts/cocoapods/rncore.rb | 32 ++++++++---- .../scripts/cocoapods/rndependencies.rb | 30 +++++++---- .../scripts/ios-prebuild/hermes.js | 48 +++++++++++++---- .../ios-prebuild/reactNativeDependencies.js | 45 ++++++++++++---- .../sdks/hermes-engine/hermes-utils.rb | 28 +++++++--- 8 files changed, 198 insertions(+), 47 deletions(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index b686aefa0162..4ee5651cf612 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -27,6 +27,7 @@ import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository internal object DependencyUtils { + private const val REACT_NATIVE_MAVEN_CACHE_URL = "https://rnmaven.swmtest.xyz/" internal data class Coordinates( val versionString: String, @@ -75,6 +76,14 @@ internal object DependencyUtils { repo.content { it.excludeGroup("org.webkit") } } } + if (!hasProperty(INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO)) { + mavenRepoFromUrl(REACT_NATIVE_MAVEN_CACHE_URL) { repo -> + repo.content { + it.includeGroupByRegex("com\\.facebook\\.react.*") + it.includeGroupByRegex("com\\.facebook\\.hermes.*") + } + } + } repositories.mavenCentral { repo -> // We don't want to fetch JSC from Maven Central as there are older versions there. repo.content { it.excludeGroup("org.webkit") } diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 5c57bb296fa4..7726c9a0f265 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -61,6 +61,21 @@ class DependencyUtilsTest { .isNotNull() } + @Test + fun configureRepositories_containsReactNativeMavenCache() { + val repositoryURI = URI.create("https://rnmaven.swmtest.xyz/") + val project = createProject() + + configureRepositories(project, false) + + assertThat( + project.repositories.firstOrNull { + it is MavenArtifactRepository && it.url == repositoryURI + } + ) + .isNotNull() + } + @Test fun configureRepositories_containsGoogleRepo() { val repositoryURI = URI.create("https://dl.google.com/dl/android/maven2/") @@ -221,6 +236,42 @@ class DependencyUtilsTest { assertThat(indexOfLocalRepo < indexOfMavenCentral).isTrue() } + @Test + fun configureRepositories_mavenCacheHasHigherPriorityThanMavenCentral() { + val mavenCacheURI = URI.create("https://rnmaven.swmtest.xyz/") + val mavenCentralURI = URI.create("https://repo.maven.apache.org/maven2/") + val project = createProject() + + configureRepositories(project, false) + + val indexOfMavenCache = + project.repositories.indexOfFirst { + it is MavenArtifactRepository && it.url == mavenCacheURI + } + val indexOfMavenCentral = + project.repositories.indexOfFirst { + it is MavenArtifactRepository && it.url == mavenCentralURI + } + assertThat(indexOfMavenCache < indexOfMavenCentral).isTrue() + } + + @Test + fun configureRepositories_withProjectPropertySet_doesNotContainMavenCache() { + val localMaven = tempFolder.newFolder("m2") + val mavenCacheURI = URI.create("https://rnmaven.swmtest.xyz/") + val project = createProject() + project.extensions.extraProperties.set("react.internal.mavenLocalRepo", localMaven.absolutePath) + + configureRepositories(project, false) + + assertThat( + project.repositories.firstOrNull { + it is MavenArtifactRepository && it.url == mavenCacheURI + } + ) + .isNull() + } + @Test fun configureRepositories_snapshotRepoHasHigherPriorityThanMavenCentral() { val repositoryURI = URI.create("https://central.sonatype.com/repository/maven-snapshots/") diff --git a/packages/react-native/package.json b/packages/react-native/package.json index ec26182439fe..ddf4b98c998a 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -167,7 +167,7 @@ "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", - "hermes-compiler": "0.0.0", + "hermes-compiler": "250829098.0.14", "invariant": "^2.2.4", "memoize-one": "^5.0.0", "metro-runtime": "^0.84.3", diff --git a/packages/react-native/scripts/cocoapods/rncore.rb b/packages/react-native/scripts/cocoapods/rncore.rb index 252588c98432..972e83ab7d73 100644 --- a/packages/react-native/scripts/cocoapods/rncore.rb +++ b/packages/react-native/scripts/cocoapods/rncore.rb @@ -44,6 +44,9 @@ def add_rncore_dependency(s) ## - RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS: If set to 1, it will download the dSYMs for the prebuilt RNCore frameworks and install these in the framework folders class ReactNativeCoreUtils + MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" + REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" + @@build_from_source = true @@react_native_path = "" @@react_native_version = "" @@ -364,16 +367,27 @@ def self.generate_plist_content(mappings) end def self.stable_tarball_url(version, build_type, dsyms = false) - ## You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded. - ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - maven_repo_url = - ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ? - ENV['ENTERPRISE_REPOSITORY'] : - "https://repo1.maven.org/maven2" + candidates = stable_tarball_urls(version, build_type, dsyms) + return candidates.find { |url| artifact_exists(url) } || candidates.first + end + + def self.stable_tarball_urls(version, build_type, dsyms = false) group = "com/facebook/react" - # Sample url from Maven: - # https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.81.0/react-native-artifacts-0.81.0-reactnative-core-debug.tar.gz - return "#{maven_repo_url}/#{group}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-reactnative-core-#{dsyms ? "dSYM-" : ""}#{build_type.to_s}.tar.gz" + return maven_repository_urls().map { |maven_repo_url| + # Sample url from Maven: + # https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.81.0/react-native-artifacts-0.81.0-reactnative-core-debug.tar.gz + "#{maven_repo_url}/#{group}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-reactnative-core-#{dsyms ? "dSYM-" : ""}#{build_type.to_s}.tar.gz" + } + end + + def self.maven_repository_urls() + ## You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. + ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. + if ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" + return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] + end + + return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] end def self.nightly_tarball_url(version, configuration, dsyms = false) diff --git a/packages/react-native/scripts/cocoapods/rndependencies.rb b/packages/react-native/scripts/cocoapods/rndependencies.rb index 1c7fac1a6cb7..5cb4cae75000 100644 --- a/packages/react-native/scripts/cocoapods/rndependencies.rb +++ b/packages/react-native/scripts/cocoapods/rndependencies.rb @@ -57,6 +57,9 @@ def add_rn_third_party_dependencies(s) end class ReactNativeDependenciesUtils + MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" + REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" + @@build_from_source = true @@react_native_path = "" @@react_native_version = "" @@ -165,16 +168,25 @@ def self.podspec_source_download_prebuild_release_tarball() end def self.release_tarball_url(version, build_type) - ## You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded. - ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - maven_repo_url = - ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ? - ENV['ENTERPRISE_REPOSITORY'] : - "https://repo1.maven.org/maven2" + candidates = release_tarball_urls(version, build_type) + return candidates.find { |url| artifact_exists(url) } || candidates.first + end + + def self.release_tarball_urls(version, build_type) group = "com/facebook/react" - # Sample url from Maven: - # https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.79.0-rc.0/react-native-artifacts-0.79.0-rc.0-reactnative-dependencies-debug.tar.gz - return "#{maven_repo_url}/#{group}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-reactnative-dependencies-#{build_type.to_s}.tar.gz" + return maven_repository_urls().map { |maven_repo_url| + "#{maven_repo_url}/#{group}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-reactnative-dependencies-#{build_type.to_s}.tar.gz" + } + end + + def self.maven_repository_urls() + ## You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. + ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. + if ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" + return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] + end + + return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] end def self.nightly_tarball_url(version, build_type) diff --git a/packages/react-native/scripts/ios-prebuild/hermes.js b/packages/react-native/scripts/ios-prebuild/hermes.js index eb3df6314352..a7c57049cb0b 100644 --- a/packages/react-native/scripts/ios-prebuild/hermes.js +++ b/packages/react-native/scripts/ios-prebuild/hermes.js @@ -17,6 +17,8 @@ const {promisify} = require('util'); const pipeline = promisify(stream.pipeline); const hermesLog = createLogger('Hermes'); +const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; +const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; /*:: import type {BuildFlavor, Destination, Platform} from './types'; @@ -187,16 +189,42 @@ function hermesEngineTarballEnvvarDefined() /*: boolean */ { return !!process.env.HERMES_ENGINE_TARBALL_PATH; } -function getTarballUrl( +async function getTarballUrl( version /*: string */, buildType /*: BuildFlavor */, -) /*: string */ { - // You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded. - // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - const mavenRepoUrl = - process.env.ENTERPRISE_REPOSITORY ?? 'https://repo1.maven.org/maven2'; +) /*: Promise */ { + const candidates = getTarballUrls(version, buildType); + for (const url of candidates) { + console.log(`Checking if Hermes artifact exists at URL: ${url}`); + if (await hermesArtifactExists(url)) { + console.log(`Found Hermes artifact at URL: ${url}`); + return url; + } + console.log(`Hermes artifact not found at URL: ${url}`); + } + return candidates[0]; +} + +function getTarballUrls( + version /*: string */, + buildType /*: BuildFlavor */, +) /*: Array */ { const namespace = 'com/facebook/hermes'; - return `${mavenRepoUrl}/${namespace}/hermes-ios/${version}/hermes-ios-${version}-hermes-ios-${buildType.toLowerCase()}.tar.gz`; + return getMavenRepositoryUrls().map( + mavenRepoUrl => + `${mavenRepoUrl}/${namespace}/hermes-ios/${version}/hermes-ios-${version}-hermes-ios-${buildType.toLowerCase()}.tar.gz`, + ); +} + +function getMavenRepositoryUrls() /*: Array */ { + // You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. + // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. + const enterpriseRepository = process.env.ENTERPRISE_REPOSITORY; + if (enterpriseRepository != null && enterpriseRepository !== '') { + return [enterpriseRepository.replace(/\/+$/, '')]; + } + + return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY]; } /** @@ -228,7 +256,7 @@ async function hermesSourceType( return HermesEngineSourceTypes.LOCAL_PREBUILT_TARBALL; } - const tarballUrl = getTarballUrl(version, buildType); + const tarballUrl = await getTarballUrl(version, buildType); if (await hermesArtifactExists(tarballUrl)) { hermesLog(`Using download prebuild ${buildType} tarball`); return HermesEngineSourceTypes.DOWNLOAD_PREBUILD_TARBALL; @@ -278,7 +306,7 @@ async function downloadPrebuildTarball( buildType /*: BuildFlavor */, artifactsPath /*: string*/, ) /*: Promise */ { - const url = getTarballUrl(version, buildType); + const url = await getTarballUrl(version, buildType); hermesLog(`Using release tarball from URL: ${url}`); return downloadStableHermes(version, buildType, artifactsPath); } @@ -288,7 +316,7 @@ async function downloadStableHermes( buildType /*: BuildFlavor */, artifactsPath /*: string */, ) /*: Promise */ { - const tarballUrl = getTarballUrl(version, buildType); + const tarballUrl = await getTarballUrl(version, buildType); return downloadHermesTarball(tarballUrl, version, buildType, artifactsPath); } diff --git a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js index f497338bef8b..ba436f99d1e8 100644 --- a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js +++ b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js @@ -20,6 +20,8 @@ const {promisify} = require('util'); const pipeline = promisify(stream.pipeline); const dependencyLog = createLogger('ReactNativeDependencies'); +const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; +const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; /** * Downloads ReactNativeDependencies artifacts from the specified version and build type. If you want to specify a specific @@ -178,16 +180,39 @@ function checkExistingVersion( return false; } -function getTarballUrl( +async function getTarballUrl( version /*: string */, buildType /*: BuildFlavor */, -) /*: string */ { - // You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded. - // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - const mavenRepoUrl = - process.env.ENTERPRISE_REPOSITORY ?? 'https://repo1.maven.org/maven2'; +) /*: Promise */ { + const candidates = getTarballUrls(version, buildType); + for (const url of candidates) { + if (await reactNativeDependenciesArtifactExists(url)) { + return url; + } + } + return candidates[0]; +} + +function getTarballUrls( + version /*: string */, + buildType /*: BuildFlavor */, +) /*: Array */ { const namespace = 'com/facebook/react'; - return `${mavenRepoUrl}/${namespace}/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-${buildType.toLowerCase()}.tar.gz`; + return getMavenRepositoryUrls().map( + mavenRepoUrl => + `${mavenRepoUrl}/${namespace}/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-${buildType.toLowerCase()}.tar.gz`, + ); +} + +function getMavenRepositoryUrls() /*: Array */ { + // You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. + // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. + const enterpriseRepository = process.env.ENTERPRISE_REPOSITORY; + if (enterpriseRepository != null && enterpriseRepository !== '') { + return [enterpriseRepository.replace(/\/+$/, '')]; + } + + return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY]; } async function getNightlyTarballUrl( @@ -230,7 +255,7 @@ async function reactNativeDependenciesSourceType( version /*: string */, buildType /*: BuildFlavor */, ) /*: Promise */ { - const tarballUrl = getTarballUrl(version, buildType); + const tarballUrl = await getTarballUrl(version, buildType); if (await reactNativeDependenciesArtifactExists(tarballUrl)) { dependencyLog(`Using download prebuild ${buildType} tarball`); return ReactNativeDependenciesEngineSourceTypes.DOWNLOAD_PREBUILD_TARBALL; @@ -273,7 +298,7 @@ async function downloadPrebuildTarball( buildType /*: BuildFlavor */, artifactsPath /*: string*/, ) /*: Promise */ { - const url = getTarballUrl(version, buildType); + const url = await getTarballUrl(version, buildType); dependencyLog(`Using release tarball from URL: ${url}`); return downloadStableReactNativeDependencies( version, @@ -302,7 +327,7 @@ async function downloadStableReactNativeDependencies( buildType /*: BuildFlavor */, artifactsPath /*: string */, ) /*: Promise */ { - const tarballUrl = getTarballUrl(version, buildType); + const tarballUrl = await getTarballUrl(version, buildType); return downloadReactNativeDependenciesTarball( tarballUrl, version, diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index 288a5b638543..80ae4001056d 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -7,6 +7,8 @@ HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git" ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE" +MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" +REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" module HermesEngineSourceType LOCAL_PREBUILT_TARBALL = :local_prebuilt_tarball @@ -190,17 +192,27 @@ def hermestag_file(react_native_path) end def release_tarball_url(version, build_type) + candidates = release_tarball_urls(version, build_type) + return candidates.find { |url| hermes_artifact_exists(url) } || candidates.first +end + +def release_tarball_urls(version, build_type) + namespace = "com/facebook/hermes" + return maven_repository_urls().map { |maven_repo_url| + # Sample url from Maven: + # https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/0.14.0/hermes-ios-0.14.0-hermes-ios-debug.tar.gz + "#{maven_repo_url}/#{namespace}/hermes-ios/#{version}/hermes-ios-#{version}-hermes-ios-#{build_type.to_s}.tar.gz" + } +end + +def maven_repository_urls() ## You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - maven_repo_url = - ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ? - ENV['ENTERPRISE_REPOSITORY'] : - "https://repo1.maven.org/maven2" + if ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" + return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] + end - namespace = "com/facebook/hermes" - # Sample url from Maven: - # https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/0.14.0/hermes-ios-0.14.0-hermes-ios-debug.tar.gz - return "#{maven_repo_url}/#{namespace}/hermes-ios/#{version}/hermes-ios-#{version}-hermes-ios-#{build_type.to_s}.tar.gz" + return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] end def download_stable_hermes(react_native_path, version, configuration) From e7d71749f4e4f25fe830648d6a215de30e5f1302 Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Wed, 24 Jun 2026 12:26:46 +0200 Subject: [PATCH 02/13] reduce artifacts exists calls on iOS builds --- .../scripts/ios-prebuild/hermes.js | 30 ++++++++++++++----- .../ios-prebuild/reactNativeDependencies.js | 27 ++++++++++++++--- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/packages/react-native/scripts/ios-prebuild/hermes.js b/packages/react-native/scripts/ios-prebuild/hermes.js index a7c57049cb0b..b5b5df656324 100644 --- a/packages/react-native/scripts/ios-prebuild/hermes.js +++ b/packages/react-native/scripts/ios-prebuild/hermes.js @@ -19,6 +19,7 @@ const pipeline = promisify(stream.pipeline); const hermesLog = createLogger('Hermes'); const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; +const artifactExistenceCache = new Map(); /*:: import type {BuildFlavor, Destination, Platform} from './types'; @@ -193,16 +194,25 @@ async function getTarballUrl( version /*: string */, buildType /*: BuildFlavor */, ) /*: Promise */ { + const existingUrl = await findExistingTarballUrl(version, buildType); + if (existingUrl != null) { + return existingUrl; + } + + return getTarballUrls(version, buildType)[0]; +} + +async function findExistingTarballUrl( + version /*: string */, + buildType /*: BuildFlavor */, +) /*: Promise */ { const candidates = getTarballUrls(version, buildType); for (const url of candidates) { - console.log(`Checking if Hermes artifact exists at URL: ${url}`); if (await hermesArtifactExists(url)) { - console.log(`Found Hermes artifact at URL: ${url}`); return url; } - console.log(`Hermes artifact not found at URL: ${url}`); } - return candidates[0]; + return null; } function getTarballUrls( @@ -233,13 +243,20 @@ function getMavenRepositoryUrls() /*: Array */ { async function hermesArtifactExists( tarballUrl /*: string */, ) /*: Promise */ { + if (artifactExistenceCache.has(tarballUrl)) { + return artifactExistenceCache.get(tarballUrl); + } + try { const response /*: Response */ = await fetch(tarballUrl, { method: 'HEAD', }); - return response.status === 200; + const exists = response.status === 200; + artifactExistenceCache.set(tarballUrl, exists); + return exists; } catch (e) { + artifactExistenceCache.set(tarballUrl, false); return false; } } @@ -256,8 +273,7 @@ async function hermesSourceType( return HermesEngineSourceTypes.LOCAL_PREBUILT_TARBALL; } - const tarballUrl = await getTarballUrl(version, buildType); - if (await hermesArtifactExists(tarballUrl)) { + if ((await findExistingTarballUrl(version, buildType)) != null) { hermesLog(`Using download prebuild ${buildType} tarball`); return HermesEngineSourceTypes.DOWNLOAD_PREBUILD_TARBALL; } diff --git a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js index ba436f99d1e8..dcd6c02ae87a 100644 --- a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js +++ b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js @@ -22,6 +22,7 @@ const pipeline = promisify(stream.pipeline); const dependencyLog = createLogger('ReactNativeDependencies'); const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; +const artifactExistenceCache = new Map(); /** * Downloads ReactNativeDependencies artifacts from the specified version and build type. If you want to specify a specific @@ -184,13 +185,25 @@ async function getTarballUrl( version /*: string */, buildType /*: BuildFlavor */, ) /*: Promise */ { + const existingUrl = await findExistingTarballUrl(version, buildType); + if (existingUrl != null) { + return existingUrl; + } + + return getTarballUrls(version, buildType)[0]; +} + +async function findExistingTarballUrl( + version /*: string */, + buildType /*: BuildFlavor */, +) /*: Promise */ { const candidates = getTarballUrls(version, buildType); for (const url of candidates) { if (await reactNativeDependenciesArtifactExists(url)) { return url; } } - return candidates[0]; + return null; } function getTarballUrls( @@ -237,13 +250,20 @@ async function getNightlyTarballUrl( async function reactNativeDependenciesArtifactExists( tarballUrl /*: string */, ) /*: Promise */ { + if (artifactExistenceCache.has(tarballUrl)) { + return artifactExistenceCache.get(tarballUrl); + } + try { const response /*: Response */ = await fetch(tarballUrl, { method: 'HEAD', }); - return response.status === 200; + const exists = response.status === 200; + artifactExistenceCache.set(tarballUrl, exists); + return exists; } catch (e) { + artifactExistenceCache.set(tarballUrl, false); return false; } } @@ -255,8 +275,7 @@ async function reactNativeDependenciesSourceType( version /*: string */, buildType /*: BuildFlavor */, ) /*: Promise */ { - const tarballUrl = await getTarballUrl(version, buildType); - if (await reactNativeDependenciesArtifactExists(tarballUrl)) { + if ((await findExistingTarballUrl(version, buildType)) != null) { dependencyLog(`Using download prebuild ${buildType} tarball`); return ReactNativeDependenciesEngineSourceTypes.DOWNLOAD_PREBUILD_TARBALL; } From fa2216495b3eb7f6cced4ee395e368ad7485167e Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Wed, 24 Jun 2026 12:55:10 +0200 Subject: [PATCH 03/13] reduce artifacts exists calls in ruby --- packages/react-native/scripts/cocoapods/rncore.rb | 2 +- packages/react-native/scripts/cocoapods/rndependencies.rb | 2 +- packages/react-native/sdks/hermes-engine/hermes-utils.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/rncore.rb b/packages/react-native/scripts/cocoapods/rncore.rb index 972e83ab7d73..afa93dd05dea 100644 --- a/packages/react-native/scripts/cocoapods/rncore.rb +++ b/packages/react-native/scripts/cocoapods/rncore.rb @@ -489,7 +489,7 @@ def self.download_rncore_tarball(react_native_path, tarball_url, version, config end def self.release_artifact_exists(version) - return artifact_exists(stable_tarball_url(version, :debug)) + return stable_tarball_urls(version, :debug).any? { |url| artifact_exists(url) } end def self.nightly_artifact_exists(version) diff --git a/packages/react-native/scripts/cocoapods/rndependencies.rb b/packages/react-native/scripts/cocoapods/rndependencies.rb index 5cb4cae75000..9555f819658e 100644 --- a/packages/react-native/scripts/cocoapods/rndependencies.rb +++ b/packages/react-native/scripts/cocoapods/rndependencies.rb @@ -313,7 +313,7 @@ def self.download_rndeps_tarball(react_native_path, tarball_url, version, config end def self.release_artifact_exists(version) - return artifact_exists(release_tarball_url(version, :debug)) + return release_tarball_urls(version, :debug).any? { |url| artifact_exists(url) } end def self.nightly_artifact_exists(version) diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index 80ae4001056d..f05c98c59165 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -91,7 +91,7 @@ def force_build_from_stable_branch(react_native_path) end def release_artifact_exists(version) - return hermes_artifact_exists(release_tarball_url(version, :debug)) + return release_tarball_urls(version, :debug).any? { |url| hermes_artifact_exists(url) } end def podspec_source(source_type, version, react_native_path) From db9f786b281c8fbdafc8f40ab7d2a90fd675d43d Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Wed, 24 Jun 2026 17:32:28 +0200 Subject: [PATCH 04/13] fix lint issues --- packages/react-native/scripts/ios-prebuild/hermes.js | 7 ++++--- .../scripts/ios-prebuild/reactNativeDependencies.js | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/react-native/scripts/ios-prebuild/hermes.js b/packages/react-native/scripts/ios-prebuild/hermes.js index b5b5df656324..3ce8d8195cd9 100644 --- a/packages/react-native/scripts/ios-prebuild/hermes.js +++ b/packages/react-native/scripts/ios-prebuild/hermes.js @@ -19,7 +19,7 @@ const pipeline = promisify(stream.pipeline); const hermesLog = createLogger('Hermes'); const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; -const artifactExistenceCache = new Map(); +const artifactExistenceCache /*: Map */ = new Map(); /*:: import type {BuildFlavor, Destination, Platform} from './types'; @@ -243,8 +243,9 @@ function getMavenRepositoryUrls() /*: Array */ { async function hermesArtifactExists( tarballUrl /*: string */, ) /*: Promise */ { - if (artifactExistenceCache.has(tarballUrl)) { - return artifactExistenceCache.get(tarballUrl); + const cached = artifactExistenceCache.get(tarballUrl); + if (cached != null) { + return cached; } try { diff --git a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js index dcd6c02ae87a..620248abb00b 100644 --- a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js +++ b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js @@ -22,7 +22,7 @@ const pipeline = promisify(stream.pipeline); const dependencyLog = createLogger('ReactNativeDependencies'); const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; -const artifactExistenceCache = new Map(); +const artifactExistenceCache /*: Map */ = new Map(); /** * Downloads ReactNativeDependencies artifacts from the specified version and build type. If you want to specify a specific @@ -250,8 +250,9 @@ async function getNightlyTarballUrl( async function reactNativeDependenciesArtifactExists( tarballUrl /*: string */, ) /*: Promise */ { - if (artifactExistenceCache.has(tarballUrl)) { - return artifactExistenceCache.get(tarballUrl); + const cached = artifactExistenceCache.get(tarballUrl); + if (cached != null) { + return cached; } try { From 4ce6cd378deee0351a41a719f2719c79e64b7f81 Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 26 Jun 2026 10:05:05 +0200 Subject: [PATCH 05/13] undo hermes-compiler version change --- packages/react-native/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/package.json b/packages/react-native/package.json index ddf4b98c998a..ec26182439fe 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -167,7 +167,7 @@ "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", - "hermes-compiler": "250829098.0.14", + "hermes-compiler": "0.0.0", "invariant": "^2.2.4", "memoize-one": "^5.0.0", "metro-runtime": "^0.84.3", From 479acf192d7619fd8657392d970033b12385224a Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 26 Jun 2026 11:23:42 +0200 Subject: [PATCH 06/13] Add reactNativeMavenCacheEnabled flag for toggling usage of Maven cache repo --- .../facebook/react/utils/DependencyUtils.kt | 13 ++++++++- .../com/facebook/react/utils/PropertyUtils.kt | 4 +++ .../react/utils/DependencyUtilsTest.kt | 16 +++++++++++ .../react-native/scripts/cocoapods/rncore.rb | 13 ++++++++- .../scripts/cocoapods/rndependencies.rb | 13 ++++++++- .../scripts/ios-prebuild/hermes.js | 15 +--------- .../ios-prebuild/reactNativeDependencies.js | 19 ++++--------- .../scripts/ios-prebuild/utils.js | 28 +++++++++++++++++++ .../sdks/hermes-engine/hermes-utils.rb | 13 ++++++++- 9 files changed, 102 insertions(+), 32 deletions(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index 4ee5651cf612..900acb417b05 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -14,6 +14,7 @@ import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY_DEFAULT import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_PUBLISHING_GROUP import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_VERSION_NAME +import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_PUBLISHING_GROUP import com.facebook.react.utils.PropertyUtils.INTERNAL_USE_HERMES_NIGHTLY @@ -76,7 +77,10 @@ internal object DependencyUtils { repo.content { it.excludeGroup("org.webkit") } } } - if (!hasProperty(INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO)) { + // The React Native Maven cache must be added before Maven Central so it can serve cached + // artifacts first, while Maven Central remains the fallback. + if (!hasProperty(INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO) && + isReactNativeMavenCacheEnabled()) { mavenRepoFromUrl(REACT_NATIVE_MAVEN_CACHE_URL) { repo -> repo.content { it.includeGroupByRegex("com\\.facebook\\.react.*") @@ -280,6 +284,13 @@ internal object DependencyUtils { else -> INCLUDE_JITPACK_REPOSITORY_DEFAULT } + internal fun Project.isReactNativeMavenCacheEnabled(): Boolean = + when { + hasProperty(INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED) -> + property(INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED).toString().toBoolean() + else -> true + } + internal fun String.isNightly(): Boolean = this.startsWith("0.0.0") || "-nightly-" in this internal fun Project.exclusiveEnterpriseRepository() = diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt index a35e5f37c5d1..111f1439128d 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt @@ -62,6 +62,10 @@ object PropertyUtils { */ const val INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO = "react.internal.mavenLocalRepo" + /** Internal property that controls whether the React Native Maven cache is enabled. */ + const val INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED = + "react.internal.reactNativeMavenCacheEnabled" + /** * Internal property used to specify where the Windows Bash executable is located. This is useful * for contributors who are running Windows on their machine. diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 7726c9a0f265..83dae9725d07 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -272,6 +272,22 @@ class DependencyUtilsTest { .isNull() } + @Test + fun configureRepositories_withReactNativeMavenCacheDisabled_doesNotContainMavenCache() { + val mavenCacheURI = URI.create("https://rnmaven.swmtest.xyz/") + val project = createProject() + project.extensions.extraProperties.set("react.internal.reactNativeMavenCacheEnabled", "false") + + configureRepositories(project, false) + + assertThat( + project.repositories.firstOrNull { + it is MavenArtifactRepository && it.url == mavenCacheURI + } + ) + .isNull() + } + @Test fun configureRepositories_snapshotRepoHasHigherPriorityThanMavenCentral() { val repositoryURI = URI.create("https://central.sonatype.com/repository/maven-snapshots/") diff --git a/packages/react-native/scripts/cocoapods/rncore.rb b/packages/react-native/scripts/cocoapods/rncore.rb index afa93dd05dea..f7bf6eeaca27 100644 --- a/packages/react-native/scripts/cocoapods/rncore.rb +++ b/packages/react-native/scripts/cocoapods/rncore.rb @@ -387,7 +387,18 @@ def self.maven_repository_urls() return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] end - return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] + # Keep the React Native Maven cache before Maven Central so cached artifacts are tried first + # and Maven Central remains the fallback. + return react_native_maven_cache_enabled? ? + [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] : + [MAVEN_CENTRAL_REPOSITORY] + end + + def self.react_native_maven_cache_enabled?() + value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] + return true if value == nil || value == "" + + value.downcase != "false" && value != "0" end def self.nightly_tarball_url(version, configuration, dsyms = false) diff --git a/packages/react-native/scripts/cocoapods/rndependencies.rb b/packages/react-native/scripts/cocoapods/rndependencies.rb index 9555f819658e..659387924444 100644 --- a/packages/react-native/scripts/cocoapods/rndependencies.rb +++ b/packages/react-native/scripts/cocoapods/rndependencies.rb @@ -186,7 +186,18 @@ def self.maven_repository_urls() return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] end - return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] + # Keep the React Native Maven cache before Maven Central so cached artifacts are tried first + # and Maven Central remains the fallback. + return react_native_maven_cache_enabled? ? + [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] : + [MAVEN_CENTRAL_REPOSITORY] + end + + def self.react_native_maven_cache_enabled?() + value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] + return true if value == nil || value == "" + + value.downcase != "false" && value != "0" end def self.nightly_tarball_url(version, build_type) diff --git a/packages/react-native/scripts/ios-prebuild/hermes.js b/packages/react-native/scripts/ios-prebuild/hermes.js index 3ce8d8195cd9..c92848c458ba 100644 --- a/packages/react-native/scripts/ios-prebuild/hermes.js +++ b/packages/react-native/scripts/ios-prebuild/hermes.js @@ -8,7 +8,7 @@ * @format */ -const {createLogger} = require('./utils'); +const {createLogger, getMavenRepositoryUrls} = require('./utils'); const {execSync} = require('child_process'); const fs = require('fs'); const path = require('path'); @@ -17,8 +17,6 @@ const {promisify} = require('util'); const pipeline = promisify(stream.pipeline); const hermesLog = createLogger('Hermes'); -const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; -const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; const artifactExistenceCache /*: Map */ = new Map(); /*:: @@ -226,17 +224,6 @@ function getTarballUrls( ); } -function getMavenRepositoryUrls() /*: Array */ { - // You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. - // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - const enterpriseRepository = process.env.ENTERPRISE_REPOSITORY; - if (enterpriseRepository != null && enterpriseRepository !== '') { - return [enterpriseRepository.replace(/\/+$/, '')]; - } - - return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY]; -} - /** * Checks if a Hermes artifact exists at the given URL using fetch instead of curl */ diff --git a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js index 620248abb00b..05f2b6c18cc4 100644 --- a/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js +++ b/packages/react-native/scripts/ios-prebuild/reactNativeDependencies.js @@ -10,7 +10,11 @@ /*:: import type {BuildFlavor} from './types'; */ -const {computeNightlyTarballURL, createLogger} = require('./utils'); +const { + computeNightlyTarballURL, + createLogger, + getMavenRepositoryUrls, +} = require('./utils'); const {execSync} = require('child_process'); const fs = require('fs'); const path = require('path'); @@ -20,8 +24,6 @@ const {promisify} = require('util'); const pipeline = promisify(stream.pipeline); const dependencyLog = createLogger('ReactNativeDependencies'); -const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; -const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; const artifactExistenceCache /*: Map */ = new Map(); /** @@ -217,17 +219,6 @@ function getTarballUrls( ); } -function getMavenRepositoryUrls() /*: Array */ { - // You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. - // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - const enterpriseRepository = process.env.ENTERPRISE_REPOSITORY; - if (enterpriseRepository != null && enterpriseRepository !== '') { - return [enterpriseRepository.replace(/\/+$/, '')]; - } - - return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY]; -} - async function getNightlyTarballUrl( version /*: string */, buildType /*: BuildFlavor */, diff --git a/packages/react-native/scripts/ios-prebuild/utils.js b/packages/react-native/scripts/ios-prebuild/utils.js index d1c60f838b52..6e017aa90152 100644 --- a/packages/react-native/scripts/ios-prebuild/utils.js +++ b/packages/react-native/scripts/ios-prebuild/utils.js @@ -13,6 +13,9 @@ const {execSync} = require('child_process'); const fs = require('fs'); +const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; +const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; + /** * Creates a folder if it does not exist * @param {string} folderPath - The path to the folder @@ -102,9 +105,34 @@ async function computeNightlyTarballURL( return finalUrl; } +function getMavenRepositoryUrls() /*: Array */ { + // You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. + // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. + const enterpriseRepository = process.env.ENTERPRISE_REPOSITORY; + if (enterpriseRepository != null && enterpriseRepository !== '') { + return [enterpriseRepository.replace(/\/+$/, '')]; + } + + // Keep the React Native Maven cache before Maven Central so cached artifacts are tried first + // and Maven Central remains the fallback. + return isReactNativeMavenCacheEnabled() + ? [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] + : [MAVEN_CENTRAL_REPOSITORY]; +} + +function isReactNativeMavenCacheEnabled() /*: boolean */ { + const value = process.env.RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED; + if (value == null || value === '') { + return true; + } + + return value.toLowerCase() !== 'false' && value !== '0'; +} + module.exports = { createFolderIfNotExists, throwIfOnEden, createLogger, computeNightlyTarballURL, + getMavenRepositoryUrls, }; diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index f05c98c59165..e48657238399 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -212,7 +212,18 @@ def maven_repository_urls() return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] end - return [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] + # Keep the React Native Maven cache before Maven Central so cached artifacts are tried first + # and Maven Central remains the fallback. + return react_native_maven_cache_enabled? ? + [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] : + [MAVEN_CENTRAL_REPOSITORY] +end + +def react_native_maven_cache_enabled?() + value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] + return true if value == nil || value == "" + + value.downcase != "false" && value != "0" end def download_stable_hermes(react_native_path, version, configuration) From 60b7f96f6685318211cb200df29c7e1473311fac Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 26 Jun 2026 11:27:26 +0200 Subject: [PATCH 07/13] refactor ruby files --- .../react-native/scripts/cocoapods/rncore.rb | 26 +------------------ .../scripts/cocoapods/rndependencies.rb | 26 +------------------ .../react-native/scripts/cocoapods/utils.rb | 24 +++++++++++++++++ 3 files changed, 26 insertions(+), 50 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/rncore.rb b/packages/react-native/scripts/cocoapods/rncore.rb index f7bf6eeaca27..a0ac7e050d30 100644 --- a/packages/react-native/scripts/cocoapods/rncore.rb +++ b/packages/react-native/scripts/cocoapods/rncore.rb @@ -44,9 +44,6 @@ def add_rncore_dependency(s) ## - RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS: If set to 1, it will download the dSYMs for the prebuilt RNCore frameworks and install these in the framework folders class ReactNativeCoreUtils - MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" - REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" - @@build_from_source = true @@react_native_path = "" @@react_native_version = "" @@ -373,34 +370,13 @@ def self.stable_tarball_url(version, build_type, dsyms = false) def self.stable_tarball_urls(version, build_type, dsyms = false) group = "com/facebook/react" - return maven_repository_urls().map { |maven_repo_url| + return ReactNativePodsUtils.maven_repository_urls().map { |maven_repo_url| # Sample url from Maven: # https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.81.0/react-native-artifacts-0.81.0-reactnative-core-debug.tar.gz "#{maven_repo_url}/#{group}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-reactnative-core-#{dsyms ? "dSYM-" : ""}#{build_type.to_s}.tar.gz" } end - def self.maven_repository_urls() - ## You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. - ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - if ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" - return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] - end - - # Keep the React Native Maven cache before Maven Central so cached artifacts are tried first - # and Maven Central remains the fallback. - return react_native_maven_cache_enabled? ? - [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] : - [MAVEN_CENTRAL_REPOSITORY] - end - - def self.react_native_maven_cache_enabled?() - value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] - return true if value == nil || value == "" - - value.downcase != "false" && value != "0" - end - def self.nightly_tarball_url(version, configuration, dsyms = false) artefact_coordinate = "react-native-artifacts" artefact_name = "reactnative-core-#{dsyms ? "dSYM-" : ""}#{configuration ? configuration : "debug"}.tar.gz" diff --git a/packages/react-native/scripts/cocoapods/rndependencies.rb b/packages/react-native/scripts/cocoapods/rndependencies.rb index 659387924444..619244b4491b 100644 --- a/packages/react-native/scripts/cocoapods/rndependencies.rb +++ b/packages/react-native/scripts/cocoapods/rndependencies.rb @@ -57,9 +57,6 @@ def add_rn_third_party_dependencies(s) end class ReactNativeDependenciesUtils - MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" - REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" - @@build_from_source = true @@react_native_path = "" @@react_native_version = "" @@ -174,32 +171,11 @@ def self.release_tarball_url(version, build_type) def self.release_tarball_urls(version, build_type) group = "com/facebook/react" - return maven_repository_urls().map { |maven_repo_url| + return ReactNativePodsUtils.maven_repository_urls().map { |maven_repo_url| "#{maven_repo_url}/#{group}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-reactnative-dependencies-#{build_type.to_s}.tar.gz" } end - def self.maven_repository_urls() - ## You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. - ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. - if ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" - return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] - end - - # Keep the React Native Maven cache before Maven Central so cached artifacts are tried first - # and Maven Central remains the fallback. - return react_native_maven_cache_enabled? ? - [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] : - [MAVEN_CENTRAL_REPOSITORY] - end - - def self.react_native_maven_cache_enabled?() - value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] - return true if value == nil || value == "" - - value.downcase != "false" && value != "0" - end - def self.nightly_tarball_url(version, build_type) artifact_coordinate = "react-native-artifacts" artifact_name = "reactnative-dependencies-#{build_type.to_s}.tar.gz" diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 0e388d6a7ef5..98602455a672 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -12,11 +12,35 @@ # Utilities class for React Native Cocoapods class ReactNativePodsUtils + MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" + REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" + # URI::File.build validates path components as ASCII, so escape the filesystem path first. def self.local_file_uri(path) URI::File.build(path: URI::DEFAULT_PARSER.escape(path)).to_s end + def self.maven_repository_urls() + ## You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. + ## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. + if ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" + return [ENV['ENTERPRISE_REPOSITORY'].delete_suffix("/")] + end + + # Keep the React Native Maven cache before Maven Central so cached artifacts are tried first + # and Maven Central remains the fallback. + return react_native_maven_cache_enabled? ? + [REACT_NATIVE_MAVEN_CACHE_REPOSITORY, MAVEN_CENTRAL_REPOSITORY] : + [MAVEN_CENTRAL_REPOSITORY] + end + + def self.react_native_maven_cache_enabled?() + value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] + return true if value == nil || value == "" + + value.downcase != "false" && value != "0" + end + def self.warn_if_not_on_arm64 if SysctlChecker.new().call_sysctl_arm64() == 1 && !Environment.new().ruby_platform().include?('arm64') Pod::UI.warn 'Do not use "pod install" from inside Rosetta2 (x86_64 emulation on arm64).' From 0e5edbcfe588f206c8b0e6e0d506e4472411048f Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Thu, 23 Jul 2026 15:59:28 +0200 Subject: [PATCH 08/13] change url to https://repo.reactnative.dev/ --- .../kotlin/com/facebook/react/utils/DependencyUtils.kt | 2 +- .../com/facebook/react/utils/DependencyUtilsTest.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index 900acb417b05..d8942ee14050 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -28,7 +28,7 @@ import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository internal object DependencyUtils { - private const val REACT_NATIVE_MAVEN_CACHE_URL = "https://rnmaven.swmtest.xyz/" + private const val REACT_NATIVE_MAVEN_CACHE_URL = "https://repo.reactnative.dev/" internal data class Coordinates( val versionString: String, diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 83dae9725d07..cc0e3c2f18e2 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -63,7 +63,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_containsReactNativeMavenCache() { - val repositoryURI = URI.create("https://rnmaven.swmtest.xyz/") + val repositoryURI = URI.create("https://repo.reactnative.dev/") val project = createProject() configureRepositories(project, false) @@ -238,7 +238,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_mavenCacheHasHigherPriorityThanMavenCentral() { - val mavenCacheURI = URI.create("https://rnmaven.swmtest.xyz/") + val mavenCacheURI = URI.create("https://repo.reactnative.dev/") val mavenCentralURI = URI.create("https://repo.maven.apache.org/maven2/") val project = createProject() @@ -258,7 +258,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_withProjectPropertySet_doesNotContainMavenCache() { val localMaven = tempFolder.newFolder("m2") - val mavenCacheURI = URI.create("https://rnmaven.swmtest.xyz/") + val mavenCacheURI = URI.create("https://repo.reactnative.dev/") val project = createProject() project.extensions.extraProperties.set("react.internal.mavenLocalRepo", localMaven.absolutePath) @@ -274,7 +274,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_withReactNativeMavenCacheDisabled_doesNotContainMavenCache() { - val mavenCacheURI = URI.create("https://rnmaven.swmtest.xyz/") + val mavenCacheURI = URI.create("https://repo.reactnative.dev/") val project = createProject() project.extensions.extraProperties.set("react.internal.reactNativeMavenCacheEnabled", "false") From aa5c20dcb49f2ada6be31adf04f3a5e8d1e63f8c Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Thu, 23 Jul 2026 16:51:35 +0200 Subject: [PATCH 09/13] change repo url in test files --- packages/react-native/scripts/cocoapods/utils.rb | 2 +- packages/react-native/scripts/ios-prebuild/utils.js | 2 +- packages/react-native/sdks/hermes-engine/hermes-utils.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 98602455a672..77e1af7544aa 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -13,7 +13,7 @@ # Utilities class for React Native Cocoapods class ReactNativePodsUtils MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" - REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" + REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://repo.reactnative.dev/" # URI::File.build validates path components as ASCII, so escape the filesystem path first. def self.local_file_uri(path) diff --git a/packages/react-native/scripts/ios-prebuild/utils.js b/packages/react-native/scripts/ios-prebuild/utils.js index 6e017aa90152..2a5279248e22 100644 --- a/packages/react-native/scripts/ios-prebuild/utils.js +++ b/packages/react-native/scripts/ios-prebuild/utils.js @@ -14,7 +14,7 @@ const {execSync} = require('child_process'); const fs = require('fs'); const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; -const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://rnmaven.swmtest.xyz'; +const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://repo.reactnative.dev/'; /** * Creates a folder if it does not exist diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index e48657238399..e361a8f4f4ab 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -8,7 +8,7 @@ HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git" ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE" MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" -REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://rnmaven.swmtest.xyz" +REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://repo.reactnative.dev/" module HermesEngineSourceType LOCAL_PREBUILT_TARBALL = :local_prebuilt_tarball From c0b66198c6e60bc0d23bd9f6716ae6cc68e27f9d Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 24 Jul 2026 11:34:34 +0200 Subject: [PATCH 10/13] add maven2 to url --- .../facebook/react/utils/DependencyUtils.kt | 2 +- .../react/utils/DependencyUtilsTest.kt | 8 ++--- .../react-native/scripts/cocoapods/utils.rb | 2 +- .../scripts/ios-prebuild/utils.js | 33 ++++++++++--------- .../sdks/hermes-engine/hermes-utils.rb | 2 +- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index d8942ee14050..1fbbe0dc3cf9 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -28,7 +28,7 @@ import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository internal object DependencyUtils { - private const val REACT_NATIVE_MAVEN_CACHE_URL = "https://repo.reactnative.dev/" + private const val REACT_NATIVE_MAVEN_CACHE_URL = "https://repo.reactnative.dev/maven2" internal data class Coordinates( val versionString: String, diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index cc0e3c2f18e2..955ed51d6f7f 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -63,7 +63,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_containsReactNativeMavenCache() { - val repositoryURI = URI.create("https://repo.reactnative.dev/") + val repositoryURI = URI.create("https://repo.reactnative.dev/maven2") val project = createProject() configureRepositories(project, false) @@ -238,7 +238,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_mavenCacheHasHigherPriorityThanMavenCentral() { - val mavenCacheURI = URI.create("https://repo.reactnative.dev/") + val mavenCacheURI = URI.create("https://repo.reactnative.dev/maven2") val mavenCentralURI = URI.create("https://repo.maven.apache.org/maven2/") val project = createProject() @@ -258,7 +258,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_withProjectPropertySet_doesNotContainMavenCache() { val localMaven = tempFolder.newFolder("m2") - val mavenCacheURI = URI.create("https://repo.reactnative.dev/") + val mavenCacheURI = URI.create("https://repo.reactnative.dev/maven2") val project = createProject() project.extensions.extraProperties.set("react.internal.mavenLocalRepo", localMaven.absolutePath) @@ -274,7 +274,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_withReactNativeMavenCacheDisabled_doesNotContainMavenCache() { - val mavenCacheURI = URI.create("https://repo.reactnative.dev/") + val mavenCacheURI = URI.create("https://repo.reactnative.dev/maven2") val project = createProject() project.extensions.extraProperties.set("react.internal.reactNativeMavenCacheEnabled", "false") diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 77e1af7544aa..4f5c3f95e9ac 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -13,7 +13,7 @@ # Utilities class for React Native Cocoapods class ReactNativePodsUtils MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" - REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://repo.reactnative.dev/" + REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://repo.reactnative.dev/maven2" # URI::File.build validates path components as ASCII, so escape the filesystem path first. def self.local_file_uri(path) diff --git a/packages/react-native/scripts/ios-prebuild/utils.js b/packages/react-native/scripts/ios-prebuild/utils.js index 2a5279248e22..df4f55710d41 100644 --- a/packages/react-native/scripts/ios-prebuild/utils.js +++ b/packages/react-native/scripts/ios-prebuild/utils.js @@ -8,20 +8,21 @@ * @format */ -/*:: import type {BuildFlavor, MavenSubGroup} from './types'; */ +import type {BuildFlavor, MavenSubGroup} from './types'; const {execSync} = require('child_process'); const fs = require('fs'); const MAVEN_CENTRAL_REPOSITORY = 'https://repo1.maven.org/maven2'; -const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = 'https://repo.reactnative.dev/'; +const REACT_NATIVE_MAVEN_CACHE_REPOSITORY = + 'https://repo.reactnative.dev/maven2'; /** * Creates a folder if it does not exist * @param {string} folderPath - The path to the folder * @returns {string} The path to the created or existing folder */ -function createFolderIfNotExists(folderPath /*:string*/) /*: string */ { +function createFolderIfNotExists(folderPath: string): string { if (!fs.existsSync(folderPath)) { fs.mkdirSync(folderPath, {recursive: true}); if (!fs.existsSync(folderPath)) { @@ -43,15 +44,15 @@ function throwIfOnEden() { } function createLogger( - prefix /*: string */, -) /*: (message: string, level?: 'info' | 'warning' | 'error') => void */ { + prefix: string, +): (message: string, level?: 'info' | 'warning' | 'error') => void { return function ( - message /*: string */, - level /*: 'info' | 'warning' | 'error' */ = 'info', + message: string, + level: 'info' | 'warning' | 'error' = 'info', ) { // Simple log coloring for terminal output const resolvedPrefix = `[${prefix}] `; - let colorFn = (x /*:string*/) => x; + let colorFn = (x: string) => x; if (process.stdout.isTTY) { if (level === 'info') colorFn = x => `\x1b[32m${x}\x1b[0m`; else if (level === 'error') colorFn = x => `\x1b[31m${x}\x1b[0m`; @@ -63,12 +64,12 @@ function createLogger( } async function computeNightlyTarballURL( - version /*: string */, - buildType /*: BuildFlavor */, - subGroup /*: MavenSubGroup */, - artifactCoordinate /*: string */, - artifactName /*: string */, -) /*: Promise */ { + version: string, + buildType: BuildFlavor, + subGroup: MavenSubGroup, + artifactCoordinate: string, + artifactName: string, +): Promise { const xmlUrl = `https://central.sonatype.com/repository/maven-snapshots/com/facebook/${subGroup}/${artifactCoordinate}/${version}-SNAPSHOT/maven-metadata.xml`; const response = await fetch(xmlUrl); @@ -105,7 +106,7 @@ async function computeNightlyTarballURL( return finalUrl; } -function getMavenRepositoryUrls() /*: Array */ { +function getMavenRepositoryUrls(): Array { // You can use the `ENTERPRISE_REPOSITORY` variable to customise the base url from which artifacts will be downloaded. // The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central. const enterpriseRepository = process.env.ENTERPRISE_REPOSITORY; @@ -120,7 +121,7 @@ function getMavenRepositoryUrls() /*: Array */ { : [MAVEN_CENTRAL_REPOSITORY]; } -function isReactNativeMavenCacheEnabled() /*: boolean */ { +function isReactNativeMavenCacheEnabled(): boolean { const value = process.env.RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED; if (value == null || value === '') { return true; diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index e361a8f4f4ab..2f43ef1139e9 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -8,7 +8,7 @@ HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git" ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE" MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2" -REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://repo.reactnative.dev/" +REACT_NATIVE_MAVEN_CACHE_REPOSITORY = "https://repo.reactnative.dev/maven2" module HermesEngineSourceType LOCAL_PREBUILT_TARBALL = :local_prebuilt_tarball From f3262d5aeaa17969eefffa48c902d4a0e65520d8 Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 24 Jul 2026 15:17:56 +0200 Subject: [PATCH 11/13] set cache to false by default --- .../facebook/react/utils/DependencyUtils.kt | 2 +- .../react/utils/DependencyUtilsTest.kt | 19 ++++++++++++++++++- .../react-native/scripts/cocoapods/utils.rb | 2 +- .../scripts/ios-prebuild/utils.js | 2 +- .../sdks/hermes-engine/hermes-utils.rb | 2 +- 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index 1fbbe0dc3cf9..2db330b92325 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -288,7 +288,7 @@ internal object DependencyUtils { when { hasProperty(INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED) -> property(INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED).toString().toBoolean() - else -> true + else -> false } internal fun String.isNightly(): Boolean = this.startsWith("0.0.0") || "-nightly-" in this diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 955ed51d6f7f..539365029c9b 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -62,9 +62,10 @@ class DependencyUtilsTest { } @Test - fun configureRepositories_containsReactNativeMavenCache() { + fun configureRepositories_withReactNativeMavenCacheEnabled_containsMavenCache() { val repositoryURI = URI.create("https://repo.reactnative.dev/maven2") val project = createProject() + project.extensions.extraProperties.set("react.internal.reactNativeMavenCacheEnabled", "true") configureRepositories(project, false) @@ -241,6 +242,7 @@ class DependencyUtilsTest { val mavenCacheURI = URI.create("https://repo.reactnative.dev/maven2") val mavenCentralURI = URI.create("https://repo.maven.apache.org/maven2/") val project = createProject() + project.extensions.extraProperties.set("react.internal.reactNativeMavenCacheEnabled", "true") configureRepositories(project, false) @@ -272,6 +274,21 @@ class DependencyUtilsTest { .isNull() } + @Test + fun configureRepositories_byDefault_doesNotContainMavenCache() { + val mavenCacheURI = URI.create("https://repo.reactnative.dev/maven2") + val project = createProject() + + configureRepositories(project, false) + + assertThat( + project.repositories.firstOrNull { + it is MavenArtifactRepository && it.url == mavenCacheURI + } + ) + .isNull() + } + @Test fun configureRepositories_withReactNativeMavenCacheDisabled_doesNotContainMavenCache() { val mavenCacheURI = URI.create("https://repo.reactnative.dev/maven2") diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 4f5c3f95e9ac..8eed03174686 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -36,7 +36,7 @@ def self.maven_repository_urls() def self.react_native_maven_cache_enabled?() value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] - return true if value == nil || value == "" + return false if value == nil || value == "" value.downcase != "false" && value != "0" end diff --git a/packages/react-native/scripts/ios-prebuild/utils.js b/packages/react-native/scripts/ios-prebuild/utils.js index df4f55710d41..580cd9b12145 100644 --- a/packages/react-native/scripts/ios-prebuild/utils.js +++ b/packages/react-native/scripts/ios-prebuild/utils.js @@ -124,7 +124,7 @@ function getMavenRepositoryUrls(): Array { function isReactNativeMavenCacheEnabled(): boolean { const value = process.env.RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED; if (value == null || value === '') { - return true; + return false; } return value.toLowerCase() !== 'false' && value !== '0'; diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index 2f43ef1139e9..9397ac60e470 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -221,7 +221,7 @@ def maven_repository_urls() def react_native_maven_cache_enabled?() value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] - return true if value == nil || value == "" + return false if value == nil || value == "" value.downcase != "false" && value != "0" end From 4d1499ed883ecc99ab731c529f0bca8133a1cb22 Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 24 Jul 2026 15:24:27 +0200 Subject: [PATCH 12/13] add iOS tests --- .../__tests__/maven_cache_flag-test.rb | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 packages/react-native/scripts/cocoapods/__tests__/maven_cache_flag-test.rb diff --git a/packages/react-native/scripts/cocoapods/__tests__/maven_cache_flag-test.rb b/packages/react-native/scripts/cocoapods/__tests__/maven_cache_flag-test.rb new file mode 100644 index 000000000000..8bce687926b3 --- /dev/null +++ b/packages/react-native/scripts/cocoapods/__tests__/maven_cache_flag-test.rb @@ -0,0 +1,42 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "test/unit" +require_relative "../utils.rb" +require_relative "../../../sdks/hermes-engine/hermes-utils.rb" + +class MavenCacheFlagTests < Test::Unit::TestCase + def setup + @original_value = ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] + ENV.delete('RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED') + end + + def teardown + if @original_value == nil + ENV.delete('RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED') + else + ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] = @original_value + end + end + + def test_mavenCache_isDisabledByDefault + assert_false(ReactNativePodsUtils.react_native_maven_cache_enabled?) + assert_false(react_native_maven_cache_enabled?) + end + + def test_mavenCache_isEnabledWhenExplicitlySetToTrue + ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] = 'true' + + assert_true(ReactNativePodsUtils.react_native_maven_cache_enabled?) + assert_true(react_native_maven_cache_enabled?) + end + + def test_mavenCache_isDisabledWhenExplicitlySetToFalse + ENV['RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED'] = 'false' + + assert_false(ReactNativePodsUtils.react_native_maven_cache_enabled?) + assert_false(react_native_maven_cache_enabled?) + end +end From f40fea30958e1222fd939313ddbbbd4af0c82b5f Mon Sep 17 00:00:00 2001 From: Dawid Malecki Date: Fri, 24 Jul 2026 17:45:48 +0200 Subject: [PATCH 13/13] check env var on Android --- .../facebook/react/utils/DependencyUtils.kt | 8 +++++- .../react/utils/DependencyUtilsTest.kt | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index 2db330b92325..4ab21ee29b0f 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -29,6 +29,8 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository internal object DependencyUtils { private const val REACT_NATIVE_MAVEN_CACHE_URL = "https://repo.reactnative.dev/maven2" + private const val REACT_NATIVE_MAVEN_CACHE_ENABLED_ENV = + "RCT_REACT_NATIVE_MAVEN_CACHE_ENABLED" internal data class Coordinates( val versionString: String, @@ -284,10 +286,14 @@ internal object DependencyUtils { else -> INCLUDE_JITPACK_REPOSITORY_DEFAULT } - internal fun Project.isReactNativeMavenCacheEnabled(): Boolean = + internal fun Project.isReactNativeMavenCacheEnabled( + environmentValue: String? = System.getenv(REACT_NATIVE_MAVEN_CACHE_ENABLED_ENV) + ): Boolean = when { hasProperty(INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED) -> property(INTERNAL_REACT_NATIVE_MAVEN_CACHE_ENABLED).toString().toBoolean() + !environmentValue.isNullOrEmpty() -> + !environmentValue.equals("false", ignoreCase = true) && environmentValue != "0" else -> false } diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 539365029c9b..93a8b823da97 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -12,6 +12,7 @@ import com.facebook.react.utils.DependencyUtils.configureDependencies import com.facebook.react.utils.DependencyUtils.configureRepositories import com.facebook.react.utils.DependencyUtils.exclusiveEnterpriseRepository import com.facebook.react.utils.DependencyUtils.getDependencySubstitutions +import com.facebook.react.utils.DependencyUtils.isReactNativeMavenCacheEnabled import com.facebook.react.utils.DependencyUtils.isNightly import com.facebook.react.utils.DependencyUtils.mavenRepoFromURI import com.facebook.react.utils.DependencyUtils.mavenRepoFromUrl @@ -305,6 +306,33 @@ class DependencyUtilsTest { .isNull() } + @Test + fun isReactNativeMavenCacheEnabled_withEnvironmentVariableEnabled_returnsTrue() { + val project = createProject() + + assertThat(project.isReactNativeMavenCacheEnabled("true")).isTrue() + assertThat(project.isReactNativeMavenCacheEnabled("1")).isTrue() + } + + @Test + fun isReactNativeMavenCacheEnabled_withEnvironmentVariableDisabled_returnsFalse() { + val project = createProject() + + assertThat(project.isReactNativeMavenCacheEnabled(null)).isFalse() + assertThat(project.isReactNativeMavenCacheEnabled("")).isFalse() + assertThat(project.isReactNativeMavenCacheEnabled("false")).isFalse() + assertThat(project.isReactNativeMavenCacheEnabled("FALSE")).isFalse() + assertThat(project.isReactNativeMavenCacheEnabled("0")).isFalse() + } + + @Test + fun isReactNativeMavenCacheEnabled_withProjectProperty_ignoresEnvironmentVariable() { + val project = createProject() + project.extensions.extraProperties.set("react.internal.reactNativeMavenCacheEnabled", "false") + + assertThat(project.isReactNativeMavenCacheEnabled("true")).isFalse() + } + @Test fun configureRepositories_snapshotRepoHasHigherPriorityThanMavenCentral() { val repositoryURI = URI.create("https://central.sonatype.com/repository/maven-snapshots/")