I have beow tasks in my build.gradle and just wanted to findout whether I can print the app logs while running test task.
The problem with below code is, need to quit from bootRunStartDaemon to go on to next task. So in that case cannot see app logs anymore.
def process;
tasks.register('bootRunStartDaemon') {
doLast {
ProcessBuilder builder = new ProcessBuilder(gradleCommand, "bootRun", "--args='--spring.profiles.active=it'")
builder.redirectErrorStream(true)
builder.directory(projectDir)
process = builder.start()
InputStream stdout = process.getInputStream()
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))
while ((line = reader.readLine()) != null) {
println line
}
}
}
tasks.register('bootRunStopDaemon') {
doLast {
process.destroy();
process.waitFor();
if (process.isAlive()) {
process.destroyForcibly();
}
}
}
task healthCheck(dependsOn: bootRunStartDaemon) {
// some code
}
tasks.register('integrationTest', Test ) {
description = 'Run integration tests.'
check.dependsOn integrationTest
group = 'verification'
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
tasks.withType(Test) {
useJUnitPlatform()
// Prints any test outcomes to the console
testLogging {
events "passed", "skipped", "failed"
showStackTraces true
showExceptions true
showCauses true
exceptionFormat "full"
}
}
bootRunStopDaemon.dependsOn(bootRunStartDaemon)
healthCheck.dependsOn(bootRunStartDaemon)
integrationTest.dependsOn(healthCheck)
integrationTest.finalizedBy aggregate, bootRunStopDaemon
Related
I have a kotlin multiplatform project that I am trying to publish to my Jetbrains Space maven repo. It successfully publishes to the repo but the name of the artifact is the name of my module in the project which is not the name as what the project is called.
example the published artifact is
com.tycz:sharedmodule-android:0.2.0
but I want it to be something like
com.tycz:myLibrary-android:0.2.0
I am using these doc's as reference
This is my build.gradle
plugins {
kotlin("multiplatform")
id("com.android.library")
id("kotlin-android-extensions")
id("kotlinx-serialization")
id("maven-publish")
}
repositories {
gradlePluginPortal()
google()
jcenter()
mavenCentral()
}
group = "com.tycz"
version = "0.2.0"
kotlin {
android{
publishLibraryVariants("release")
}
ios {
binaries {
framework {
baseName = "sharedmodule"
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:1.4.1")
implementation("io.ktor:ktor-client-json:1.4.1")
implementation("io.ktor:ktor-client-serialization:1.4.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("androidx.core:core-ktx:1.3.2")
implementation("io.ktor:ktor-client-android:1.4.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.12")
}
}
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:1.4.1")
}
}
val iosTest by getting
}
}
android {
compileSdkVersion(30)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
packagingOptions {
excludes.add("META-INF/*.kotlin_module")
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
afterEvaluate {
publishing {
repositories {
maven {
url = uri("https://maven.pkg.jetbrains.space/tyczj/p/vqi18/tweedle")
credentials {
username = "$username"
password = "$password"
}
}
}
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework =
kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>(
targetName
).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
How can I change the name of the artifact?
As far as I can see, maven-publish plugin derives artifactId from the Project's name attribute(link), so to change the artifact's name I would recommend setting the appropriate name at your module's settings.gradle.kts like that:
rootProject.name = 'myLibrary'
to change the module name will solve your question
before
include(":android", ":desktop", ":common")
after
include(":android", ":desktop", ":youlib")
I currently have a gradle build script for a KMM multiplatform library that looks like below. I'm trying to use JaCoCo to report the test results and code coverage. I can see somewhere the test results in HTML, but I don't get to see the XML reports for test results and code coverage generated anywhere. How can I change this gradle file so that I can get the XML reports generated?
I'm using ./gradlew testCoverage
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization") version "1.4.10"
id("com.android.library")
id("kotlin-android-extensions")
jacoco
}
group = "xxx"
version = "1.0-SNAPSHOT"
repositories {
gradlePluginPortal()
google()
jcenter()
mavenCentral()
}
val coroutinesVersion = "1.3.9-native-mt"
val ktorVersion = "1.4.0"
kotlin {
android()
ios {
}
sourceSets {
val commonMain by getting {
dependencies {
// ...
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
}
}
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.2.0")
implementation("io.ktor:ktor-client-android:$ktorVersion")
}
}
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktorVersion")
}
val targetName = System.getenv("TARGET_NAME") ?: ""
if (targetName.endsWith("xxx")){
kotlin.srcDirs("src/prod/kotlin")
} else {
kotlin.srcDirs("src/dev/kotlin")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
api("io.ktor:ktor-client-mock:$ktorVersion")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.12")
}
}
}
}
android {
compileSdkVersion(29)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
flavorDimensions("environment")
productFlavors {
create("dev") {
dimension = "environment"
}
create("prod") {
dimension = "environment"
}
}
}
jacoco {
toolVersion = "0.8.5"
}
val jacocoTestReport by tasks.creating(JacocoReport::class.java) {
reports {
xml.isEnabled = true
csv.isEnabled = false
html.isEnabled = false
}
}
val jacocoTestCoverageVerification by tasks.creating(JacocoCoverageVerification::class.java) {
dependsOn(jacocoTestReport)
violationRules {
rule {
limit {
minimum = "0.8".toBigDecimal()
}
}
}
}
val testCoverage by tasks.registering {
group = "verification"
description = "Runs the unit tests with coverage."
dependsOn("test", jacocoTestReport, jacocoTestCoverageVerification)
tasks["jacocoTestReport"].mustRunAfter("test")
tasks["jacocoTestCoverageVerification"].mustRunAfter("jacocoTestReport")
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION")?.toUpperCase() ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework = kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
PS.: I intentionally masked some strings in the code that are sensitive.
I had a similar issue and solved it by specifying the source directories and execution data. You might need to change these values according to your project.
sourceDirectories.setFrom(files(project.projectDir))
executionData.setFrom(
fileTree(project.projectDir) {
setIncludes(setOf("**/**/*.exec", "**/**/*.ec"))
}
)
I'm trying to migrate from groovy to gradle-kotlin dsl, but I'm new to it, so I dont know how to configure Jfrog Artifactory. Please help me with converting that part of code to gradle-kotlin dsl:
task sourceJar(type: Jar) {
from sourceSets.main.allJava
}
artifactory {
contextUrl = "http://10.0.0.49:8081/artifactory"
publish {
repository {
repoKey = 'gradle-dev-local'
username = artifactory_username
password = artifactory_password
}
defaults {
publications('mavenJava')
publishArtifacts = true
publishPom = true
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
groupId = "ua.tiras.oloader"
artifactId = 'core'
version = "1.0.62"
artifact("$buildDir/libs/${project.getName()}.jar")
artifact sourceJar {
classifier "sources"
}
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.api.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
}
I solved it this way:
val sourcesJar by tasks.creating(Jar::class) {
dependsOn(JavaPlugin.CLASSES_TASK_NAME)
classifier = "sources"
from(sourceSets["main"].allSource)
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
groupId = "ua.tiras"
artifactId = "aloader-core"
version = "0.0.4"
artifact(sourcesJar)
artifact("$buildDir/libs/${project.name}.jar")
pom {
withXml {
asNode().appendNode("dependencies").let {
for (dependency in configurations["api"].dependencies) {
it.appendNode("dependency").apply {
appendNode("groupId", dependency.group)
appendNode("artifactId", dependency.name)
appendNode("version", dependency.version)
}
}
}
}
}
}
}
}
artifactory {
setContextUrl("http://dev.tirascloud.com:8081/artifactory")
publish(delegateClosureOf<PublisherConfig> {
repository(delegateClosureOf<GroovyObject> {
setProperty("repoKey", "gradle-dev-local")
setProperty("username", project.findProperty("artifactory_username") ?: "nouser")
setProperty("password", project.findProperty("artifactory_password") ?: "nopass")
})
defaults(delegateClosureOf<GroovyObject> {
invokeMethod("publications", "mavenJava")
setProperty("publishPom", true)
setProperty("publishArtifacts", true)
})
})
resolve(delegateClosureOf<ResolverConfig> {
setProperty("repoKey", "repo")
})
I found another example - an official one JFrog:
https://github.com/jfrog/project-examples/blob/master/gradle-examples/gradle-kts-example-publish/build.gradle.kts
import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.jfrog.buildinfo", "build-info-extractor-gradle", "4.+")
}
configurations.classpath {
resolutionStrategy {
cacheDynamicVersionsFor(0, "seconds")
cacheChangingModulesFor(0, "seconds")
}
}
}
plugins {
java
`maven-publish`
}
fun javaProjects() = subprojects.filter {
File(it.projectDir, "src").isDirectory
}
val currentVersion: String by project
allprojects {
apply(plugin = "com.jfrog.artifactory")
group = "org.jfrog.test.gradle.publish"
version = currentVersion
status = "Integration"
repositories {
maven("http://127.0.0.1:8081/artifactory/libs-release")
}
}
tasks.named<ArtifactoryTask>("artifactoryPublish") {
skip = true
}
project("services") {
tasks.named<ArtifactoryTask>("artifactoryPublish") {
skip = true
}
}
configure(javaProjects()) {
apply(plugin = "java")
apply(plugin = "maven-publish")
dependencies {
testImplementation("junit:junit:4.7")
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("mavenJava") {
from(components.getByName("java"))
artifact(file("$rootDir/gradle.properties"))
}
}
}
}
project("api") {
apply(plugin = "ivy-publish")
configure<PublishingExtension> {
publications {
register<IvyPublication>("ivyJava") {
from(components.getByName("java"))
artifact(file("$rootDir/settings.gradle.kts")) {
name = "gradle-settings"
extension = "txt"
type = "text"
}
// The config below will add a extra attribute to the ivy.xml
// See http://ant.apache.org/ivy/history/latest-milestone/concept.html#extra
descriptor.withXml {
val info = asNode().get("info") as groovy.util.NodeList
val first = info.first() as groovy.util.Node
first.attributes()["e:architecture"] = "amd64"
}
}
}
}
tasks.named<ArtifactoryTask>("artifactoryPublish") {
publications(publishing.publications["ivyJava"])
}
}
configure<org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention> {
clientConfig.isIncludeEnvVars = true
setContextUrl("http://127.0.0.1:8081/artifactory")
publish {
repository {
setRepoKey("libs-snapshot-local") // The Artifactory repository key to publish to
setUsername(findProperty("artifactory_user")) // The publisher user name
setPassword(findProperty("artifactory_password")) // The publisher password
// This is an optional section for configuring Ivy publication (when publishIvy = true).
ivy {
setIvyLayout("[organization]/[module]/ivy-[revision].xml")
setArtifactLayout("[organization]/[module]/[revision]/[module]-[revision](-[classifier]).[ext]")
setMavenCompatible(true) // Convert any dots in an [organization] layout value to path separators, similar to Maven"s groupId-to-path conversion. True if not specified
}
}
defaults {
// Reference to Gradle publications defined in the build script.
// This is how we tell the Artifactory Plugin which artifacts should be
// published to Artifactory.
publications("mavenJava")
setPublishArtifacts(true)
// Properties to be attached to the published artifacts.
setProperties(mapOf(
"qa.level" to "basic",
"dev.team" to "core"
))
setPublishPom(true) // Publish generated POM files to Artifactory (true by default)
setPublishIvy(true) // Publish generated Ivy descriptor files to Artifactory (true by default)
}
}
}
The accepted answer didn't work for me with the artifactory plugin version 4.27.1. A good place to check is definitely the already mentioned provided example by JFrog. Here is a simplified extract based on the offical example:
configure<org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention> {
clientConfig.isIncludeEnvVars = true
setContextUrl(findProperty("artifactory_url"))
publish {
repository {
setRepoKey(repoKeyValue) // The Artifactory repository key to publish to
setUsername(findProperty("artifactory_user")) // The publisher user name
setPassword(findProperty("artifactory_password")) // The publisher password
setMavenCompatible(true)
}
defaults {
publications("mypublicationreference")
setPublishArtifacts(true)
}
}
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("mypublicationreference") {
from(components.getByName("java"))
artifact("$buildDir/libs/${project.name}.jar")
}
}
}
Note that the referenced properties such as artifactory_url can be defined in a gradle.properties file.
I am facing some issues with the gradle plugin to deploy/publish the jar which is generated by swagger-codegen plugin.
I already looked at this question and my needs are completely different but it is acting like this. It is deploying the jar generated by the spring-boot application instead of the codegen one.
This is my task to generate the source folder:
import io.swagger.codegen.config.CodegenConfigurator
import io.swagger.codegen.DefaultGenerator
def swaggerSourceFile = "${project.rootDir}/build/generated/swagger-json/swagger.json"
def swaggerTargetFolder = 'build/generated/java/src/main/java'
task generateApi {
inputs.file("$swaggerSourceFile")
outputs.dir("$projectDir/$swaggerTargetFolder")
doLast {
def config = new CodegenConfigurator()
config.setInputSpec("$swaggerSourceFile")
config.setOutputDir("$projectDir/$swaggerTargetFolder")
config.setLang('java')
config.setAdditionalProperties([
'apiPackage' : 'com.xyz.abc.testmanager.controller',
'modelPackage' : 'com.xyz.abc.testmanager.model',
'sourceFolder' : swaggerTargetFolder,
'groupId' : 'com.xyz.abc',
"artifactId" : 'testmanager',
'pom.version' : '1.0.' + System.getenv('BUILD_NUMBER')
])
new DefaultGenerator().opts(config.toClientOptInput()).generate()
}
}
clean.doFirst {
delete(swaggerTargetFolder)
}
configurations {
generatedCompile
}
sourceSets {
generated {
compileClasspath = configurations.generatedCompile
java {
srcDir file("${project.buildDir.path}/swagger/src/main/java")
}
}
main {
compileClasspath += generated.output
runtimeClasspath += generated.output
}
test {
compileClasspath += generated.output
runtimeClasspath += generated.output
}
}
The upload task is:
def ifJenkins = System.getenv('BUILD_NUMBER') != null ? true : false
uploadArchives {
repositories {
mavenDeployer {
if(ifJenkins){
repository(url: "http://maven.cloud.test:8081/nexus/content/repositories/releases/") {
authentication(userName: System.getenv('MAVEN_CREDS'), password: System.getenv('MAVEN_CREDS_PASSWORD'))
}
}
else
{
repository(url: "http://maven.cloud.test:8081/nexus/content/repositories/releases/") {
authentication(userName: 'test', password: 'test')
}
}
if(ifJenkins){
pom.version = "1.0." + System.getenv('BUILD_NUMBER')
pom.groupId = "com.xyz.abc"
} else{
pom.version = "0.0." + System.currentTimeMillis()
pom.groupId = "com.xyz.abc"
}
pom.artifactId = jar.baseName
pom.packaging = "jar"
pom.name = "Test Manager Client"
}
}
}
I am stuck here as I am not sure whether the problem is with the task or something else.
How do I make sure that my pom.xml generated by swagger-codegen is actually generating the jar and upload the same jar to maven?
I'm leaking jRuby processes, and I don't know how to stop this. I need the groovy script to keep going after launching jRuby, and I need jRuby to die when the main script dies.
test.groovy, loop.rb
loop.rb
while( true )
puts 'Hello from jRuby'
sleep 1
end
test.groovy
def command = "jruby ./loop.rb"
Thread.start {
Process process
try {
process = command.execute()
}
catch (IOException e) {
e.printStackTrace()
return
}
Runtime.runtime.addShutdownHook {
println "Attempting to stop process"
process.destroy()
}
process.consumeProcessOutput(System.out, System.err)
process.waitFor()
}
while( true ){ println 'Hello from groovy'; Thread.sleep(1000) }
Execute
groovy test.groovy
How do I make sure that the external javaw process I create with jRuby is killed? Even though sending Cntrl+C to the running application kills the running groovy process, the jRuby process sticks around. Help?
This should do the trick, but it's ugly:
The basic solution is to look at the output of jps -lm and kill the appropriate process from the PIDs listed there.
new JavaProcessKiller().killAll('loop.rb')
class JavaProcessKiller {
public void killAll(String processPattern) {
getRunningJavaProcesses().each { String processLine ->
if (processLine.contains(processPattern)) {
String pidToKill = getPidFromProcessLine(processLine)
killPid(pidToKill)
}
}
}
protected String[] getRunningJavaProcesses() {
def output = new ByteArrayOutputStream()
def p = ['jps', '-lm'].execute()
p.consumeProcessOutput(new PrintStream(output), System.err)
p.waitFor()
return output.toString().split("\\n")
}
protected String getPidFromProcessLine(String line) {
def pidPattern = /^(\d+).*$/
def matcher = (line =~ pidPattern)
return matcher[0][1]
}
protected void killPid(String pid) {
def killCommands = [
['taskkill', '/F', '/PID', pid],
['kill', pid]
]
boolean processKilledSuccessfully = false
killCommands.each { command ->
if (!processKilledSuccessfully) {
try {
def output = new ByteArrayOutputStream()
def error = new ByteArrayOutputStream()
def process = command.execute()
process.consumeProcessOutput(new PrintStream(output), new PrintStream(error))
process.waitFor()
processKilledSuccessfully = true
}
catch (Exception e) {
}
}
}
}
}