1/** 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 * @format 8 */ 9 10'use strict'; 11 12const {exec, echo, exit, test, env, pushd, popd} = require('shelljs'); 13const {saveFiles} = require('./scm-utils'); 14const {createHermesPrebuiltArtifactsTarball} = require('./hermes/hermes-utils'); 15 16// TODO: we should probably remove this because of this? https://github.com/facebook/react-native/pull/34846 17function saveFilesToRestore(tmpPublishingFolder) { 18 const filesToSaveAndRestore = [ 19 'template/Gemfile', 20 'template/_ruby-version', 21 'template/package.json', 22 '.ruby-version', 23 'Gemfile.lock', 24 'Gemfile', 25 'package.json', 26 'ReactAndroid/gradle.properties', 27 'Libraries/Core/ReactNativeVersion.js', 28 'React/Base/RCTVersion.m', 29 'ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', 30 'ReactCommon/cxxreact/ReactNativeVersion.h', 31 ]; 32 33 saveFiles(filesToSaveAndRestore, tmpPublishingFolder); 34} 35 36function generateAndroidArtifacts(releaseVersion, tmpPublishingFolder) { 37 // -------- Generating Android Artifacts 38 echo('Generating Android artifacts inside /tmp/maven-local'); 39 if (exec('./gradlew publishAllToMavenTempLocal').code) { 40 echo('Could not generate artifacts'); 41 exit(1); 42 } 43 44 echo('Generated artifacts for Maven'); 45 46 let artifacts = [ 47 '.module', 48 '.pom', 49 '-debug.aar', 50 '-release.aar', 51 '-debug-sources.jar', 52 '-release-sources.jar', 53 ].map(suffix => { 54 return `react-android-${releaseVersion}${suffix}`; 55 }); 56 57 artifacts.forEach(name => { 58 if ( 59 !test( 60 '-e', 61 `/tmp/maven-local/com/facebook/react/react-android/${releaseVersion}/${name}`, 62 ) 63 ) { 64 echo( 65 `Failing as expected file: \n\ 66 /tmp/maven-local/com/facebook/react/react-android/${releaseVersion}/${name}\n\ 67 was not correctly generated.`, 68 ); 69 exit(1); 70 } 71 }); 72} 73 74function publishAndroidArtifactsToMaven(releaseVersion, isNightly) { 75 // -------- Publish every artifact to Maven Central 76 // The GPG key is base64 encoded on CircleCI and then decoded here 77 let buff = Buffer.from(env.ORG_GRADLE_PROJECT_SIGNING_KEY_ENCODED, 'base64'); 78 env.ORG_GRADLE_PROJECT_SIGNING_KEY = buff.toString('ascii'); 79 80 // We want to gate ourselves against accidentally publishing a 1.x or a 1000.x on 81 // maven central which will break the semver for our artifacts. 82 if (!isNightly && releaseVersion.startsWith('0.')) { 83 // -------- For stable releases, we also need to close and release the staging repository. 84 if ( 85 exec( 86 './gradlew publishAllToSonatype closeAndReleaseSonatypeStagingRepository -PisNightly=' + 87 isNightly, 88 ).code 89 ) { 90 echo( 91 'Failed to close and release the staging repository on Sonatype (Maven Central)', 92 ); 93 exit(1); 94 } 95 } else { 96 // -------- For nightly releases, we only need to publish the snapshot to Sonatype snapshot repo. 97 if (exec('./gradlew publishAllToSonatype -PisNightly=' + isNightly).code) { 98 echo('Failed to publish artifacts to Sonatype (Maven Central)'); 99 exit(1); 100 } 101 } 102 103 echo('Published artifacts to Maven Central'); 104} 105 106function generateiOSArtifacts( 107 jsiFolder, 108 hermesCoreSourceFolder, 109 buildType, 110 targetFolder, 111) { 112 pushd(`${hermesCoreSourceFolder}`); 113 114 //Need to generate hermesc 115 exec( 116 `${hermesCoreSourceFolder}/utils/build-hermesc-xcode.sh ${hermesCoreSourceFolder}/build_host_hermesc`, 117 ); 118 119 //Generating iOS Artifacts 120 exec( 121 `JSI_PATH=${jsiFolder} BUILD_TYPE=${buildType} ${hermesCoreSourceFolder}/utils/build-mac-framework.sh`, 122 ); 123 124 exec( 125 `JSI_PATH=${jsiFolder} BUILD_TYPE=${buildType} ${hermesCoreSourceFolder}/utils/build-ios-framework.sh`, 126 ); 127 128 popd(); 129 130 const tarballOutputPath = createHermesPrebuiltArtifactsTarball( 131 hermesCoreSourceFolder, 132 buildType, 133 targetFolder, 134 true, // this is excludeDebugSymbols, we keep it as the default 135 ); 136 137 return tarballOutputPath; 138} 139 140function failIfTagExists(version, buildType) { 141 // When dry-run in stable branch, the tag already exists. 142 // We are bypassing the tag-existence check when in a dry-run to have the CI pass 143 if (buildType === 'dry-run') { 144 return; 145 } 146 147 if (checkIfTagExists(version)) { 148 echo(`Tag v${version} already exists.`); 149 echo('You may want to rollback the last commit'); 150 echo('git reset --hard HEAD~1'); 151 exit(1); 152 } 153} 154 155function checkIfTagExists(version) { 156 const {code, stdout} = exec('git tag -l', {silent: true}); 157 if (code !== 0) { 158 throw new Error('Failed to retrieve the list of tags'); 159 } 160 const tags = new Set(stdout.split('\n')); 161 return tags.has(`v${version}`); 162} 163 164module.exports = { 165 generateAndroidArtifacts, 166 generateiOSArtifacts, 167 publishAndroidArtifactsToMaven, 168 saveFilesToRestore, 169 failIfTagExists, 170}; 171