我的Jenkins版本给了我以下错误:
13:18:22 FAILURE: Build failed with an exception. 13:18:22 13:18:22 * Where: 13:18:22 Script '/Users/abcd/Jenkins/Jenkins-Workspaces/ABCD/ABCDL/node_modules/@react-native-community/cli-platform-android/native_modules.gradle' line: 190 13:18:22 13:18:22 * What went wrong: 13:18:22 A problem occurred evaluating settings 'AppName'. 13:18:22 > Text must not be null or empty 13:18:22
似乎问题出在@react-native-community/cli- platform节点模块上,但请阅读以下已关闭的问题:https : //github.com/facebook/react- native/issues/25479
@react-native-community/cli- platform
对我来说,尚不清楚该方案的最终提议是什么。
有一个关于此本机问题的更简单修补程序的建议:https : //github.com/facebook/react- native/issues/25822
但我的错误不是抱怨那条线。
至于安装,@react-native-community/cli我相信我已经在package-lock.json文件中包含了它:
@react-native-community/cli
package-lock.json
"react-native": { "version": "0.60.4", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.60.4.tgz", "integrity": "sha512-WE41lbGQjnzM9srIFtMDtMJkQAvk95iZwuFvAxl68s80bkYa7Ou9sGFHpeYIV6cY8yHtheCSo5q6YMxhdfkdOw==", "requires": { "@babel/runtime": "^7.0.0", "@react-native-community/cli": "^2.0.1", "@react-native-community/cli-platform-android": "^2.0.1", "@react-native-community/cli-platform-ios": "^2.0.1",
其他人提到了有关的内容app/build.gradle,这是我的相关部分:
app/build.gradle
// Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.compile into 'libs' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
还提到了android/settings.gradle,这是我的:
android/settings.gradle
rootProject.name = 'NFIBEngage' include ':react-native-device-info' project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android') include ':appcenter-crashes' project(':appcenter-crashes').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-crashes/android') include ':appcenter-analytics' project(':appcenter-analytics').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-analytics/android') include ':appcenter' project(':appcenter').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter/android') include ':react-native-webview' project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android') apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app'
根据我在这里收集的信息:
https://react-native-community.github.io/upgrade- helper/?from=0.53.3&to=0.60.4
以上文件是正确的。
那么,这里到底有什么问题,我该如何解决?
就node_modules/@react-native-community/cli-platform- android/native_modules.gradle line 190这个而言:
node_modules/@react-native-community/cli-platform- android/native_modules.gradle line 190
def json = new JsonSlurper().parseText(reactNativeConfigOutput)
问题可能与我如何编写index.js文件有关:
/** * @format */ import { AppRegistry } from "react-native"; // old config code import KeyboardManager from "react-native-keyboard-manager"; // old config code ^^^ import NFIBEngage from "./App"; import { name as appName } from "./app.json"; // old config code import { Sentry } from "react-native-sentry"; Sentry.config( "https://asdf@sentry.io/123456677" ).install(); KeyboardManager.setToolbarPreviousNextButtonEnable(true); // old config code ^^^ AppRegistry.registerComponent("NFIBEngage", () => NFIBEngage);
被AppRegistry.registerComponent()正确写入?
AppRegistry.registerComponent()
我在本地运行了Jenkins脚本,我相信这里就是这个脚本:
import fs from "fs-extra"; import eachSeries from "async/eachSeries"; import { exec } from "child_process"; import { androidDirectory } from "../../app.json"; import { resolveFromRoot, distDir, createLogger } from "../build"; const logger = createLogger("android"); const APK_PATTERN = /release\.apk$/i; function copyArtifactsToDist() { logger.logHeader("Copying APK to Dist", { repeatChar: "=" }); const baseDir = `${androidDirectory}/app/build/outputs/apk`; const allFlavs = ["dev", "qa", "ua", "prod"]; const branchName = process.env.GitVersion_BranchName || ""; const buildFlavour = branchName.startsWith("release/") ? allFlavs : ["dev"]; const envs = { dev: "INT", qa: "QA", ua: "UA", prod: "" }; buildFlavour .map(env => { const apkOutputDir = resolveFromRoot(`${baseDir}/${env}/release`); return { apkOutputDir, env }; }) .forEach(({ apkOutputDir, env }) => { const src = `${apkOutputDir}/app-${env}-release.apk`; //prettier-ignore const binaryName = env === 'prod' ? 'ENGAL.apk' : `ENGAL-${envs[env]}.apk`; const dest = `${distDir}/${binaryName}`; fs.copy(src, dest, (err: Error) => { if (err) { logger.error(err); } }); }); } function run() { logger.logHeader("Starting Android Builds", { repeatChar: "#" }); const flavours = [ { endpoint: "dv", flavour: "Dev", appcenterKey: "<hashKeys>" }, { endpoint: "qa", flavour: "Qa", appcenterKey: "<hashKeys>" }, { endpoint: "ua", flavour: "Ua", appcenterKey: "<hashKeys>" }, { endpoint: "prod", flavour: "Prod", appcenterKey: "<hashKeys>" } ]; const versionCode = process.env.Build || 1; const release = process.env.GitVersion_MajorMinorPatch || "1.0.0"; const fullAppVersion = `${release}-${versionCode}`; const devFlav = flavours.find(f => f.flavour.toLocaleLowerCase() === "dev"); const branchName = process.env.GitVersion_BranchName || ""; const buildFlavour = branchName.startsWith("release/") ? flavours : [devFlav]; eachSeries( buildFlavour, (f, callback) => { //prettier-ignore logger.logHeader( `starting gradle assemble${f.flavour}Release with flag - versionName=${fullAppVersion} -PversionCode=${versionCode}`, {repeatChar: '-'} ); const engaInfo = `ENGAGE_VERSION=${fullAppVersion}`; const engaEndpoint = `ENGAGE_ENDPOINT=${f.endpoint}`; const engaCenter = `APPCENTER_KEY=${f.appcenterKey}`; const engaPlatform = "APPCENTER_PLATFORM=android"; //prettier-ignore const prepare = `${engaEndpoint} ${engaCenter} ${engaInfo} ${engaPlatform} npm run setup`; const cd = `cd ${androidDirectory}`; //prettier-ignore const releaseCmd = `./gradlew assemble${f.flavour}Release -PversionName=${fullAppVersion} -PversionCode=${versionCode} && cd ..`; exec(`${prepare} && ${cd} && ${releaseCmd}`, err => { if (err) { return callback(err); } logger.logHeader(`${f.flavour} Android Build Successful!`, { repeatChar: "#" }); logger.close(); callback(null); }); }, error => { if (error) { logger.logHeader("Android Builds Failed!", { repeatChar: "#" }); logger.error(error); logger.close(); } copyArtifactsToDist(); } ); } run();
通过npm run build和本地我收到此错误:
npm run build
FAILURE: Build failed with an exception. * What went wrong: Task 'assembleDevRelease' not found in root project 'AppName'. Some candidates are: 'assembleRelease'.
这些是相关的错误吗?任何对React Native构建有经验的人?
正如建议的那样,我查看了我的android/app/build.gradle文件productFlavors,发现它们之间确实缺少:
android/app/build.gradle
productFlavors
buildTypes { debug { signingConfig signingConfigs.debug } release { // Caution! In production, you need to generate your own keystore file. // see https://facebook.github.io/react-native/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // https://developer.android.com/studio/build/configure-apk-splits.html def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = versionCodes.get(abi) * 123456 + defaultConfig.versionCode } } }
所以我这样添加它:
buildTypes { debug { signingConfig signingConfigs.debug } release { // Caution! In production, you need to generate your own keystore file. // see https://facebook.github.io/react-native/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } productFlavors { dev { resValue "string", "app_name", getAppName("INT") resValue "string", "link_launcher", getLauncher("dv") applicationIdSuffix ".dv" manifestPlaceholders = [onesignal_app_id: "<hash_id>", onesignal_google_project_number: "123456789"] } qa { resValue "string", "app_name", getAppName("QA") resValue "string", "link_launcher", getLauncher("qa") applicationIdSuffix ".qa" manifestPlaceholders = [onesignal_app_id: "<hash_id>", onesignal_google_project_number: "123456789"] } ua { resValue "string", "app_name", getAppName("UA") resValue "string", "link_launcher", getLauncher("ua") applicationIdSuffix ".ua" manifestPlaceholders = [onesignal_app_id: "<hash_id>", onesignal_google_project_number: "123456789"] } prod { resValue "string", "app_name", getAppName() resValue "string", "link_launcher", getLauncher() manifestPlaceholders = [onesignal_app_id: "<hash_id>", onesignal_google_project_number: "601125149914"] } } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // https://developer.android.com/studio/build/configure-apk-splits.html def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = versionCodes.get(abi) * 1048576 + defaultConfig.versionCode } } }
该buildTypes期待比原来的传统有点不同的buildTypes,所以我不知道如果多数民众赞成不错,但无论如何我跑,然后npm run build再在本地和得到这个错误:
buildTypes
* Where: Build file '/Users/danale/Projects/NFIBEngage/android/app/build.gradle' line: 168 * What went wrong: A problem occurred evaluating project ':app'. > Could not find method getAppName() for arguments [INT] on ProductFlavor_Decorated{name=dev, dimension=null, minSdkVersion=null, targetSdkVersion=null, renderscriptTargetApi=null, renderscriptSupportModeEnabled=null, renderscriptSupportModeBlasEnabled=null, renderscriptNdkModeEnabled=null, versionCode=null, versionName=null, applicationId=null, testApplicationId=null, testInstrumentationRunner=null, testInstrumentationRunnerArguments={}, testHandleProfiling=null, testFunctionalTest=null, signingConfig=null, resConfig=null, mBuildConfigFields={}, mResValues={}, mProguardFiles=[], mConsumerProguardFiles=[], mManifestPlaceholders={}, mWearAppUnbundled=null} of type com.android.build.gradle.internal.dsl.ProductFlavor.
通过添加缺少的方法,我能够解决本地错误,如下所示:
def appName = "Engage"; /** * Get the version name from command line param * * @return int If the param -PversionName is present then return int value or -1 */ def getAppName = { env -> return (env ? appName + " ("+ env + ")" : appName); } /** * Get the version name from command line param * * @return int If the param -PversionName is present then return int value or -1 */ def getLauncher = { env -> return (env ? "engage-" + env + ".nfib.org" : "engage.nfib.org"); } android { compileSdkVersion rootProject.ext.compileSdkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } flavorDimensions "default" defaultConfig { applicationId "com.nfib.engage" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" } } signingConfigs { debug { storeFile file('debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } } buildTypes { debug { signingConfig signingConfigs.debug } release { // Caution! In production, you need to generate your own keystore file. // see https://facebook.github.io/react-native/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } productFlavors { dev { dimension 'default' resValue "string", "app_name", getAppName("INT") resValue "string", "link_launcher", getLauncher("dv") applicationIdSuffix ".dv" manifestPlaceholders = [onesignal_app_id: "b78285eb-f1ec-46f3-9ad0-c7efe691a401", onesignal_google_project_number: "584236827312"] } qa { dimension 'default' resValue "string", "app_name", getAppName("QA") resValue "string", "link_launcher", getLauncher("qa") applicationIdSuffix ".qa" manifestPlaceholders = [onesignal_app_id: "e4280f5e-62ec-41a4-bd86-f5b94e471a36", onesignal_google_project_number: "162802054510"] } ua { dimension 'default' resValue "string", "app_name", getAppName("UA") resValue "string", "link_launcher", getLauncher("ua") applicationIdSuffix ".ua" manifestPlaceholders = [onesignal_app_id: "2ffd8dc0-9c6b-4035-999d-fc694194725a", onesignal_google_project_number: "594905904045"] } prod { dimension 'default' resValue "string", "app_name", getAppName() resValue "string", "link_launcher", getLauncher() manifestPlaceholders = [onesignal_app_id: "82dcb42f-1d35-4b79-bc28-2d1d02dbda36", onesignal_google_project_number: "601125149914"] } }
不幸的是,我在詹金斯身上仍然遇到同样的错误。
通过注释可以使构建正常运行的一些更改:
在package.json中,您的cli版本位于,^2.0.1并且2.0.1确实是您从github.com/facebook/react- native/issues/25479链接到的问题的cli版本,您是否已验证与def command = "../node_modules/.bin/react-native config"(from github.com/facebook/react- native/issues/…)中的对node_modules/@react-native-community/cli-platform- android/native_modules.gradle吗?您还应该确保cli的安装版本为> = 2.0.2。
^2.0.1
2.0.1
def command = "../node_modules/.bin/react-native config"
node_modules/@react-native-community/cli-platform- android/native_modules.gradle
2.0.2
确保将中的buildTypes和productFlavors定义android/app/build.gradle设置为包括要在jenkins工作中尝试构建的所有不同变体。像你看起来有味道dev,qa,ua和prod。请查看gradle文档developer.android.com/studio/build/build- variants#build-types了解更多信息。
dev
qa
ua
prod
看来您缺少的getAppName功能build.gradle。有点像ext.getAppName = {suffix = '' -> 'MyAppName' + suffix}。快速扫描您的build.gradle外观,就像您需要另一个调用一样getLauncher,它会为您使用的任何内容返回适当的字符串link_launcher。
getAppName
build.gradle
ext.getAppName = {suffix = '' -> 'MyAppName' + suffix}
getLauncher
link_launcher