From 7e0c0136ed5121ec5fd1f6a896ad8423461a5a0f Mon Sep 17 00:00:00 2001 From: Tomas Z <93541722+tznamena@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:01:01 -0500 Subject: [PATCH] AAP-35592: Move git hooks to own folder, add pre-push hook (#674) # [AAP-35592] Add git hook checking existence of Jira number in branch and commit messages ## Description This PR provides following changes: * creates new folder for git hooks to make the git hooks more visible and easier to maintain. The folder itself contains documentation. * adds a new git hook invoked at `git push` to check whether the branch and commit message at the time of push contain Jira number (AAP-NNNNN) or a special marker `NO_JIRA` to indicate the changes don't have/need a Jira item. These changes are needed in order to keep work items in Jira in sync with their corresponding pull requests and commits. The Jira numbers included in the commit messages can be different from Jira number in branch name to allow for cherry-picking of commits when PRs are being back ported. ## Type of Change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update - [ ] Test update - [x] Refactoring (no functional changes) - [x] Development environment change - [ ] Configuration change ## Self-Review Checklist - [x] I have performed a self-review of my code - [x] I have added relevant comments to complex code sections - [x] I have updated documentation where needed - [x] I have considered the security impact of these changes - [x] I have considered performance implications - [x] I have thought about error handling and edge cases - [x] I have tested the changes in my local environment ## Testing Instructions ### Prerequisites ### Steps to Test 1. Pull down the PR 2. Run `make git_hooks_config` in the root of the repo 3. Create a new branch, make some change, commit it and try to push it to your fork. Based on branch name and commit message you will see different results (see below). ### Expected Results * If the branch did not include either a Jira number in format AAP-NNNN or magic string NO_JIRA you shouldn't be able to push. * If the branch did include Jira number, but commit message did not, you shouldn't be able to push. * If the branch did include Jira number, and the commit message included the same Jira number, your push will succeed. * If the branch did include Jira number and the commit message included **different** Jira number, you will see a warning but the push will succeed. --- .githooks/README.md | 28 ++++++++++++++++ pre-commit.sh => .githooks/pre-commit | 0 .githooks/pre-push | 46 +++++++++++++++++++++++++++ Makefile | 13 +++----- 4 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 .githooks/README.md rename pre-commit.sh => .githooks/pre-commit (100%) create mode 100755 .githooks/pre-push diff --git a/.githooks/README.md b/.githooks/README.md new file mode 100644 index 000000000..ed8c513d6 --- /dev/null +++ b/.githooks/README.md @@ -0,0 +1,28 @@ +# .githooks + +This folder contains executable files that will be invoked by git at certain git operations. + +By default git hooks are located i `.git/hooks` folder at the root of the repository. Since the default folder is hidden by most IDEs, this repository reconfigures git's hook location in order to make the hooks visible and easier to maintain. + +## Configuration + +Normal development flows (see file [../README.md](../README.md) ) will call git to change the location of git hooks. + +To make this change manually you can invoke following command from the root of the repository: + +```sh +make git_hooks_config +``` + +## Git hooks implementation + +Git hooks are simply executable files that follow the rules below: + +* have executable permissions +* file name must correspond to git hook name with no extension(no `.sh` or `.py`) (see documentation section below) + +Return code other than zero(0) will cause the git operation that triggerred the hook to fail, while zero(0) return code indicates success and git opertaion will succeed. + +## Documentation + +Git hooks documentation: diff --git a/pre-commit.sh b/.githooks/pre-commit similarity index 100% rename from pre-commit.sh rename to .githooks/pre-commit diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 000000000..e4e863516 --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Name of default branch from which feature branches are created and to which PRs will be merged back to +DEFAULT_BRANCH="devel" +# Regexp to match jira number AAP-NNNNN or magic string "NO_JIRA" +NO_JIRA_MARKER="NO_JIRA" +JIRA_REGEXP="(aap-[0-9]+|${NO_JIRA_MARKER})" + +# Fetch current branch name and list of commits since diverging from default branch +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +CURRENT_COMMITS=$(git --no-pager log --format=%s --reverse ${DEFAULT_BRANCH}..) + +# Extract Jira number or magic marker from branch and commit messages(filtered for unique values) +BRANCH_JIRA=$(grep -i -o -E "${JIRA_REGEXP}" <<< ${CURRENT_BRANCH}) +COMMIT_JIRAS=$(grep -i -o -E "${JIRA_REGEXP}" <<< ${CURRENT_COMMITS} | uniq ) +# Count all Jira numbers and those matching Jira from branch name +COMMIT_JIRA_COUNT=$(grep -c . <<< ${COMMIT_JIRAS}) +MATCHING_JIRAS_COUNT=$(grep -ic -E "${BRANCH_JIRA}" <<< ${COMMIT_JIRAS}) + +echo "JIRA number from branch name: ${BRANCH_JIRA}" +echo "JIRA numbers from commits:" +echo "${COMMIT_JIRAS}" +echo "Number of JIRA numbers from commits matching JIRA number from branch name: ${MATCHING_JIRAS_COUNT}" + +# if no Jira or no magic marker found in branch name, fail +echo "Checking branch name..." +if [ "${BRANCH_JIRA}" = "" ]; then + echo "Fail: Branch name does not contain a JIRA number or a ${NO_JIRA_MARKER} marker." + exit 1 +# if branch does not have the magic marker, check the commits as well +elif [ "${BRANCH_JIRA}" != "${NO_JIRA_MARKER}" ]; then + echo "Checking commit messages..." + # if there is no Jira number or magic marker, fail + if [ ${COMMIT_JIRA_COUNT} -eq 0 ]; then + echo "Fail: No commit message contains a JIRA number or a ${NO_JIRA_MARKER} marker." + exit 1 + # if no Jira numbers or magic marker match the Jira number from branch name, inform the user + # this case might be happening when code is being back-ported under different Jira number in branch name + elif [ ${MATCHING_JIRAS_COUNT} -eq 0 ]; then + echo "Warning: No Jira numbers or ${NO_JIRA_MARKER} marker in commit messages match Jira number from branch name." + else + echo "OK. Found Jira numbers(or ${NO_JIRA_MARKER} marker) in commit messages that match Jira number in branch name." + fi +else + echo "OK. Skipping checks of commit messages, branch name includes ${NO_JIRA_MARKER}." +fi diff --git a/Makefile b/Makefile index 0af0ba501..64bd9c2f7 100644 --- a/Makefile +++ b/Makefile @@ -11,17 +11,14 @@ COMPOSE_UP_OPTS ?= DOCKER_COMPOSE ?= docker compose .PHONY: PYTHON_VERSION clean build\ - check lint check_black check_flake8 check_isort + check lint check_black check_flake8 check_isort git_hooks_config PYTHON_VERSION: @echo "$(subst python,,$(PYTHON))" -## Install the pre-commit hook in the approprate .git directory structure -.git/hooks/pre-commit: - @echo "if [ -x pre-commit.sh ]; then" > .git/hooks/pre-commit - @echo " ./pre-commit.sh;" >> .git/hooks/pre-commit - @echo "fi" >> .git/hooks/pre-commit - @chmod +x .git/hooks/pre-commit +## Set the local git configuration(specific to this repo) to look for hooks in .githooks folder +git_hooks_config: + git config --local core.hooksPath .githooks ## Zero out all of the temp and build files clean: @@ -69,7 +66,7 @@ stop-postgres: # -------------------------------------- # Build the library into /dist -build: .git/hooks/pre-commit +build: git_hooks_config python -m build .