From 980cd38f8e1b39bb469b338e315262a53a0843ba Mon Sep 17 00:00:00 2001 From: Simon Diesenreiter Date: Sat, 30 Nov 2024 21:22:54 +0100 Subject: [PATCH] build: introduce conventional commits, ref NOISSUE --- .gitea/conventional_commits/commit-msg | 47 ++++++++ .../conventional_commits/generate-version.sh | 105 ++++++++++++++++++ .../conventional_commits/hooks/text-styles.sh | 44 ++++++++ .gitignore | 3 +- Makefile | 26 +++-- 5 files changed, 215 insertions(+), 10 deletions(-) create mode 100755 .gitea/conventional_commits/commit-msg create mode 100755 .gitea/conventional_commits/generate-version.sh create mode 100755 .gitea/conventional_commits/hooks/text-styles.sh diff --git a/.gitea/conventional_commits/commit-msg b/.gitea/conventional_commits/commit-msg new file mode 100755 index 0000000..335984a --- /dev/null +++ b/.gitea/conventional_commits/commit-msg @@ -0,0 +1,47 @@ +#!/usr/bin/env sh +echo "Running commit message checks..." + +. "$(dirname -- "$0")/../../.gitea/conventional_commits/hooks/text-styles.sh" + + +# Get the commit message +commit="$(cat .git/COMMIT_EDITMSG)" +# Define the conventional commit regex +regex='^((build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\(.+\))?(!?):\s([a-zA-Z0-9-_!\&\.\%\(\)\=\w\s]+)\s?(,?\s?)((ref(s?):?\s?)(([A-Z0-9]+\-[0-9]+)|(NOISSUE))))|(release: .*)$' + +# Check if the commit message matches the conventional commit format +if ! echo "$commit" | grep -Pq "$regex" +then + echo + colorPrint red "❌ Failed to create commit. Your commit message does not follow the conventional commit format." + colorPrint red "Please use the following format: $(colorPrint brightRed 'type(scope)?: description')" + colorPrint red "Available types are listed below. Scope is optional. Use ! after type to indicate breaking change." + echo + colorPrint brightWhite "Quick examples:" + echo "feat: add email notifications on new direct messages refs ABC-1213" + echo "feat(shopping cart): add the amazing button ref: DEFG-23" + echo "feat!: remove ticket list endpoint ref DADA-109" + echo "fix(api): handle empty message in request body refs: MINE-82" + echo "chore(deps): bump some-package-name to version 2.0.0 refs ASDF-12" + echo + colorPrint brightWhite "Commit types:" + colorPrint brightCyan "build: $(colorPrint white "Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)" -n)" + colorPrint brightCyan "ci: $(colorPrint white "Changes to CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)" -n)" + colorPrint brightCyan "chore: $(colorPrint white "Changes which doesn't change source code or tests e.g. changes to the build process, auxiliary tools, libraries" -n)" + colorPrint brightCyan "docs: $(colorPrint white "Documentation only changes" -n)" + colorPrint brightCyan "feat: $(colorPrint white "A new feature" -n)" + colorPrint brightCyan "fix: $(colorPrint white "A bug fix" -n)" + colorPrint brightCyan "perf: $(colorPrint white "A code change that improves performance" -n)" + colorPrint brightCyan "refactor: $(colorPrint white "A code change that neither fixes a bug nor adds a feature" -n)" + colorPrint brightCyan "revert: $(colorPrint white "Revert a change previously introduced" -n)" + colorPrint brightCyan "test: $(colorPrint white "Adding missing tests or correcting existing tests" -n)" + echo + + colorPrint brightWhite "Reminders" + echo "Put newline before extended commit body" + echo "More details at $(underline "http://www.conventionalcommits.org")" + echo + echo "The commit message you attempted was: $commit" + echo + exit 1 +fi \ No newline at end of file diff --git a/.gitea/conventional_commits/generate-version.sh b/.gitea/conventional_commits/generate-version.sh new file mode 100755 index 0000000..b4654db --- /dev/null +++ b/.gitea/conventional_commits/generate-version.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# Rules for generating semantic versioning +# major: breaking change +# minor: feat, style +# patch: build, fix, perf, refactor, revert + +PREVENT_REMOVE_FILE=$1 +TEMP_FILE_PATH=.gitea/conventional_commits/tmp + +LAST_TAG=$(git describe --tags --abbrev=0 --always) +echo "Last tag: #$LAST_TAG#" +PATTERN="^[0-9]+\.[0-9]+\.[0-9]+$" + +increment_version() { + local version=$1 + local increment=$2 + local major=$(echo $version | cut -d. -f1) + local minor=$(echo $version | cut -d. -f2) + local patch=$(echo $version | cut -d. -f3) + + if [ "$increment" == "major" ]; then + major=$((major + 1)) + minor=0 + patch=0 + elif [ "$increment" == "minor" ]; then + minor=$((minor + 1)) + patch=0 + elif [ "$increment" == "patch" ]; then + patch=$((patch + 1)) + fi + + echo "${major}.${minor}.${patch}" +} + +create_file() { + local with_range=$1 + if [ -s $TEMP_FILE_PATH/messages.txt ]; then + return 1 + fi + if [ "$with_range" == "true" ]; then + git log $LAST_TAG..HEAD --no-decorate --pretty=format:"%s" > $TEMP_FILE_PATH/messages.txt + else + git log --no-decorate --pretty=format:"%s" > $TEMP_FILE_PATH/messages.txt + fi +} + +get_commit_range() { + rm $TEMP_FILE_PATH/messages.txt + if [[ $LAST_TAG =~ $PATTERN ]]; then + create_file true + else + create_file + LAST_TAG="0.0.0" + fi + echo " " >> $TEMP_FILE_PATH/messages.txt +} + +start() { + mkdir -p $TEMP_FILE_PATH + get_commit_range + new_version=$LAST_TAG + increment_type="" + + while read message; do + echo $message + if echo $message | grep -Pq '(feat|style)(\([\w]+\))?!:([a-zA-Z0-9-_!\&\.\%\(\)\=\w\s]+)\s?(,?\s?)((ref(s?):?\s?)(([A-Z0-9]+\-[0-9]+)|(NOISSUE)))'; then + increment_type="major" + echo "a" + break + elif echo $message | grep -Pq '(feat|style)(\([\w]+\))?:([a-zA-Z0-9-_!\&\.\%\(\)\=\w\s]+)\s?(,?\s?)((ref(s?):?\s?)(([A-Z0-9]+\-[0-9]+)|(NOISSUE)))'; then + if [ -z "$increment_type" ] || [ "$increment_type" == "patch" ]; then + increment_type="minor" + echo "b" + fi + elif echo $message | grep -Pq '(build|fix|perf|refactor|revert)(\(.+\))?:\s([a-zA-Z0-9-_!\&\.\%\(\)\=\w\s]+)\s?(,?\s?)((ref(s?):?\s?)(([A-Z0-9]+\-[0-9]+)|(NOISSUE)))'; then + if [ -z "$increment_type" ]; then + increment_type="patch" + echo "c" + fi + fi + done < $TEMP_FILE_PATH/messages.txt + + if [ -n "$increment_type" ]; then + new_version=$(increment_version $LAST_TAG $increment_type) + echo "New version: $new_version" + + gitchangelog | grep -v "[rR]elease:" > HISTORY.md + git add DotnetTestLib/VERSION HISTORY.md + echo $new_version > DotnetTestLib/VERSION + git commit -m "release: version $new_version 🚀" + echo "creating git tag : $new_version" + git tag $new_version + git push -u origin HEAD --tags + echo "Gitea Actions will detect the new tag and release the new version." + else + echo "No changes requiring a version increment." + fi +} + +start + +if [ -z "$PREVENT_REMOVE_FILE" ]; then + rm -f $TEMP_FILE_PATH/messages.txt +fi \ No newline at end of file diff --git a/.gitea/conventional_commits/hooks/text-styles.sh b/.gitea/conventional_commits/hooks/text-styles.sh new file mode 100755 index 0000000..73d91ef --- /dev/null +++ b/.gitea/conventional_commits/hooks/text-styles.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +colorPrint() { + local color=$1 + local text=$2 + shift 2 + local newline="\n" + local tab="" + + for arg in "$@" + do + if [ "$arg" = "-t" ]; then + tab="\t" + elif [ "$arg" = "-n" ]; then + newline="" + fi + done + + case $color in + black) color_code="30" ;; + red) color_code="31" ;; + green) color_code="32" ;; + yellow) color_code="33" ;; + blue) color_code="34" ;; + magenta) color_code="35" ;; + cyan) color_code="36" ;; + white) color_code="37" ;; + brightBlack) color_code="90" ;; + brightRed) color_code="91" ;; + brightGreen) color_code="92" ;; + brightYellow) color_code="93" ;; + brightBlue) color_code="94" ;; + brightMagenta) color_code="95" ;; + brightCyan) color_code="96" ;; + brightWhite) color_code="97" ;; + *) echo "Invalid color"; return ;; + esac + + printf "\e[${color_code}m${tab}%s\e[0m${newline}" "$text" +} + +underline () { + printf "\033[4m%s\033[24m" "$1" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 31db540..185aa60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ **/bin -**/obj \ No newline at end of file +**/obj +.gitea/conventional_commits/tmp/* \ No newline at end of file diff --git a/Makefile b/Makefile index 6fd9690..ceb6b7c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,13 @@ .ONESHELL: +.PHONY: issetup +issetup: + @[ -f .git/hooks/commit-msg ] || (echo "You must run 'make setup' first to initialize the repo!" && exit 1) + +.PHONY: setup +setup: + @cp .gitea/conventional_commits/commit-msg .git/hooks/ + .PHONY: help help: ## Show the help. @echo "Usage: make " @@ -8,35 +16,35 @@ help: ## Show the help. @fgrep "##" Makefile | fgrep -v fgrep .PHONY: buildrel -buildrel: ## Format code. +buildrel: issetup ## Format code. dotnet build -c Release project_name.sln .PHONY: build -build: ## Format code. +build: issetup ## Format code. dotnet build project_name.sln .PHONY: publish -publish: ## Format code. +publish: issetup ## Format code. dotnet publish -c Release project_name.sln .PHONY: fmt -fmt: ## Format code. +fmt: issetup ## Format code. dotnet format project_name.sln .PHONY: lint -lint: ## Lint code. +lint: issetup ## Lint code. dotnet format --verify-no-changes --verbosity diagnostic project_name.sln .PHONY: test -test: ## Run tests and generate coverage report. +test: issetup ## Run tests and generate coverage report. dotnet test project_name.sln .PHONY: clean -clean: ## Clean unused files. +clean: issetup ## Clean unused files. dotnet clean project_name.sln .PHONY: release -release: ## Create a new tag for release. +release: issetup ## Create a new tag for release. @echo "WARNING: This operation will create a version tag and push to gitea" @read -p "Version? (provide the next x.y.z semver) : " TAG; echo "$$TAG" > project_name/VERSION @gitchangelog > HISTORY.md @@ -48,7 +56,7 @@ release: ## Create a new tag for release. @echo "Gitea Actions will detect the new tag and release the new version." .PHONY: docs -docs: ## Build the documentation. +docs: issetup ## Build the documentation. @echo "building documentation ..." @mkdocs build URL="site/index.html"; xdg-open $$URL || sensible-browser $$URL || x-www-browser $$URL || gnome-open $$URL || open $$URL