Create a directory in Debian file creation task - gradle

I have the following gradle task that I use to create a debian archive:
val packDeb by tasks.registering(Deb::class) {
mkdir("/var/lib/salam/")
}
But I get the following error when I run ./gradlew build
org.gradle.api.UncheckedIOException: Failed to create directory '/var/lib/salam'
What am I doing wrong here?

The mkdir method that you are using is not part of the Deb task (but rather comes from the project object). The method is called at the time your Gradle project is configured, i.e., Gradle tries to create that directory at the time when Gradle starts up. This most likely fails because the user account with which you run Gradle does not have write permissions under /var/lib.
To create that directory when installing the DEB package, you could do something like this:
plugins {
id("nebula.deb") version "6.2.0"
}
import com.netflix.gradle.plugins.deb.Deb
val packDeb by tasks.registering(Deb::class) {
into("/")
// TODO assumes that the (non-empty) "salam" dir is prepared in your
// project dir
from("salam") {
into("var/lib/salam")
}
}

Related

gradle does not create build folder

I have a simple gradle project, created by gradle init
The build.gradle file contains the next content:
plugins {
id 'base'
}
tasks.register('copyFile', Copy) {
from 'desc'
into "$buildDir/desc"
}
running the copyFile or the build task doesn't create a build folder
I can not reproduce the issue you are having, Am using gradle 6.9 , And tested with 7.5
I tried the following :
Having desc folder, With any folder/files inside
calling gradle copyFile
This resulted in success and copyed all the files and folders into /build/desc/
The task will create both build folder + desc folder but it will only work if desc is not empty.
Otherwise, It will not execute any commands as there are no files nor folders in /desc folder
So, Just make sure the /desc is not empty, and call the function with gradle copyFile
If you want to link this task with gradle build , you can add the following line to your code.
tasks.named("build") { finalizedBy("copyFile") }

How can I configure a Gradle plugin externally to the build?

How can I apply a plugin configuration to a Gradle project externally of the build so that it does not get included in Git source control?
Details
I have a Gradle project which uses the gradle-git-properties plugin to generate a git.properties file based on the project's Git details.
plugins {
id 'java'
id 'com.gorylenko.gradle-git-properties'
}
// Rest of build.gradle goes here
Additionally, I'm checking out my project to multiple locations locally using git working trees. However, projects using gradle-git-properties fail when run from a linked working tree, per gradle-git-properties#14.
$ ./gradlew generateGitProperties
> Task :subproject:generateGitProperties FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':subproject:generateGitProperties'.
> Error while evaluating property 'generatedProperties' of task ':subproject:generateGitProperties'
> gradlegitproperties.org.eclipse.jgit.errors.RepositoryNotFoundException: repository not found: /Users/Me/my-project/.git/worktrees/my-project
I have been using a plugin configuration to work around the issue, allowing the project to build successfully when run from the linked working tree:
gitProperties {
Path dotGitPath = rootProject.layout.projectDirectory.asFile.toPath().resolve(".git")
if (Files.isRegularFile(dotGitPath)) {
Files.lines(dotGitPath).withCloseable { ditGitFileLines ->
dotGitDirectory = ditGitFileLines
.filter { it.startsWith("gitdir: ") }
.map { it.substring('gitdir: '.length(), it.lastIndexOf('/.git/')) }
.map { project.objects.directoryProperty().convention(project.layout.projectDirectory.dir(it)) }
.findFirst()
.orElse(project.objects.directoryProperty().convention(project.layout.projectDirectory.dir(".git")))
}
}
}
The problem with this solution is that it requires modifying the build file. This is a shared repository, and I'm the only person accessing it who uses multiple git working trees. Therefore, I don't want to include this workaround in the build itself.
Is there a way I can automatically apply this plugin configuration externally to the build file or any other file that would be committed with the project?
A Gradle initialization script can be used, putting the plugin configuration into an external file.
There are several ways to use an init script:
Specify a file on the command line. The command line option is -I or --init-script followed by the path to the script. […]
Put a file called init.gradle (or init.gradle.kts for Kotlin) in the USER_HOME/.gradle/ directory.
Put a file that ends with .gradle (or .init.gradle.kts for Kotlin) in the USER_HOME/.gradle/init.d/ directory.
Put a file that ends with .gradle (or .init.gradle.kts for Kotlin) in the GRADLE_HOME/init.d/ directory, in the Gradle distribution. […]
~/.gradle/init.d/git-worktree-fix.gradle
import java.nio.file.Files
import java.nio.file.Path
allprojects {
plugins.withId('com.gorylenko.gradle-git-properties') {
gitProperties {
Path dotGitPath = rootProject.layout.projectDirectory.asFile.toPath().resolve(".git")
if (Files.isRegularFile(dotGitPath)) {
Files.lines(dotGitPath).withCloseable { ditGitFileLines ->
dotGitDirectory = ditGitFileLines
.filter { it.startsWith("gitdir: ") }
.map { it.substring('gitdir: '.length(), it.lastIndexOf('/.git/')) }
.map { project.objects.directoryProperty().convention(project.layout.projectDirectory.dir(it)) }
.findFirst()
.orElse(project.objects.directoryProperty().convention(project.layout.projectDirectory.dir(".git")))
}
}
}
}
}
The gitProperties configuration is wrapped in a plugins.withId('com.gorylenko.gradle-git-properties') check, since otherwise projects not using the gradle-git-properties plugin would fail when using this script.

Run go command as a gradle task

I am using gradle as the build tool for a terraform project. I do have unit tests written in go for the project under the ..test/... folder . The way I am running test locally is just on the commandline go test ..test/..' which will run all tests under the test folder. I want to integrate this in the build , so that every build will run this command 'go test ..test/..', How do I achieve this in gradle. Can a custom task be utilized to run a go command?
I am trying to do something like the following
task testExec(type: Exec) {
workingDir "${buildDir}/test"
commandLine 'go','test'
} doLast {
println "Test Executed!"
}
But I get the error
> A problem occurred starting process 'command 'go''
For what its worth , I tried other commands and get the same erorr for ex
task testExec(type: Exec) {
workingDir "${buildDir}/test"
commandLine 'echo','${}buildDir'
} doLast {
println "Test Executed!"
}
gives similar error
> A problem occurred starting process 'command 'echo''
You can use the gradle plugin. First you can follow the starting guide and add the plugin:
plugins {
id 'com.github.blindpirate.gogradle' version '0.11.4'
}
golang {
packagePath = 'github.com/your/package' // go import path of project to be built, NOT local file system path!
}
Then you can run the following command to execute all go files that follow the file name convention <name>_test.go:
gradlew goTest
Otherwise you can also create a complete custom task or a custom task with the plugin.
EDIT:
I found the cause of your error. The variable buildDir refers to the build folder in your project: <project_folder>/build. The problem now is that the folder test does not exists and the exception is thrown. Instead, you can use the variable projectDir.

Create a second installDist task?

