Add a single file to gradle resources - resources

I'm using the config var plugin for heroku (see https://devcenter.heroku.com/articles/config-vars).
It allows me to use a .env file which I do not push to source control to define the heroku environment.
So when I'm on heroku, I can access sensible information via System.properties.
In dev, I would like to read from this file so it would be best if it were on my classpath.
The .env file is at the root of my project so I cannot use something like this :
sourceSets {
main {
resources {
srcDirs = ['src/main/resources', '/']
}
}
}
What is the simplest way to include a single file into gradle resources ?

The earlier answers seemed more complicated than I was hoping for, so I asked on the gradle forums and got a reply from a Sterling Green who's one of the gradle core devs.
He suggested configuring processResources directly
processResources {
from(".env")
}
He also mentioned that it might be a bad idea to include the project root as an input directly.

After merging the previous answer here with another tips from other sites, I came up with the following solution:
sourceSets {
specRes {
resources {
srcDir 'extra-dir'
include 'extrafiles/or-just-one-file.*'
}
}
main.resources {
srcDir 'src/standard/resources'
srcDir specRes.resources
}
}
processResources {
rename 'some.file', 'META-INF/possible-way-to-rename.txt'
}
I still wonder whether there is some better way.

What I ended up doing was to add project root directory as a resource folder including only the file I was interested in :
sourceSets.main.resources { srcDir file('.') include '.env' }
Seems to do the trick. I wonder if it's the best solution thought

Related

Gradle extra property does not exist - defined in sub-module

I'm migrating maven build to gradle and I'm struggling with defining basic plugin configuration in the root project. And providing specific configuration properties in sub-module.
Here is an example:
root: build.gradle
configure(filterSubprojects(['component'])) {
apply plugin: "org.flywaydb.flyway"
flyway {
url = "jdbc:oracle:thin:#${db.host}:${db.port}:${db.name}"
user = db.owner.name
password = db.owner.password
}
}
specific-subproject-component: build.gradle
ext {
db = [
host : <host>,
port : <port>,
name : <name>,
user : [name: <user-name>, password: <user-password>]
]
}
I'm getting this error:
Cannot get property 'db' on extra properties extension as it does not exist
Probably very basic question, but I can't figure out how to do this.
The problem here is, that the specifics component build.gradle file was not yet evaluated when your root build.gradle file is evaluated, so db does indeed not yet exist when the configure block runs. To fix this you should be able to declare evaluationDependsOnChildren() in your root build.gradle file.

Gradle Sync task, sync into folder but ignore specified directories in destination

