Governance of cucumber projects using git hooks and gherkin-lint

Ankush Sawant
4 min readJun 24, 2021

With some big automation projects having many people pushing their code it apparently becomes difficult to adhere to rules defined. Same happened with us and then we decided to put some sort of governance on it.

Problem Statements
1. We want to set some governance on feature files like required tags, not required tags, missing steps and what not.
2. Set some governance on git branch name, we were literally having branches with all words.

Governance on Feature files

We know there are several linting tools available which developers generally use. But our search was for something specific for cucumber. Search ended on gherkin-lint, a feature file linter.

How to integrate with Java based projects?

Step-1: It requires node and npm so added frontend-maven-plugin we wanted it to run on need so we made it profile based in our pom.xml

<profile>
<id>local</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.7.5</version>
<configuration>
<installDirectory>node-dir</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<phase>install</phase>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v12.18.0</nodeVersion>
<npmVersion>6.14.4</npmVersion>
</configuration>
</execution>
<execution>
<id>front-npm-install</id>
<phase>install</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
<workingDirectory>nodedir</workingDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

</build>
</profile>

Step-2: Add directory in project as mentioned in plugin and add a package.json file to get gherkin-lint.

directory structure and package.json

Step-3: Add dependency

<dependency>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.0</version>
</dependency>

Step-4: Run mvn clean install -P local to get node, npm and gherkin-lint installed. On success, all the components will be installed inside node-dir as shown below. First node directory is of node and npm and node_modules directory is installed of gherkin-lint.

Step-5: Till now we have got all the required thing for linting our feature files. Next is we need to set rules. gherkin-lint provides a wide rage of possible rules which we can set as per our requirement.
For that we need to have .gherkin-lintrc file in our framework (preferably at root level). This will contain all the rules.
Rules are self explanatory and more details can be found here

Step-6: Once all set, need to execute below command to get the job done
`.node-dir/node_modules/.bin/gherkin-lint -c ./.gherkin-lintrc ./path/to/folder/with/feature/files

Integrate above with Git Hook

Above command at 6th step will lint all the feature files which falls under target folder. Our objective is to lint on modified feature files before commit. We will leverage git’s pre-commit hook with some bash script.
To give a short introduction git hooks are small piece of codes which triggers at some point of git execution.
These hooks can be find inside .git/hooks directory. We will use pre-commit hook which executes before actual commit takes place.
Below is my pre-commithook file (remember you need to remove .sample extension)

#!/bin/bash

#Author Ankush Sawant

RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[1;34m'
MAGENTA='\033[1;35m'
NC='\033[0m' # No Color
erroredFiles=0

function get_abs_filename() {
#$1 : relative filename
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")/"
}

export PATH="$PATH:$(get_abs_filename "node-dir/node")"
printf "${BLUE}--------------- STARTING FEATURE FILE VALIDATION BEFORE COMMIT ---------------${NC}\n"
files=$(git diff --diff-filter=d --cached --name-only | grep -E '\.(feature)$'| wc -l)
printf "${BLUE}Number of feature files staged and will be validated are : ${MAGENTA}'$files'${NC}\n"
if [ $files -eq 0 ]
then
printf "${GREEN}No feature file is staged now validation exits......${NC}\n"
exit 0
fi


for file in $(git diff --diff-filter=d --cached --name-only | grep -E '\.(feature)$')
do
./node-dir/node_modules/.bin/gherkin-lint -c ./.gherkin-lintrc $file
if [ $? -ne 0 ]
then
erroredFiles=$(($erroredFiles+1))
fi
done

if [ $erroredFiles -ne 0 ]
then
printf "${RED}Commit REJECTED due to compliance in '$erroredFiles' feature files. Please correct them and commit again${NC}\n"
exit 1
else
printf "${GREEN}Good job!! your commit was good and accepted${NC}\n"
exit 0
fi

Below are few screenshots covering 3 major scenarios

commit messages

Sharing the Git Hook’s with team

As of now we have kept our pre-commit hook inside .git/hooks directory. But we can not commit and share this directory with our team mate. So we need to do a common trick for it (this will work even for git version <2.9 however there is a better option in version >2.9).

We will create a .githook directory in our project’s root, place pre-commit file inside this directory(we can place multiple hooks here) and will use maven’s maven-resources-plugin to copy file from .githook directory to .git/hooks directory during install phase.

<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-resource-one</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>

<configuration>
<outputDirectory>./.git/hooks</outputDirectory>
<includeEmptyDirs>true</includeEmptyDirs>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>./.githooks</directory>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

Governance on branch name

TDB

--

--

Ankush Sawant

Working as a Senior Lead with GlobalLogic. Passionate about learning new things. Likes humor and not an Covidiot.