jvm-test-suite common test sources for use in multiple test suites - kotlin

Using the jvm-test-suite gradle plugin, I would like to be able to create a common test source set for use in other test suites. I envision the structure to look like the following where the sources and resources from common can be used in unit, integration, functional, and performance:
project/
├─ src/
│ ├─ main/
│ ├─ test/
│ │ ├─ common/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ unit/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ integration/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ functional/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ performance/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
So far I have tried the following, which I thought would provide the proper classpaths for each test suite:
#file:Suppress("UnstableApiUsage")
plugins {
`jvm-test-suite`
}
// Register `commonTest` source set
sourceSets {
register("commonTest") {
java {
compileClasspath += named("main").get().output
runtimeClasspath += named("main").get().output
srcDir("src/test/common/kotlin")
}
resources {
srcDir("src/test/common/resources")
}
}
}
// Make `commonTestImplementation` extend from `testImplementation` so that we can use all dependencies that `testImplementation` uses
val commonTestImplementation by configurations.getting {
extendsFrom(configurations.named("testImplementation").get())
}
configure<TestingExtension> {
suites {
val sourceSetMain = sourceSets.named("main").get()
val sourceSetCommon = sourceSets.named("commonTest").get()
// These might be able to just be variables instead of lazy evaluation
val sourceSetMainClasspath = { sourceSetMain.compileClasspath + sourceSetMain.output }
val sourceSetCommonClasspath = { sourceSetMain.compileClasspath + sourceSetMain.output }
val test by getting(JvmTestSuite::class) {
testType.set(TestSuiteType.UNIT_TEST)
sources {
// Add common test compile classpath and outputs to the `unitTest` suite?
compileClasspath += sourceSetCommonClasspath()
runtimeClasspath += output + compileClasspath
java {
setSrcDirs(listOf("src/test/unit/kotlin"))
// I've also tried the following which only works when applied to only 1 test suite but not all. Same with the commented out resources portion directly below
// setSrcDirs(listOf("src/test/unit/kotlin", sourceSetCommon.java.srcDirs))
}
resources {
setSrcDirs(listOf("src/test/unit/resources"))
// setSrcDirs(listOf("src/test/unit/resources", sourceSetCommon.resources.srcDirs))
}
}
}
val functionalTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.FUNCTIONAL_TEST)
dependencies {
implementation(project())
}
sources {
// Add common test compile classpath and outputs to the `unitTest` suite?
compileClasspath += sourceSetCommonClasspath()
runtimeClasspath += output + compileClasspath
java {
setSrcDirs(listOf("src/test/functional/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/functional/resources"))
}
}
targets {
all {
testTask.configure {
shouldRunAfter(test)
}
}
}
}
}
}
val functionalTestImplementation by configurations.getting {
extendsFrom(configurations.named("testImplementation").get())
}
From this, I expect to be able to access common test sources in both the unit test (unit) directory and functional test (functional) directory. However, this does not work as expected. Any thoughts/input are greatly appreciated!

Related

gradle publishing not working - No such Algorithm

