Automate releases from PR titles and clean up CI workflows.
Code Quality Pipeline / code-quality (pull_request) Failing after 39s
PR Title Check / check-title (pull_request) Successful in 5s
Test Python Package / test (pull_request) Successful in 1m3s

Add release and PR title checks, shared CI scripts, Gitea PR template, and align pyproject.toml to v0.3.1.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Brian Bjarke Jensen
2026-06-28 22:18:40 +02:00
co-authored by Cursor
parent 2bb361e3a3
commit a8491c005c
18 changed files with 417 additions and 80 deletions
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${SCRIPT_DIR}/common.sh"
usage() {
echo "Usage: bump-version.sh <major|minor|patch>" >&2
echo " bump-version.sh --from-tag <vX.Y.Z>" >&2
exit 1
}
if [[ $# -lt 1 ]]; then
usage
fi
if [[ "$1" == "--from-tag" ]]; then
if [[ $# -ne 2 ]]; then
usage
fi
VERSION="${2#v}"
else
BUMP_TYPE="$1"
CURRENT=$(latest_tag_version)
VERSION=$(bump_semver "$CURRENT" "$BUMP_TYPE")
fi
set_pyproject_version "$VERSION"
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "version=${VERSION}"
fi
echo "Updated pyproject.toml to version ${VERSION}" >&2
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${SCRIPT_DIR}/common.sh"
PR_TITLE="${1:-${PR_TITLE:-}}"
if [[ -z "$PR_TITLE" ]]; then
echo "Usage: check-pr-title.sh <pr-title> (changed files on stdin)" >&2
exit 1
fi
CHANGED_FILES=$(cat)
if ! has_source_changes "$CHANGED_FILES"; then
echo "No changes under ${SOURCE_DIR}/ — PR title prefix not required."
exit 0
fi
if title_has_bump_prefix "$PR_TITLE"; then
echo "PR title has a valid version bump prefix."
exit 0
fi
cat >&2 <<EOF
PR changes files under ${SOURCE_DIR}/ but the title lacks a version bump prefix.
Title: ${PR_TITLE}
When changing package source, start the PR title with one of:
[patch] or [fix] — bug fix
[minor] or [feat] — new feature
[major] or [breaking] — breaking change
Example: [patch] Fix connection retry in RedisAdapter
See .gitea/PULL_REQUEST_TEMPLATE.md for details.
EOF
exit 1
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
# Shared helpers for release and PR title CI scripts.
SOURCE_DIR="python_repositories"
# Returns bump type (major|minor|patch) or empty if no valid prefix.
bump_type_from_title() {
local title="$1"
local lower
lower=$(echo "$title" | tr '[:upper:]' '[:lower:]')
if echo "$lower" | grep -qE '^\[(major|breaking)\]'; then
echo "major"
elif echo "$lower" | grep -qE '^\[(minor|feat)\]'; then
echo "minor"
elif echo "$lower" | grep -qE '^\[(patch|fix)\]'; then
echo "patch"
fi
}
title_has_bump_prefix() {
[[ -n "$(bump_type_from_title "$1")" ]]
}
strip_bump_prefix() {
local title="$1"
echo "$title" | sed -E 's/^\[(patch|fix|minor|feat|major|breaking)\][[:space:]]*//i'
}
extract_pr_title_from_merge_commit() {
local msg="$1"
echo "$msg" | sed -n "s/^Merge pull request '\(.*\)' (#.*/\1/p"
}
changed_source_files() {
grep -E "^${SOURCE_DIR}/" || true
}
has_source_changes() {
local files="$1"
echo "$files" | changed_source_files | grep -q .
}
read_pyproject_version() {
sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml | head -1
}
latest_tag_version() {
local tag
tag=$(git describe --tags --abbrev=0 2>/dev/null || true)
if [[ -n "$tag" ]]; then
echo "${tag#v}"
else
read_pyproject_version
fi
}
set_pyproject_version() {
local version="$1"
sed -i.bak -E "s/^version = \".*\"/version = \"${version}\"/" pyproject.toml
rm -f pyproject.toml.bak
}
bump_semver() {
local current="$1"
local bump_type="$2"
local major minor patch
IFS=. read -r major minor patch <<< "$current"
case "$bump_type" in
major)
major=$((major + 1))
minor=0
patch=0
;;
minor)
minor=$((minor + 1))
patch=0
;;
patch)
patch=$((patch + 1))
;;
*)
echo "Unknown bump type: $bump_type" >&2
return 1
;;
esac
echo "${major}.${minor}.${patch}"
}
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${SCRIPT_DIR}/common.sh"
NEW_TAG="${1:-}"
SUMMARY="${2:-}"
PREV_TAG="${3:-}"
if [[ -z "$NEW_TAG" ]]; then
echo "Usage: generate-release-notes.sh <new-tag> [summary] [prev-tag]" >&2
exit 1
fi
if [[ -z "$PREV_TAG" ]]; then
PREV_TAG=$(git describe --tags --abbrev=0 "${NEW_TAG}^" 2>/dev/null || git describe --tags --abbrev=0 2>/dev/null || true)
fi
NOTES="## Summary"
if [[ -n "$SUMMARY" ]]; then
NOTES="${NOTES}
$(strip_bump_prefix "$SUMMARY")"
else
NOTES="${NOTES}
Automated release ${NEW_TAG}."
fi
if [[ -n "$PREV_TAG" ]]; then
NOTES="${NOTES}
## Changes since ${PREV_TAG}
$(git log "${PREV_TAG}..HEAD" --pretty=format:'- %h %s' || true)"
else
NOTES="${NOTES}
## Changes
$(git log --pretty=format:'- %h %s' -20 || true)"
fi
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
{
echo 'body<<EOF'
echo "$NOTES"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
else
echo "$NOTES"
fi
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${SCRIPT_DIR}/common.sh"
COMMIT_MSG="${1:-${COMMIT_MSG:-}}"
if [[ -z "$COMMIT_MSG" ]]; then
echo "Usage: parse-merge-commit.sh <commit-message>" >&2
exit 1
fi
PR_TITLE=$(extract_pr_title_from_merge_commit "$COMMIT_MSG")
if [[ -z "$PR_TITLE" ]]; then
bump="skip"
else
bump_type=$(bump_type_from_title "$PR_TITLE")
if [[ -n "$bump_type" ]]; then
bump="$bump_type"
else
bump="skip"
fi
fi
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
{
echo "pr_title=${PR_TITLE}"
echo "bump=${bump}"
} >> "$GITHUB_OUTPUT"
else
echo "pr_title=${PR_TITLE}"
echo "bump=${bump}"
fi