During development I am using a standard-function installDist (from the application plugin) in build.gradle:
installDist{}
... but I now want to have another task which installs/distributes/deploys a "production" version to the production location, which also incorporates the version into the directory structure. I tried this:
task deployOperativeVersion( type: installDist ) {
destinationDir = file( "$productionDir/$version" )
}
Build failure output:
Build file '/home/mike/IdeaProjects/JavaFXExp2/Organiser/build.gradle' line: 98
* What went wrong:
A problem occurred evaluating root project 'Organiser'.
> class org.gradle.api.tasks.Sync_Decorated cannot be cast to class java.lang.Class
(org.gradle.api.tasks.Sync_Decorated is in unnamed module of loader org.gradle.
internal.classloader.VisitableURLClassLoader #aec6354; java.lang.Class is in module
java.base of loader 'bootstrap')
It appears that installDist is not a "type" as in Test.
How can I achieve this? Incidentally I would be really keen on having two separate tasks: to get installDist to run I've found that you only have to type ./gradlew inst ... with a task called deployXXX it would be sufficient to type ./gradlew depl.
I also tried this:
task deployOperativeVersion{
installDist{
destinationDir = file( "$operativeDir/$version" )
}
}
... which doesn't seem to have done anything. Nor this:
task deployOperativeVersion{
doFirst {
installDist {
destinationDir = file("$operativeDir/$version")
}
}
}
A bit later I thought I had indeed found the answer:
task deployOperativeVersion{
dependsOn installDist{ destinationDir=file("$productionDir/$version")
}
... but to my amazement (will I ever get to a reasonable understanding of Gradle before Hell freezes over?), including this actually appears to influence the "routine" installDist task: specifically, it stops the latter from operating normally, and means that even when I run installDist the deployment/distribution/installation still goes to productionDir/version, rather than the default location.
So then I wondered about two tasks both of which are dependent on installDist:
task deployOperativeVersion{
dependsOn installDist{ destinationDir=file("$productionDir/$version") }
}
task stdInstall{
dependsOn installDist{ destinationDir=file("build/install") }
}
... haha, no joy: I run one and it deploys OK. I then run the other... and get an error:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':installDist'.
> The specified installation directory '/home/mike/IdeaProjects/JavaFXExp2/Organiser/build/install' is neither empty nor does it contain an installation for 'Organiser'.
If you really want to install to this directory, delete it and run the install task again.
Alternatively, choose a different installation directory.
... needless to say, this is NOT the case: under ...Organiser/build/install there is one directory only, Organiser, with /bin and /lib directories under it.
Your task should be declared as a Sync task, which is the actual type of the installDist task. The application plugin is using the distribution plugin. You can grab the content configuration from the main distribution, which is the source, or from the installDist task.
task deployOperativeVersion(type: Sync) {
destinationDir = file("${productionDir}/${version}")
with distributions.main.content
}
or
task deployOperativeVersion(type: Sync) {
destinationDir = file("${productionDir}/${version}")
with installDist
}

Gradle - Error Copying Files To Project Root

I’m getting the following error whenever I attempt to use a Copy task to copy a file into the root of a project (the same folder I’m running gradle from):
Failed to create MD5 hash for file content.
I thought this was related to the artifacts I was pulling from Artifactory, but that seems to be unrelated. I was able to get the same results with a minimal script.
Is there something obviously wrong with what I’m doing, or does Gradle intentionally disallow such things?
task fails(type:Copy) {
from 'build/someFile.txt'
into new File('.').absolutePath
}
task works(type:Copy) {
from 'build/someFile.txt'
into new File('.').absolutePath + '/output'
}
Short Answer: Don't copy into the project directory, you are best to use into "$buildDir/someFolder" so that the folder is isolated to this single task, and also so that it will be cleaned by gradle clean
Long Answer: At it's core, Gradle has the concept of an "UP-TO-DATE" check for every single task. If Gradle sees that nothing has changed since last time a task was executed it will use the old result instead of executing again.
UP-TO-DATE checking is implemented by taking a "hash" of the task inputs and task outputs. Since you are using into '.' that means that the entire contents of the project directory is considered a task output (bad)
Gradle uses the .gradle folder for temp files (eg task hashes) It's likely some of these files are locked for writing as Gradle is trying to also read the same files (to calculate the "hash" of the task outputs) causing the error you are seeing
* EDIT *
If you need to copy into the project directory for legacy reasons, you might use Project.copy(...) directly instead of a Copy task. You could manually manage the task inputs/outputs in this case
Eg
task customCopy {
inputs.file "$buildDir/someFile.txt"
outputs.file 'someFile.txt'
doLast {
copy {
from "$buildDir/someFile.txt"
into '.'
}
}
}
Can you believe it, the following works
task myCopy(type: Copy) {
from "$rootDir/app1/src/main/resources/db"
into "$rootDir/app2/src/test/resources/db"
}
test.dependsOn myCopy
and the following doesn't 🤦
task myCopy(type: Copy) {
from '$rootDir/app1/src/main/resources'
into '$rootDir/app2/src/test/resources'
}
test.dependsOn myCopy

Resources