I have a nexus repository that I want to publish my gradles versions catalog to. Here's the gradle build script:
buildscript {
dependencies {
classpath("com.android.tools.build:gradle:7.2.0")
}
}
plugins {
id ("version-catalog")
id ("maven-publish")
}
catalog {
versionCatalog {
from(files("gradle/libs.versions.toml"))
}
}
publishing {
publications {
create<MavenPublication>("VersionCatalog") {
groupId = "com.phinneyridge"
artifactId = "com.phinneyridge.version.catalog"
version = "1.0.0"
from(components["versionCatalog"])
}
repositories {
maven {
name = "PhinneyRidgeRepository"
url = uri(System.getenv()["PhinneyRidgeReleaseRepoUrl"].toString())
credentials {
username = System.getenv().get("PhinneyRidgeRepoUser").toString()
password = System.getenv().get("PhinneyRidgeRepoUserPW").toString()
}
println(url)
println(credentials.username + ":" + credentials.password)
}
}
}
}
Here's the output I get when I try to publish:
gradlew publish
Type-safe dependency accessors is an incubating feature.
Configure project :
https://ridgetop/nexus/repository/maven-releases/
publisher:mavenpublisher
Task :publishVersionCatalogPublicationToPhinneyRidgeRepositoryRepository FAILED
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':publishVersionCatalogPublicationToPhinneyRidgeRepositoryRepository'.
Failed to publish publication 'VersionCatalog' to repository 'PhinneyRidgeRepository'
java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.
SSLContextImpl$DefaultSSLContext)
If I changed the maven repository to mavenLocal(), the script actually publishes the version catalog to the local maven repository just fine.
What's also interesting, is that I have a custom gradle plugin in a different build script and it fairly well the same looking code pattern, and it successfully publishes the custom gradle plugin to same repository. Here's the code for that working script:
plugins {
id ("java-gradle-plugin")
"java-library"
id ("maven-publish")
id("com.gradle.plugin-publish") version "0.20.0"
id("org.jetbrains.kotlin.jvm") version "1.6.20"
id("org.gradle.kotlin.kotlin-dsl") version "2.1.7"
}
gradlePlugin {
group = "com.phinneyridge"
plugins {
create("PhinneyRidgePlugin") {
id = "com.phinneyridge.project"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeProjectPlugin"
}
create("PhinneyRidgeAndroidAppPlugin") {
id = "com.phinneyridge.android.application"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeAndroidAppPlugin"
}
create("PhinneyRidgeAndroidLibPlugin") {
id = "com.phinneyridge.android.library"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeAndroidLibPlugin"
}
create("PhinneyRidgeAndroidKotlinAppPlugin") {
id = "com.phinneyridge.android.kotlin.application"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeAndroidKotlinAppPlugin"
}
create("PhinneyRidgeAndroidKotlinLibPlugin") {
id = "com.phinneyridge.android.kotlin.library"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeAndroidKotlinLibPlugin"
}
create("PhinneyRidgeJavaAppPlugin") {
id = "com.phinneyridge.java.application"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeJavaAppPlugin"
}
create("PhinneyRidgeJavaLibPlugin") {
id = "com.phinneyridge.java.library"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeJavaLibPlugin"
}
create("PhinneyRidgeJavaKotlinAppPlugin") {
id = "com.phinneyridge.java.kotlin.application"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeJavaKotlinAppPlugin"
}
create("PhinneyRidgeJavaKotlinLibPlugin") {
id = "com.phinneyridge.java.kotlin.library"
implementationClass = "com.phinneyridge.android.gradle.PhinneyRidgeJavaKotlinLibPlugin"
}
create("PhinneyRidgeDSAnnotations") {
id = "com.phinneyridge.dsannotations"
implementationClass = "com.phinneyridge.osgi.DSAnnotations"
}
create("Aar2Jar") {
id = "com.phinneyridge.aar2jar"
implementationClass = "com.phinneyridge.android.Aar2Jar"
}
}
}
group = "com.phinneyridge"
version = "1.0.0"
publishing {
repositories {
maven {
url = uri(System.getenv().get("PhinneyRidgeReleaseRepoUrl").toString())
credentials {
username = System.getenv().get("PhinneyRidgeRepoUser").toString()
password = System.getenv().get("PhinneyRidgeRepoUserPW").toString()
}
}
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
gradleApi();
implementation ("com.android.tools.build:gradle:7.1.3")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20")
}
There's some differences, but the maven repository is constructed exactly the same. So the question is why am I getting the NoSuchAlgorithm error when I try to publish the version catalog?
If I try publishing with stacktrace I see the following:
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.securit
y.ssl.SSLContextImpl$DefaultSSLContext)
at org.gradle.internal.resource.transport.http.HttpClientConfigurer.jdkSupportsTLSProtocol(HttpClientConfigurer.java:115)
And here's what jdkSupportTLSProtocol looks like:
private static boolean jdkSupportsTLSProtocol(#SuppressWarnings("SameParameterValue") final String protocol) {
try {
for (String supportedProtocol : SSLContext.getDefault().getSupportedSSLParameters().getProtocols()) {
if (protocol.equals(supportedProtocol)) {
return true;
}
}
return false;
} catch (NoSuchAlgorithmException e) {
throw UncheckedException.throwAsUncheckedException(e);
}
}
It's the SSLContext.getDefault() that throws the NoSuchAlgorithException. I'm just currently at a lost understand what I need to change to get around this problem.
I figured out a solution to the problem.
I added a line of code to the maven repository declaration:
maven {
javax.net.ssl.SSLContext.setDefault(javax.net.ssl.SSLContext.getInstance("default"))
name = "PhinneyRidgeRepository"
url = uri(System.getenv()["PhinneyRidgeReleaseRepoUrl"].toString())
credentials {
username = System.getenv().get("PhinneyRidgeRepoUser").toString()
password = System.getenv().get("PhinneyRidgeRepoUserPW").toString()
}
println(url)
println(credentials.username + ":" + credentials.password)
}
}
That solved the problem, but I don't have an explanation why I had to set the SSLContext in one situation and not the other. According to the gradle documentation SSLContext.getDefault() is supposeto automagically call SSLContext.getInstance("Default") when the SSLContext is not initialized. (By the way the instance name seems to be case insensitive, so "default" or "Default" both worked.) My speculation is that this is a gradle bug, probably because the publication in one case is from component. That's the only obvious difference that I see that sets the two contrasting situations apart. By the way SSLContext.getInstance("TLSv1.2") would not work; I had to use "default"

