Using a Git Pre-Commit Hook for Automatic Linting, Unit Testing, and Code Standards Checking of Application Code

Problem: I want to automatically run unit tests, lint the application code, and check it’s state against team standards every time I try to commit my changes to a project. It would be nice if the commit aborts if any of the existing tests fails or if I did not follow a particular standard that the team agrees to uphold. The commit pushes through if there are no errors. If possible, I don’t have to change anything in my software development workflow.

Solution: Use a Git pre-commit hook. Under the .git/hooks hidden folder in the project directory, create a new file called pre-commit (without any file extension) containing something like the following bash script (for testing PHP code):

#!/bin/sh

stagedFiles=$(git diff-index --cached HEAD | grep ".php" | grep "^:" | sed 's:.*[DAM][ \\''t]*\([^ \\''t]*\):\1:g');
errorMessage="Please correct the errors above. Commit aborted."

printf "Linting and checking code standards ..."
for file in $stagedFiles
do
  php -l $file
  LINTVAL=$?
  if [[ $LINTVAL != 0 ]]
  then
    printf $errorMessage
    exit 1
  fi
  php core/phpcs.phar --colors --standard=phpcs.xml $file
  STANDVAL=$?
  if [[ $STANDVAL != 0 ]]
  then
    printf $errorMessage
    exit 1
  fi
done

printf "Running unit tests ..."
core/vendor/bin/phpunit --colors="always" [TESTS_DIRECTORY]
TESTSVAL=$?
if [[ $TESTSVAL != 0 ]]
then
  printf $errorMessage
  exit 1
fi

where

  • linting and code standard checks only runs for the files you want to commit changes to
  • code standard checks are based on a certain phpcs.xml file
  • unit tests inside a particular TESTS_DIRECTORY will run
  • the commit will abort whenever any of the lints, code standard checks, or unit tests fails

Post-Installation Notes after Setting-Up Cucumber-Ruby-Watir Automated Checks with Jenkins on a Windows 10 Amazon EC2 Server

Had a chance to set up cucumber tests to run via Jenkins on a Windows 10 Amazon EC2 server last week. It’s been a while since I installed everything from scratch, so that was good practice. I ran into some problems, which was a bit expected since my local setup was on Windows 7, so this post serves as a guide for possible future installations.

The process:

  • Install desired browsers where the tests will run.
  • Install Java and the latest JDK. Include the JDK path to Window’s system environment variables. This is necessary for running the selenium server.
  • Install the latest Ruby and DevKit versions, required for installing ruby gems and running the test suite.
  • Install Jenkins, which will take care of scheduling and test results reporting. Also install Jenkins as a service, to run automatically after the server boots up.
  • Install Git on the machine, and setup the credentials for retrieving the test code from the remote repository.
  • Check out the test code from the remote repository.
  • Set the selenium server to run automatically after the machine boots.
  • Install the required ruby gems using bundler.
  • Check if cucumber tests run properly by running a sample via the command line interface.
  • Create/Import Jenkins jobs for the cucumber tests. Install the Jenkins plugins necessary for test results reporting. Possibly set up Jenkins to pull the latest test code from the remote repository.
  • Run cucumber tests via Jenkins.

Some reminders for future installs:

  • Install the 32-bit version of Ruby’s DevKit instead of the 64-bit because the latter version creates problems with gem installs.
  • Windows 10 has trouble installing ruby gems (using the bundle install command) from the default HTTPS source. To fix this, replace the gems source list in the Gemfile from HTTPS to HTTP.
  • Install Jenkins using the MSI-based Windows installer on its own directory on the C drive, then install it as a service afterwards.
  • Do not install all suggested Jenkins plugins at first, especially the ones related to Git. These will break Jenkins on Windows so install only those that are actually needed for cucumber tests to run.
  • Via Jenkin’s Configure System module, set the shell executable to the location of the command line’s executable file (i.e., C:\Windows\system32\cmd.exe) so that Jenkins can run cucumber tests via the default Windows command line interface. In addition, each Jenkins job Build needs to be set as “Execute Windows Batch Command” instead of “Execute Shell”.
  • Remember to change the timezone of the machine to the proper timezone.
  • Test a sample basic cucumber project first to see if cucumber is properly running on the machine before retrieving the actual test suite from the Git repository.
  • In saving the machine’s generated public SSH identification (via Putty or the ssh keygen command using Cygwin), do not include a name for the file to be saved so that the system generates the default id_rsa.pub file.

Pushing Initial Project Code to a Newly Created Github Repository

  1. Create a new Github repository on your account, say TestRepo
  2. Create SSH public and private keys for your machine, and add that SSH key to your Github account
  3. Go to your project directory and create a .gitignore file for files and folders you do not want to publicly upload to your Github repository
  4. Open the command prompt, by pressing the Window and R keyboard buttons at the same time, typing in cmd, and pressing Enter
  5. In the command prompt, go to the root of your project code, say cd C:\Users\Your_Machine_Name\Test_Project
  6. Run git init
  7. Run git add . 
  8. Run git commit -m ‘Initial commit’. You can replace the commit message with a desired message if you want to.
  9. Go to your newly created Github repo and copy its SSH address, i.e. git@github.com:github_username/TestRepo
  10. Back to the command prompt, run git remote add origin git@github.com:github_username/TestRepo
  11. Run git push -u origin master

Update: Pushing latest changes to the repository

  1. Back on the command prompt, run git status to display the files where changes were last made
  2. Copy the path of the file you want to commit, then run git add <filename> for each file. Run git add -u if you want to include everything except the new files. Run git add -A if literally all files needed to be committed.
  3. Run git commit -m <commit message> to ready the files for transfer to your repository
  4. Run git push -u origin master to push these changes

Update: Creating and/or Moving to a particular branch of code

  1. On the command prompt, run git branch to display all the branches available to you locally. By default, there is only one branch, aptly named as master.
  2. If you want to build a new branch from master, run git checkout -b <branch_name>. This creates and automatically moves you to the new branch.
  3. If you want to move to another branch, run git checkout <branch_name>.

Update: Creating a new branch from an existing branch

  1. Run git checkout -b <new_branch> <existing_branch>

Update: Merging Branches

  1. Run git merge <branch_name> if you want to merge that branch to the branch where you are currently in.

Update: Deleting branches

  1. Run git branch -d <branch_name> if you want to delete a branch. This will delete that branch in your local repository.
  2. Run git push –delete <remote_name> <branch_name>. This will delete the selected branch in the remote repository.

Update: Retrieving latest version of code

  1. Run git fetch origin.
  2. Run git reset –hard origin/master. Note that this will effectively remove all files locally and replace them with the latest files found in the remote repository.