diff --git a/.gitea/conventional_commits/commit-msg b/.gitea/conventional_commits/commit-msg new file mode 100644 index 0000000..67face6 --- /dev/null +++ b/.gitea/conventional_commits/commit-msg @@ -0,0 +1,50 @@ +#!/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 + echo "The exact RegEx applied to this message was:" + colorPrint brightCyan "$regex" + 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..9ad4612 --- /dev/null +++ b/.gitea/conventional_commits/generate-version.sh @@ -0,0 +1,106 @@ +#!/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 -f $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]+)|(#[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]+)|(#[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]+)|(#[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 HISTORY.md + echo $new_version > VERSION + git add 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 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/.gitea/release_message.sh b/.gitea/release_message.sh new file mode 100755 index 0000000..6d42019 --- /dev/null +++ b/.gitea/release_message.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# generates changelog since last release +previous_tag=$(git tag --sort=-creatordate | sed -n 2p) +git shortlog "${previous_tag}.." | sed 's/^./ &/' \ No newline at end of file diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml new file mode 100644 index 0000000..bcc8c28 --- /dev/null +++ b/.gitea/workflows/release.yaml @@ -0,0 +1,61 @@ +name: Build Docker image +permissions: + contents: write + +env: + SKIP_MAKE_SETUP_CHECK: 'true' + +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - '*' # Push events to matching v*, i.e. v1.0, v20.15.10 + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + release: + name: Create Release + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v5 + with: + # by default, it uses a depth of 1 + # this fetches all history so that we can read each commit + fetch-depth: 0 + - name: Generate Changelog + run: .gitea/release_message.sh > release_message.md + - name: Release + uses: softprops/action-gh-release@v1 + with: + body_path: release_message.md + + deploy: + needs: release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Check version match + run: | + REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F '/' '{print $2}' | tr '-' '_') + if [ "$(cat VERSION)" = "${GITHUB_REF_NAME}" ] ; then + echo "Version matches successfully!" + else + echo "Version must match!" + exit -1 + fi + - name: Login to Gitea container registry + uses: docker/login-action@v3 + with: + username: gitearobot + password: ${{ secrets.PACKAGE_GITEA_PAT }} + registry: git.disi.dev + - name: Build and publish + run: | + REPOSITORY_OWNER=$(echo "$GITHUB_REPOSITORY" | awk -F '/' '{print $1}' | tr '[:upper:]' '[:lower:]') + REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F '/' '{print $2}' | tr '-' '_') + docker build -t "git.disi.dev/$REPOSITORY_OWNER/unraid-mcp:$(cat VERSION)" ./ + docker push "git.disi.dev/$REPOSITORY_OWNER/unraid-mcp:$(cat VERSION)" diff --git a/Dockerfile b/Dockerfile index 9a97595..0cf084f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,7 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/ COPY pyproject.toml . COPY uv.lock . COPY README.md . +COPY LICENSE . # Copy the source code COPY unraid_mcp/ ./unraid_mcp/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b1c2ae6 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +.ONESHELL: + +VERSION ?= $(shell cat ./VERSION) + +.PHONY: issetup +issetup: + @[ -f .git/hooks/commit-msg ] || [ $SKIP_MAKE_SETUP_CHECK = "true" ] || (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 " + @echo "" + @echo "Targets:" + @fgrep "##" Makefile | fgrep -v fgrep + +.PHONY: release +release: issetup ## Create a new tag for release. + @./.gitea/conventional_commits/generate-version.sh + +.PHONY: build +build: issetup + @docker build -t unraid-mcp:${VERSION} . \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..8a9ecc2 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.0.1 \ No newline at end of file