Skip to content

Instantly share code, notes, and snippets.

@Buitragox
Last active May 14, 2025 23:01
Show Gist options
  • Save Buitragox/57a498858e899f8dd300855248e30017 to your computer and use it in GitHub Desktop.
Save Buitragox/57a498858e899f8dd300855248e30017 to your computer and use it in GitHub Desktop.
Compare spec coverage between two commits
# This script is used to get the coverage of two commits in a git repository.
function coverages() {
local HASH_MODE=false
local PICKER_MODE=false
local SEARCH_TERM=""
local COMMIT=""
local PREV_COMMIT=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-c|--commits)
HASH_MODE=true
shift
COMMIT="$1"
shift
if [[ $# -gt 0 ]]; then
PREV_COMMIT="$1"
shift
else
echo "Error: When using -c|--commits, you must provide two commit hashes."
return 1
fi
;;
-p|--picker)
PICKER_MODE=true
shift
;;
*)
SEARCH_TERM="$1"
shift
;;
esac
done
# Check if a search term or commit hashes were provided
if [[ -z "$SEARCH_TERM" && "$HASH_MODE" = false && "$PICKER_MODE" = false ]]; then
echo "Usage: coverages <COMMIT_DESCRIPTION>"
echo " or: coverages -c <COMMIT_HASH1> <COMMIT_HASH2>"
echo ' or: coverages -p | --picker (requires \e]8;;https://github.com/junegunn/fzf\e\\fzf\e]8;;\e\\ to pick commits)'
echo "Examples:"
echo " coverages \"#240\" (If the PR is already merged)"
echo " coverages \"COM-123: Fix\""
echo " coverages -c abc1234 def5678"
echo " coverages -c HEAD HEAD~1"
echo " coverages -p"
return 1
fi
local RED='\033[0;31m'
local NC='\033[0m' # No Color
# Check if fzf is installed if using picker mode
if [[ "$PICKER_MODE" = true ]]; then
if ! command -v fzf >/dev/null 2>&1; then
echo "Error: fzf is not installed. Please install it first with:"
echo " brew install fzf"
return 1
fi
COMMIT=$(git log --pretty=format:"%h %ad %s" --date=short | fzf --prompt="Select the first commit (newer) » " --height=~50% --layout=reverse --border | awk '{print $1}')
if [[ -z "$COMMIT" ]]; then
echo "No commit selected. Aborting."
return 1
fi
echo "${RED}Selected commit #1: $COMMIT${NC}"
PREV_COMMIT=$(git log --pretty=format:"%h %ad %s" --date=short | fzf --prompt="Select the first commit (newer) » " --height=~50% --layout=reverse --border | awk '{print $1}')
if [[ -z "$PREV_COMMIT" ]]; then
echo "No second commit selected. Aborting."
return 1
fi
echo "${RED}Selected commit #2: $PREV_COMMIT${NC}"
fi
# Skip commit search if hash mode or picker mode is enabled (direct commit hashes provided)
if [[ "$HASH_MODE" = false && "$PICKER_MODE" = false ]]; then
COMMIT=$(git log --grep="$SEARCH_TERM" --format="%H" -n 1)
if [[ -z $COMMIT ]]; then
echo "No commit found with description \"$SEARCH_TERM\" in the message."
return 1
fi
# Use the previous commit as the second commit
PREV_COMMIT=$(git rev-parse $COMMIT~1)
fi
# Verify commits exist when using hash mode
if [[ "$HASH_MODE" = true || "$PICKER_MODE" = true ]]; then
if ! git rev-parse --verify $COMMIT^{commit} >/dev/null 2>&1; then
echo "Error: First commit hash '$COMMIT' is not valid."
return 1
fi
if ! git rev-parse --verify $PREV_COMMIT^{commit} >/dev/null 2>&1; then
echo "Error: Second commit hash '$PREV_COMMIT' is not valid."
return 1
fi
fi
echo "Commit #1: $COMMIT"
git log -n 1 --pretty=format:"%s%n%n%b" $COMMIT
echo "Commit #2: $PREV_COMMIT"
git log -n 1 --pretty=format:"%s%n%n%b" $PREV_COMMIT
# Ask for confirmation before proceeding
echo -n "Get coverages for these commits? (y/n): "
read CONFIRM
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
echo "Cancelled."
return 0
fi
local CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
echo "${RED}Checking out commit $COMMIT...${NC}"
git checkout $COMMIT
if [[ $? -ne 0 ]]; then
echo "${RED}Error: git checkout failed. You may have uncommitted changes. Aborting.${NC}"
return 1
fi
echo "${RED}Installing gems...${NC}"
bundle install
echo "${RED}Preparing database...${NC}"
bundle exec rake db:test:prepare
echo "${RED}Running tests...${NC}"
bundle exec rspec
local AFTER=$(cat ./coverage/.last_run.json | jq '.result.covered_percent')
echo "${RED}Checking out previous commit $PREV_COMMIT...${NC}"
git checkout $PREV_COMMIT
echo "${RED}Installing gems...${NC}"
bundle install
echo "${RED}Preparing database...${NC}"
bundle exec rake db:test:prepare
echo "${RED}Running tests...${NC}"
bundle exec rspec
local BEFORE=$(cat ./coverage/.last_run.json | jq '.result.covered_percent')
echo "${RED}Restoring environment...${NC}"
git checkout $CURRENT_BRANCH
bundle install
bundle exec rake db:test:prepare
echo "\n${RED}DONE!${NC}"
echo "Coverage before (commit #1 $COMMIT): $BEFORE"
echo "Coverage after (commit #2 $PREV_COMMIT): $AFTER"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment