Governance of cucumber projects using git hooks and gherkin-lint
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.

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-commit
hook 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

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