How to get publish to wait on AAR file to exist before trying to publish?

Problem Statment
I am trying to create a build and publish a library based on properties I pass in through command line. I would like to use :
./gradlew clean build publish -PnexusUsername=* -PnexusPassword=* -PmajorVersion=x -PminorVersion=x -PbuildNumber=x
Work Around
My current work around for this is I use
./gradlew clean; ./gradlew build; ./gradlew publish -PnexusUsername=* -PnexusPassword=* -PmajorVersion=x -PminorVersion=x -PbuildNumber=x
Below you will find my main build gradle. I have tried many ideas of waiting for assembleRelease to be added and publishing being finalized by it, but alas I am not a gradle expert, so I am asking for help. I have two POJO/POKO libraries and one Android Library that I am publishing out as an AAR. The error I receive is that the POM file cannot be made because the AAR does not exist.
import CiCdDependencies.BOSS_SDK_SNAPSHOT
import CiCdDependencies.buildNumber
import CiCdDependencies.majorVersion
import CiCdDependencies.minorVersion
import CiCdDependencies.nexusPassword
import CiCdDependencies.NEXUS_URL
import CiCdDependencies.nexusUserName
import CiCdDependencies.productVersion
import CiCdDependencies.VERSION_NAME
import Coverage.androidCoverage
import Coverage.testCoverage
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.0.4")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0")
classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3")
}
}
plugins {
id("java")
id("maven-publish")
id("org.sonarqube").version("3.3")
}
ext {
// Major / Minor / Release and Build numbering
productVersion = (project.findProperty("productVersion") ?: (System.getenv("PRODUCT_VERSION")
?: "0")).toString()
majorVersion =
(project.findProperty("majorVersion") ?: (System.getenv("MAJOR_VERSION") ?: "0")).toString()
minorVersion =
(project.findProperty("minorVersion") ?: (System.getenv("MINOR_VERSION") ?: "0")).toString()
buildNumber =
(project.findProperty("buildNumber") ?: (System.getenv("BUILD_NUMBER") ?: "0")).toString()
//for publishing
nexusUserName =
(project.findProperty("nexusUsername") ?: (System.getenv("NEXUS_USERNAME"))).toString()
nexusPassword =
(project.findProperty("nexusPassword") ?: (System.getenv("NEXUS_PASSWORD"))).toString()
testCoverage = project.hasProperty("TEST_COVERAGE")
androidCoverage = project.hasProperty("ANDROID_COVERAGE")
}
description = "MAFIA BOSS SDK (Kotlin)"
allprojects {
apply {
plugin("jacoco")
}
// Read only repositories for dependencies; this should never be used to publish
repositories {
google()
mavenCentral()
maven {
name = "DI2E-BossSdkReleases"
setUrl("$NEXUS_URL$BOSS_SDK_RELEASES")
credentials {
username = nexusUserName
password = nexusPassword
}
}
maven {
name = "DI2E-BossSdkSnapshots"
setUrl("$NEXUS_URL$BOSS_SDK_SNAPSHOT")
credentials {
username = nexusUserName
password = nexusPassword
}
}
}
}
sonarqube {
properties {
val gitBranch = "git rev-parse --abbrev-ref HEAD".runCommand()
property("sonar.sourceEncoding", "UTF-8")
property("sonar.host.url", "https://sonarqube.di2e.net")
property("sonar.projectVersion", gitBranch)
property("sonar.projectKey", "MAFIA-KotlinSDK")
property("sonar.login", "c58feafd2a81797dec0361dd2d8758885e4145d7")
property("sonar.junit.reportPaths", "**/test-results/**/*.xml")
property("sonar.coverage.jacoco.xmlReportPaths", "**/reports/jacoco/jacocoTestReport/jacocoTestReport.xml")
}
}
tasks.getByName("publish").dependsOn("build")
/**
* Publishing configuration
*/
afterEvaluate {
publishing {
logger.lifecycle("Publishing ${VERSION_NAME()}")
publications {
val isSnapshot = !project.hasProperty("RELEASE")
create<MavenPublication>("BOSSSDKJAVA") {
groupId = "BOSS"
artifactId = "SDK-KOTLIN"
version = if (isSnapshot) {
"${VERSION_NAME()}-SNAPSHOT"
} else {
VERSION_NAME()
}
// The interfaces JAR
artifact("${rootProject.projectDir}/InfrastructureBase/build/libs/InfrastructureBase.jar") {
classifier = "InfrastructureBase"
}
// The implementations JAR
artifact("${rootProject.projectDir}/InfrastructureImpl/build/libs/InfrastructureImpl.jar") {
classifier = "InfrastructureImpl"
}
}
create<MavenPublication>("BOSSSDKANDROID") {
groupId = "BOSS"
artifactId = "SDK-ANDROID"
version = if (isSnapshot) {
"${VERSION_NAME()}-SNAPSHOT"
} else {
VERSION_NAME()
}
// The implementations AAR
artifact("${rootProject.projectDir}/InfrastructureAndroidImpl/build/outputs/aar/InfrastructureAndroidImpl-release.aar") {
classifier = "InfrastructureAndroidImpl"
}
}
repositories {
maven {
url = if (isSnapshot) {
logger.lifecycle("Performing snapshot build.")
uri("$NEXUS_URL$BOSS_SDK_SNAPSHOT")
} else {
logger.lifecycle("Performing release build.")
uri("$NEXUS_URL$BOSS_SDK_RELEASES")
}
credentials {
username = nexusUserName
password = nexusPassword
}
}
}
}
}
}
afterEvaluate {
tasks.getByName("jacocoTestReport", type = JacocoReport::class) {
reports {
print("I am reporting" )
xml.required.set(testCoverage)
html.required.set(testCoverage)
}
val fileFilter = mutableSetOf(
"**/R.class",
"**/R\$*.class",
"**/BuildConfig.*",
"**/Manifest*.*",
"**/*Test*.*",
"android/**/*.*",
"**/*\$Lambda$*.*", // Jacoco can not handle several "$" in class name.
"**/*\$inlined$*.*" // Kotlin specific, Jacoco can not handle several "$" in class name.
)
val debugTree = fileTree("${buildDir}/tmp/kotlin-classes/debug") {
exclude(fileFilter)
}
val mainSrc = "${project.projectDir}/src/main/java"
sourceDirectories.from(files(mainSrc))
classDirectories.setFrom(debugTree)
if (androidCoverage) {
executionData.setFrom(fileTree("$buildDir") {
include(
setOf(
"jacoco/*.exec",
"outputs/code-coverage/debugAndroidTest/connected/*coverage.ec",
"outputs/unit_test_code_coverage/*.exec"
)
)
})
} else if (testCoverage) {
executionData.setFrom(fileTree("$buildDir") {
include(
setOf(
"jacoco/*.exec",
"outputs/unit_test_code_coverage/*.exec"
)
)
})
}
configurations.all {
resolutionStrategy {
eachDependency {
if ("org.jacoco" == requested.group) {
useVersion("0.8.7")
}
}
}
}
}
}
tasks.getByName("sonarqube"){
dependsOn(tasks.getByName("jacocoTestReport"))
}
fun String.runCommand(currentWorkingDir: File = file("./")): String {
val byteOut = getByteOutput()
project.exec {
workingDir = currentWorkingDir
commandLine = this#runCommand.split("\\s".toRegex())
standardOutput = byteOut
}
return String(byteOut.toByteArray()).trim()
}```
I believe AGP has done something to make it easier, check it here: https://developer.android.com/studio/build/maven-publish-plugin
release(MavenPublication) {
// Applies the component for the release build variant.
from components.release
// You can then customize attributes of the publication as shown below.
groupId = 'com.example.MyLibrary'
artifactId = 'final'
version = '1.0'
}
The Android Gradle plugin creates a component for each build variant artifact in your app or library module that you can use to customize a publication to a Maven repository.
And you may need to move the android part to that android library's build.gradle(.kts).

React-native - Unable to build after configuring React Native Facebook SDK

I followed the instructions on Facebook and npmjs. I even have tried cd.. android && gradlew clean and the clean failed also. I have restarted my computer several times but to no avail. Please can anyone tell me where I got this wrong? I am building the app on Windows.
The dependencies are:
"react-native": "^0.62.2",
"react-native-fbsdk": "^2.0.0",
java jdk 13
gradle 6.5
This is my MainApplication.java:
package com.mobileapps;
import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.reactnative.androidsdk.FBSDKPackage;
import com.brentvatne.react.ReactVideoPackage;
import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
#Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
#Override
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new FBSDKPackage());
return packages;
}
#Override
protected String getJSMainModuleName() {
return "index";
}
};
#Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
#Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* #param context
* #param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.mobileapps.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Here is my build.gradle at the root of android:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
}
repositories {
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.5.2")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
jcenter()
maven { url 'https://www.jitpack.io' }
mavenCentral()
}
}
Here is build.gradle in android/app:
apply plugin: "com.android.application"
import com.android.build.OutputFile
/**
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"],
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
project.ext.react = [
enableHermes: false, // clean and rebuild if changing
]
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
* This should be set on project.ext.react and mirrored here. If it is not set
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.pouchmoney"
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"
}
}
packagingOptions {
pickFirst "lib/armeabi-v7a/libc++_shared.so"
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/x86/libc++_shared.so"
pickFirst "lib/x86_64/libc++_shared.so"
}
// 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
}
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation 'com.facebook.android:facebook-android-sdk:[5,6)'
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
// 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)
Here is settings.gradle:
rootProject.name = 'mobileApps'
include ':react-native-fbsdk'
project(':react-native-fbsdk').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fbsdk/android')
include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
include ':react-native-config'
project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
apply from: file("../node_modules/#react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
This is the error I get when I run "react-native run-android"
info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
Jetifier found 1242 file(s) to forward-jetify. Using 8 workers...
info Starting JS server...
info Installing the app...
> Configure project :app
Reading env from: .env
> Task :app:compileDebugJavaWithJavac FAILED
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings
131 actionable tasks: 5 executed, 126 up-to-date
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Couldn't delete stale output file
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1m 30s
error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup. Run CLI with --verbose flag for more details.
Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Couldn't delete stale output file
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1m 30s

How create multi site setup in phalcon with some shared controllers , models, views with out duplicating views folder?

I need to setup multisite in phalcon where I need some common functionalities to be done among all sites and also will have site specific. Say it would have some common controllers modals and views, if I need anything to be changed in one particular site I should be able to change in that particular site with out affecting other sites. just by creating single view template and extending the controllers and modals. If i need to change anything in all sites then I could be able to change it in a single place.
multisite/shared
├── apps
│ ├── common
│ │ ├── controllers (Register namespace Common/Controller)
│ │ │ ├── IndexController.php
│ │ │ ├── LoginController.php
│ │ │ └── ProductsController.php
│ │ ├── models (Register namespace Common/Model)
│ │ │ └── Products.php
│ │ └── views
│ │ ├── login
│ │ │ └── index.volt
│ │ └── products
│ │ | └── index.volt
| | └──index.volt
│ ├── example.com
│ │ ├── controllers
│ │ │ ├── IndexController.php (extend Common/Controller)
│ │ │ ├── LoginController.php (extend Common/Controller)
│ │ │ ├── ProductsController.php (extend Common/Controller)
│ │ │ └── UsersController.php Site Specific Controller
│ │ ├── models
│ │ │ └── Products.php (extend Common/Model)
| | | └── Users.php (Site Specific Model)
│ │ └── views
│ │ └── products (Other view templates will refer to Common view folder)
│ │ └── index.volt
│ ├── example2.com
│ │ ├── controllers
│ │ │ ├── IndexController.php (extend Common/Controller)
│ │ │ ├── ProductsController.php (extend Common/Controller)
│ │ │ └── SitespecificController.php Site Specific Controller
│ │ ├── models
│ │ │ └── Products.php (extend Common/Model)
| | | └── SiteSpecific.php (Site Specific Model)
│ │ └── views
│ │ └── sitespecific (Other view templates will refer to Common view folder)
│ │ └── index.volt
└── public
└── example.com (Will contain Js CS Images to support site specific theme)
└── example2.com (Will contain Js CS Images to support site specific theme)
└── index.php
Refer : http://monkpal.com/Multisite-Set-up-with-shared-views-controllers-and-modals-Phalcon
Steps to setup multiple site with different domain name
Steps to acheive it
Step 1 : Register the namespaces of common controllers and models
Step 2 : Extend the phalcon view engine to cascading the view (say for example View engine will look for specific template file in site specific view folder if its not exist it will look in common views folder, there is no need to replicate all the template files in all sites views directories, you can overwrite single template file alone).
Step 3 : Extend Phalcon volt to provide Skin path for templates Step 4: Create site specific Volt cache folder
Step 5 : Create seperate folders with sitenames in public folder for js/css/images Step 6: Create common contollers, views, modals
Step 7: Extend common controllers , modals in site specific folderss , Views wil be taken from common folder. if you want to overwrite any template you can overwiite that alone no need all view folder. Step 8 : Set sitename by current domain name. this sitename will be used to register contollers models directries
Step 9: Set two views directory one is common and another is sitename (thi can be done only if you have extened the phalcon view to add two directories refer step 2) Files extended are here this should be in your public directory.
Files extended are here, this should be in your root directory.
custom/CustomVolt.php
<?php
namespace Custom;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Mvc\View\Engine\Volt\Compiler;
class CustomVolt extends Volt
{
public function getCompiler()
{
if (!$this->_compiler) {
$this->_compiler = new VoltCompilerExtension($this->getView());
$this->_compiler->setOptions($this->getOptions());
$this->_compiler->setDI($this->getDI());
}
return $this->_compiler;
}
}
class VoltCompilerExtension extends Volt\Compiler
{
public function compileFile($path, $compiledPath, $extendsMode = null)
{
$skinPath = $this->getOption('skinPath');
if ($skinPath) {
$skinTemplate = str_replace(
$this->getDI()->getView()->getViewsDir(),
$skinPath,
$path);
if (is_readable($skinTemplate)) {
$path = $skinTemplate;
}
}
return parent::compileFile($path, $compiledPath, $extendsMode);
}
}
custom/CustomView.php
use Phalcon\Mvc\View\Exception;
use Phalcon\Mvc\View;
use Phalcon\Cache\BackendInterface;
class CustomView extends View
{
protected $_viewsDirs;
/**
* #var
*/
protected $_eventsManager;
/**
* #param $path
*
* #return $this
*/
public function addViewsDir($path)
{
$this->_viewsDirs = $path;
$this->setViewsDir($path);
return $this;
}
/**
* #param $view
* #param array $vars
*
* #return string
*/
public function getPartial($view, $vars = [])
{
ob_start();
$this->partial($view, $vars);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
protected function _engineRender($engines, $viewPath, $silence, $mustClean, BackendInterface $cache = NULL)
{
if (is_object($cache)) {
throw new Exception('Cache view not supported...');
return;
}
$viewsDirs = is_array($this->_viewsDirs) ? array_reverse($this->_viewsDirs) : [$this->_viewsDir];
$notExists = true;
$viewEnginePath = null;
foreach ($engines as $extension => $engine) {
foreach ($viewsDirs as $viewsDir) {
$viewsDirPath = $this->_basePath . $viewsDir . $viewPath;
$viewEnginePath = $viewsDirPath . $extension;
if (is_file($viewEnginePath)) {
if (is_object($this->_eventsManager)) {
$this->_activeRenderPath = $viewEnginePath;
if($this->_eventsManager->fire('view:beforeRenderView', $this, $viewEnginePath) === false) {
break;
}
}
$engine->render($viewEnginePath, $this->_viewParams, $mustClean);
if (is_object($this->_eventsManager)) {
$this->_eventsManager->fire('view:afterRenderView', $this);
}
$notExists = false;
break 2;
}
}
}
if ($notExists) {
if (is_object($this->_eventsManager)) {
$this->_activeRenderPath = $viewEnginePath;
$this->_eventsManager->fire('view:notFoundView', $this);
}
if (!$silence) {
$exceptionMessage = 'View "'.($viewPath).'" was not found in the views directories';
throw new Exception($exceptionMessage);
return;
}
}
}
}
public/index.php
<?php
use Phalcon\Loader;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Url as UrlProvider;
use Custom\CustomVolt;
use Custom\CustomView;
if($_SERVER['HTTP_HOST'] == "example.com") {
define('SITENAME',"example.com" );
}
if($_SERVER['HTTP_HOST'] == "example2.com") {
define('SITENAME',"example2.com" );
}
define('APP_PATH', realpath('..') . '/');
try {
$loader = new Loader();
$loader->registerNamespaces(array(
'Common\Controller' => '../app/common/controllers',
'Common\Model' => '../app/common/models',
'Custom' => 'custom'
))->register();
$loader->registerDirs(array(
'../app/'.SITENAME.'/controllers/',
'../app/'.SITENAME.'/models/'
))->register();
$di = new FactoryDefault();
$di->set(
'voltService',
function ($view, $di) {
$volt = new CustomVolt($view, $di);
$volt->setOptions(
array(
"compiledPath" => "../cache/volt/".SITENAME."/",
"compiledExtension" => ".compiled",
'compileAlways' => true,
'skinPath' => '../app/'.SITENAME.'/views/'
)
);
return $volt;
}
);
$di->set(
'view',
function () {
$view = new CustomView();
$view->addViewsDir(array('../app/common/views/','../app/'.SITENAME.'/views/'));
$view->registerEngines(
array(
".volt" => 'voltService'
)
);
return $view;
}
);
$application = new Application($di);
$response = $application->handle();
$response->send();
}
catch (\Exception $e) {
echo "Exception: ", $e->getMessage();
}
To render Js and css site specific in volt tempaltes
You use can like this
{{ stylesheet_link(constant('SITENAME') ~'/css/main.css') }}
{{ javascript_include(constant('SITENAME') ~'/js/main.js') }}

Setting Compiler Level For gradle generated Maven pom

I am using gradle as project dependency manager but since I like netbeans better and can't find a native integration with maven, I copy the default pom generated by gradle as the pom.xml. But How do I set the source and target level?
my build.gradle looks like
apply plugin: 'eclipse'
apply plugin: 'maven'
apply plugin: 'java'
targetCompatibility=1.6
sourceCompatibility=1.6
after I run
gradle install
and check the build/poms/pom-default.xml it never configures the source nor target level which is defaulted to 1.3
what I am lacking is maven compiler plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
and haven't been able to find how to configure that specific part of the pom. I've found all the examples where they configure license, developer stuff and so on but not the plugin specif.
took me a while to figure it out. Like Peter said above you can just add that section. Easier said than done though, at least for me.
Fortunately, spring is using gradle so you have lots of real world examples. check git hub
install {
repositories.mavenInstaller {
customizePom(pom, project)
}
}
def customizePom(pom, gradleProject) {
pom.whenConfigured { generatedPom ->
// respect 'optional' and 'provided' dependencies
gradleProject.optionalDeps.each { dep ->
generatedPom.dependencies.find { it.artifactId == dep.name }?.optional = true
}
gradleProject.providedDeps.each { dep ->
generatedPom.dependencies.find { it.artifactId == dep.name }?.scope = 'provided'
}
// eliminate test-scoped dependencies (no need in maven central poms)
generatedPom.dependencies.removeAll { dep ->
dep.scope == 'test'
}
// add all items necessary for maven central publication
generatedPom.project {
name = gradleProject.description
description = gradleProject.description
organization {
name = 'bajoneando'
}
build {
plugins {
plugin {
groupId = 'org.apache.maven.plugins'
artifactId = 'maven-compiler-plugin'
configuration {
source = '1.6'
target = '1.6'
}
}
plugin {
groupId = 'org.apache.maven.plugins'
artifactId = 'maven-surefire-plugin'
configuration {
includes {
include = '**/*Tests.java'
}
excludes {
exclude = '**/*Abstract*.java'
}
}
}
}
resources {
resource {
directory = 'src/main/java'
includes = ['**/*']
excludes = ['**/*.java']
}
resource {
directory = 'src/main/resources'
includes = ['**/*']
}
}
testResources {
testResource {
directory = 'src/test/java'
includes = ['**/*']
excludes = ['**/*.java']
}
testResource {
directory = 'src/test/resources'
includes = ['**/*']
}
}
}
developers {
developer {
id = 'lnramirez'
name = 'Luis Ramirez Monterosa'
email = '*****#gmail.com'
}
}
}
}
}
You can add that section in the very same way as the examples do it for "license and developer stuff".