I want to synchronize a folder on my drive with another folder that contains a folder named 'logs' that i want to keep. confused? here's a diagram:
C:\
|-- mydir/ # sync this folder
| `-- someotherfiles.txt
`-- anotherDir/ # into this folder
|-- logs/ # but if this exists, leave it there
`-- someotherfiles.txt
Is this possible using the sync task? I can't seem to configure it properly, my latest attempt might allude you to my scenario so here it is (not working):
task syncDevDeployFolder(type: Sync, group: 'dev') {
from currentDeliverablesDir
destinationDir = file(project.properties['dev.deployment.dir'])
into (project.properties['dev.deployment.dir']) {
exclude "logs"
}
}
At the time of writing, the current version of Gradle is 3.3 and since version 3.1 there is an incubating feature called 'preserve' which can be used to achieve what you want:
See the example from the documentation:
// You can preserve output that already exists in the
// destination directory. Files matching the preserve
// filter will not be deleted.
task sync(type: Sync) {
from 'source'
into 'dest'
preserve {
include 'extraDir/**'
include 'dir1/**'
exclude 'dir1/extra.txt'
}
}
So in your case you could specify it like this:
preserve {
include 'logs/**'
}
Is this possible using the sync task?
No, the Sync task doesn't currently support this.
You can fallback to ant's sync task. ant object is available to all gradle build scripts anyways
task antSync << {
ant.sync(todir:"dest/"){
ant.fileset(dir: "source/")
ant.preserveintarget(includes: "logs/")
}
}

Copy and .# in file name

I faced with one gradle issue (or may be groovy related)
When I trying to copy file with .# in its name nothing is happened.
Example:
task c(type: Copy) {
from (".#webclasspath#")
into "destdir"
}
Please, could you provide way how to process such files?
seems that there is a bug in gradle, ant works just fine
task c_ant << {
ant.copy(file : '.#webclasspath#', todir : 'destdir')
}

How to use uploadConfigurationName and buildConfigurationName

In gradle documentation we can read:
For each configuration in your project, Gradle provides the tasks uploadConfigurationName and buildConfigurationName [18].
As I understand I can create build which looks like this (without any plugin because I don't want to use plugins in this project):
configurations {
productSrc
}
// create zip file which will be published
buildProductSrc(type: Copy) << {
// do the job
}
// publish zip which were build by buildProductSrc
uploadProductSrc {
repositories {
ivy {
url "http://ivy.repo/repo"
}
}
}
So if I run gradle buildProductSrc uploadProductSrc it will build zip and piblish it on ivy repository. Do I understand it correctly becouse it doesn't work?
[UPDATE]
According to Peter Niederwieser answer this is a working version of build:
apply plugin: 'base'
configurations {
productSrc
}
// create zip file which will be published
buildProductSrc << { // unable to create specific task, for example 'type: Copy'
// do the job
}
// publish zip which were build by buildProductSrc
uploadProductSrc {
repositories {
ivy {
url "http://ivy.repo/repo"
}
}
}
To get uploadConfigurationName and buildConfigurationName tasks, you'll have to apply the base plugin, or a plugin that in turn applies the base plugin (java, groovy, etc.). Alternatively, you can declare and configure such tasks yourself (but it takes more effort).

How can I create a pathing jar in Gradle

When running groovyc in a Windows env, I am running into issues due to the length of the classpath, in my situation. I would like to work around this by creating a pathing jar, and then put that jar on the cp. How can I create a pathing jar w/ all of the classpath entries specified automatically in gradle and then add that jar to the cp?
Here is a tested solution:
task pathingJar(type: Jar) {
appendix = "pathing"
doFirst {
manifest {
attributes "Class-Path": configurations.compile.files.join(" ")
}
}
}
compileGroovy {
dependsOn(pathingJar)
classpath = files(pathingJar.archivePath)
}
Depending on your exact requirements, you might have to tweak this a bit. For example, if you have tests written in Groovy, you will also need a pathing Jar for the test compile class path. In this case you'll need to repeat above configuration as follows:
task testPathingJar(type: Jar) {
appendix = "testPathing"
doFirst {
manifest {
attributes "Class-Path": configurations.testCompile.files.join(" ")
}
}
}
compileTestGroovy {
dependsOn(testPathingJar)
classpath = files(testPathingJar.archivePath)
}
I finally got the "pathing jar" idea to work. I consider this to be a permanent workaround. This could be considered a solution if it is made part of gradle itself.
The original pathing jar code was provided by Peter, but it didn't work. The problem: classpath elements referenced in the pathing jar must be relative to the location of the pathing jar. So, this appears to work for me.
task pathingJar(type: Jar , dependsOn: 'cleanPathingJar') {
/**
* If the gradle_user_home env var has been set to
* C:\ on a Win7 machine, we may not have permission to write the jar to
* this directory, so we will write it to the caches subdir instead.
* This assumes a caches subdir containing the jars
* will always exist.
*/
gradleUserHome = new File(gradle.getGradleUserHomeDir(), "caches")
relativeClasspathEntries = configurations.compile.files.collect {
new File(gradleUserHome.getAbsolutePath()).toURI().
relativize(new File(it.getAbsolutePath()).toURI()).getPath()
}
appendix = "pathing"
destinationDir = gradleUserHome
doFirst {
manifest {
attributes "Class-Path": relativeClasspathEntries.join(" ")
}
}
}
compileGroovy {
dependsOn(pathingJar)
classpath = files(pathingJar.archivePath)
}
This is what helped me:
"The filename or extension is too long error" using gradle
In other words: use the com.github.ManifestClasspath plugin.
The other solutions did not work for me because the actual project main class ended up no being included in the classpath at execution time.

Resources