Andre's Blog

20160804 Why I Write Shell Scripts With Gradle And Groovy

[GRADLE] [SHELL SCRIPT]

This week I already write my blog post on Thursday, cause I have too much to do for the weekend. I was thinking about to adapt my rule to "release on Sundays", to "till Sunday evening".

Usually when it comes to writing a script to call some programs, everybody uses something like a Bash or Batch script. When a script has to evaluate parameters, I always have the feeling of this-should-look-much-better. When it comes to parsing files I usually end up in frustration, because I will never see any beauty in the code I have to write and I have to write it anyway to solve my problem.

Several years ago I was using Perl for some months, but it was not really satisfying, because the more different functions you use, the more return variables with specific names populate your script. Perl was better than Batch, but still cryptic.

Then I had started looking at Python, but at the same time I had to work on a new project with Java and decided to write my tools from now on with Java. It was simply easier to go from C++ to Java than learning a complete new language like Python and Java came with all classes I needed.

Now I had a language I liked, where executing software was feasible and parsing files was easy, but where should I put the binaries? Add them to Git? Have them in Nexus?

At the end of the project I heard the first time about Groovy and was immediately sad I did not here about it earlier. Groovy was exactly what I was looking for, improved scriptable Java :)

A few months later I had a crash course in Gradle and there I found the last missing part of my puzzle, a tool combined with a script language,

  1. which provides command line parameters through some kind of singleton object (== project)
  2. which lists available main functions (== task) without the need to implement this help
  3. which provides short documentation for the functions (== description) without the need to implement this help
  4. which comes with the full support of Java libraries
  5. which comes with even more support of Groovy helper functionality

To show you what I mean and to give you some answers about what I meant with my post from last week, I give you a small example, let's implement a grep for scanning files in Gradle :

task grep(group: "shell tools") {

description = "greps all lines of -Pfile= containing the value provided with -Ppattern"

doLast {
  String[] lines = file(project.file) as String[]

  for (line in lines) {
    if (line.contains(project.pattern)) {
      println line
    }
  }
}

}

This script shows several aspects I have mentioned before in my blog post from last week :

The basics about Gradle are all easy

  1. The task declaration is descriptive and simple
  2. The task description is assigned to the task variable description
  3. If you only use standard classes, you do not need to import much

It is not only for writing build systems, you can write any kind of script with it.

The grep example has nothing to do with building software.

Gradle scripts are written in Groovy, so if you know Groovy or Java, you already can write Gradle scripts

Just as example for writing Java instead of Groovy :

  println line

is the same as

  system.out.println(line);

it is just something they call syntactic sugar in Groovy.

To make Gradle find your script without extra help, you have to name it build.gradle.

My script is in blog/grepExample/build.gradle, my blog is in blog/blog.md.

Every section of my blog starts with ### 20, the markdown notation for <h3> and the first digits of 2016 and all following years of this blog.

To find out which tasks my script provides I write

amos@Mini:~/gitrepo/blog$ cd grepExample/
amos@Mini:~/gitrepo/blog/grepExample$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'grepExample'.
components - Displays the components produced by root project 'grepExample'. [incubating]
dependencies - Displays all dependencies declared in root project 'grepExample'.
dependencyInsight - Displays the insight into a specific dependency in root project 'grepExample'.
help - Displays a help message.
model - Displays the configuration model of root project 'grepExample'. [incubating]
projects - Displays the sub-projects of root project 'grepExample'.
properties - Displays the properties of root project 'grepExample'.
tasks - Displays the tasks runnable from root project 'grepExample'.

shell tools tasks
-----------------
grep - greps all lines of -Pfile= containing the value provided with -Ppattern

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 16.517 secs

Don't get worried about the Total time : 16.517 secs, remember, I run this on a Samsung N150 with and old Atom processor!

gradle tasks tells us how to use our grep task :

shell tools tasks
-----------------
grep - greps all lines of -Pfile= containing the value provided with -Ppattern

I can have more tasks in different groups in my script and Gradle will list the tasks in their groups.

Now let's test the grep task with the pattern ## 20 on my blog.md file :

amos@Mini:~/gitrepo/blog/grepExample$ gradle grep -Pfile="../blog.md" -Ppattern="## 20"
:grep
### 20160897 Why I Write Shell Scripts With Gradle And Groovy
### 20160731 A Blog About Using Gradle
### 20160723 Sometimes A Sprint Fails
### 20160723 How To Install CentOS In VMWare
### 20160723 Jenkins Entries Are Now In Jenkins Blog
### 20160717 Connecting the nodes in CISystem
### 20160717 A Blog About Jenkins
### 20160717 Now Working With Git On My Synology
### 20160710 Reading Json Configurations In CISystem
### 20160703 CISystem
### 20160703 CISystem Requirement Specification
### 20160626 Sending Objects Via Sockets In Java
### 20160626 A Blog About Coding In Java
### 20160626 A Blog About The Editor Atom
### 20160619 I will post new blog entries every Sunday from now on
### 20160619 Restructuring This Blog
### 20160603 A Blog About Setting Up Xubuntu
### 20160424 A Blog About Using Git
### 20160224 How To Give Code-Blocks A Style in HTML
### 20160221 Elephant Carpaccio Or How Many Things Can I Get Done On Sunday
### 20160216 How To Debug Gradle Scripts
### 20160216 How To Upload Third-Party-Artifacts to Nexus Using Gradle
### 20160216 How To Download Artifacts Nexus Using Gradle
### 20160216 How To Enable Artifact Upload In Nexus Via Web UI
### 20160216 How To Start Nexus For Testing
### 20160216 How To Install Nexus
### 20160216 Technical Realization Of This Blog

BUILD SUCCESSFUL

Total time: 13.065 secs

Works nice, right?

I plan to use parts of this script to generate a rss.xml file for my website, soon!

Select where to go ...


The Blog
My Technical Blogs
Projects
Blogs Of Friends
RSS
CV/About
Me