Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the most appropriate way to reuse the Exec task in gradle for common command line operations?

Tags:

plugins

gradle

I'm writing a gradle build file that will install a basic development domain for our product. Essentially all of the real code is going to be in custom plugins and custom tasks. Several of the steps involved are fairly repetitive (multiple sudo calls, multiple user adds) and I would like to encapsulate the common stuff into a task.

For example:

task('addDBUser', type:AddUser) {
    username = joeUser
}

task('startService', type:SudoExec) {
    workingDir = "not/too/relevant"
    commandLine = "/etc/init.d/coolService start"
}

I'd like to reuse the various functionality that Exec gets me (stdin, stdout, etc.) as tidily as possible, while supplying the boilerplate ("sudo ...") automatically. I'm pretty sure I can just extend Exec instead of DefaultTask, but I don't know a standard way of triggering actual action. It seems easy to modify the commandLine property with what I need, but there's no generic "run()" or the like to use when I want Exec to actually go.

Do I open up Exec to identify which method is it's work method and then invoke it directly? Or is there a more generic way of accomplishing my goal?

like image 695
Josh Gagnon Avatar asked Apr 19 '13 15:04

Josh Gagnon


People also ask

How do I run a Gradle task from the command line?

To run a Gradle command, open a command window on the project folder and enter the Gradle command. Gradle commands look like this: On Windows: gradlew <task1> <task2> … ​ e.g. gradlew clean allTests.

Which Gradle command allows you to see all of the available Gradle operations running in the background?

To list all the tasks of the project, run the below command: gradle tasks -all.

How do I run Gradle tasks in parallel?

Parallel execution Yet Gradle will only run one task at a time by default, regardless of the project structure (this will be improved soon). By using the --parallel switch, you can force Gradle to execute tasks in parallel as long as those tasks are in different projects.

How do I run a Gradle build in terminal?

gradle file, which is located in the subdir/. task hello << { println "using build file '$buildFile.name' in '$buildFile.parentFile.name'." } You can use the following command to execute the above script. using build file 'myproject.


2 Answers

To see which method is executed for a task you can check the sources of Exec and search for a method marked with @TaskAction. It turns out that it's the exec() method but in general you don't want to be calling task actions manually but let Gradle do it for you. The best idea in my opinion is to add methods/setters to your custom tasks. It might look like that:

task addUser(type: AddUser) {
    username = 'fromGradle'
}


class SudoExec extends Exec {

    void sudoCommand(Object... arguments) {
        executable 'sudo'
        args = arguments.toList()
    }
}

class AddUser extends SudoExec {

    void setUsername(String username) {
        sudoCommand('useradd', username)
    }
}
like image 121
erdi Avatar answered Sep 19 '22 06:09

erdi


This code is able to handle multiple parameters, as it doesn't hook into setters of any specific parameters, but uses lazy GString evaluation.

task vagrantfile (type:Vagrantfile) {
    account 'vagrant'
    password 'vagrant'
}

class Vagrantfile extends Copy {
    String account
    String password

    def Vagrantfile() {
        from 'templates/'
        into 'build/'
        include 'Vagrantfile.ubuntu.tpl'
        rename {'Vagrantfile'}
        expand (account:"${->account}", password:"${->password}")
    }
}
like image 23
mkuzmin Avatar answered Sep 19 '22 06:09

mkuzmin