Created
September 29, 2025 07:26
-
-
Save dazz/ce1d95b2c3d9ae6640f62c6d0bde2ee7 to your computer and use it in GitHub Desktop.
Revisions
-
dazz created this gist
Sep 29, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,21 @@ # Configuration RELEASE_BRANCH ?= main CALVER_PATTERN ?= %Y.%m.%d .PHONY: release release-auto release-next-tag release-check # Interactive release (prompts for pull and confirmation) release: @RELEASE_BRANCH=$(RELEASE_BRANCH) CALVER_PATTERN=$(CALVER_PATTERN) ./scripts/release.sh release # Automated release (no prompts, pull + create + push) release-auto: @RELEASE_BRANCH=$(RELEASE_BRANCH) CALVER_PATTERN=$(CALVER_PATTERN) ./scripts/release.sh release --auto # Show next tag release-next-tag: @RELEASE_BRANCH=$(RELEASE_BRANCH) CALVER_PATTERN=$(CALVER_PATTERN) ./scripts/release.sh next-tag # Check for changes release-check: @RELEASE_BRANCH=$(RELEASE_BRANCH) CALVER_PATTERN=$(CALVER_PATTERN) ./scripts/release.sh check-changes This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,29 @@ # Git Release Tag ## Usage ```bash # Interactive (default - asks for pull and confirmation) ./scripts/release.sh make release # Fully automated (no prompts at all) ./scripts/release.sh --auto ./scripts/release.sh release --auto make release-auto # Skip only confirmation ./scripts/release.sh --no-confirm # Skip only pull ./scripts/release.sh --no-pull # Kombinationen ./scripts/release.sh release --no-pull --no-confirm # Mit custom CalVer CALVER_PATTERN=%Y.%m ./scripts/release.sh --auto # Über Makefile make release-auto CALVER_PATTERN=%Y.%m ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,268 @@ #!/bin/bash set -e # Configuration RELEASE_BRANCH="${RELEASE_BRANCH:-main}" CALVER_PATTERN="${CALVER_PATTERN:-%Y.%m.%d}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Functions show_help() { cat << EOF Usage: $(basename "$0") [COMMAND] [OPTIONS] Commands: release Create a new release (default) next-tag Show what the next tag would be check-branch Check if current branch is correct check-changes Check if there are new merges since last tag help Show this help message Release Options: --no-pull Skip git pull --no-confirm Skip confirmation prompt --auto Equivalent to --no-confirm (pull, create, push without prompts) Environment Variables: RELEASE_BRANCH Branch from which releases are created (default: main) CALVER_PATTERN Date format for CalVer tags (default: %Y.%m.%d) Examples: %Y.%m.%d -> 2025.09.29 (default) %Y.%m -> 2025.09 %Y.%W -> 2025.39 (week number) v%Y.%m.%d -> v2025.09.29 Examples: $(basename "$0") # Interactive release process $(basename "$0") release --auto # Automated release (no prompts) $(basename "$0") release --no-confirm # Pull interactively, skip confirmation $(basename "$0") release --no-pull # Skip pull, confirm before push $(basename "$0") next-tag # See what tag would be created CALVER_PATTERN=%Y.%m $(basename "$0") --auto # Automated with custom pattern EOF } check_branch() { local current_branch=$(git rev-parse --abbrev-ref HEAD) if [ "$current_branch" != "$RELEASE_BRANCH" ]; then echo -e "${RED}Error: Releases can only be created from the '$RELEASE_BRANCH' branch.${NC}" echo "Current branch: $current_branch" return 1 fi echo -e "${GREEN}✓ On $RELEASE_BRANCH branch${NC}" return 0 } get_last_tag() { git describe --tags --abbrev=0 2>/dev/null || echo "" } calculate_next_tag() { local base_tag=$(date +"$CALVER_PATTERN") local existing_tags=$(git tag -l "$base_tag*" | sort -V) if [ -z "$existing_tags" ]; then echo "$base_tag" else local last_today=$(echo "$existing_tags" | tail -n 1) if [ "$last_today" = "$base_tag" ]; then echo "$base_tag.1" else local suffix=$(echo "$last_today" | sed "s/$(echo "$base_tag" | sed 's/\./\\./g')\.//") local next_suffix=$((suffix + 1)) echo "$base_tag.$next_suffix" fi fi } show_next_tag() { local last_tag=$(get_last_tag) local next_tag=$(calculate_next_tag) echo "Release branch: $RELEASE_BRANCH" echo "CalVer pattern: $CALVER_PATTERN" echo "Last tag: ${last_tag:-none}" echo "Next tag: $next_tag" } get_changelog() { local last_tag="$1" if [ -z "$last_tag" ]; then echo -e "${YELLOW}Warning: No previous tag found, showing all merge commits${NC}" >&2 git log --merges HEAD \ --pretty=format:"- %s" \ | sed -E 's/^Merge (pull request #[0-9]+ from [^ ]+ |branch .+ )?//' \ | head -n 20 else git log --merges "$last_tag"..HEAD \ --pretty=format:"- %s" \ | sed -E 's/^Merge (pull request #[0-9]+ from [^ ]+ |branch .+ )?//' fi } check_changes() { local last_tag=$(get_last_tag) local msg=$(get_changelog "$last_tag") echo "Release branch: $RELEASE_BRANCH" echo "CalVer pattern: $CALVER_PATTERN" echo "Last tag: ${last_tag:-none}" echo "" if [ -z "$msg" ]; then echo -e "${YELLOW}No new merges since $last_tag${NC}" return 1 else echo -e "${GREEN}Found new merges:${NC}" echo "$msg" return 0 fi } update_branch() { local skip_pull="$1" if [ "$skip_pull" = "true" ]; then echo "Skipping git pull (--no-pull)" return 0 fi read -p "Update $RELEASE_BRANCH branch (git pull)? [Y/n] " update_answer case $update_answer in [nN]*) echo "Branch will not be updated." ;; *) echo "Updating $RELEASE_BRANCH branch..." git pull ;; esac } create_release() { local skip_pull=false local skip_confirm=false # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --no-pull) skip_pull=true shift ;; --no-confirm|--auto) skip_confirm=true shift ;; *) echo -e "${RED}Error: Unknown option '$1'${NC}" show_help exit 1 ;; esac done # Check branch check_branch || exit 1 # Update branch if [ "$skip_pull" = "false" ]; then if [ "$skip_confirm" = "true" ]; then echo "Updating $RELEASE_BRANCH branch..." git pull else update_branch "$skip_pull" fi else echo "Skipping git pull" fi # Get tags local last_tag=$(get_last_tag) local new_tag=$(calculate_next_tag) echo "" echo "CalVer pattern: $CALVER_PATTERN" echo "Last tag: ${last_tag:-none}" echo "New tag: $new_tag" # Generate changelog local msg=$(get_changelog "$last_tag") if [ -z "$msg" ]; then echo -e "${RED}No new merges since $last_tag${NC}" exit 1 fi # Preview echo "" echo "Tag message preview:" echo "----------------------" echo "Release $new_tag" echo "" echo "$msg" echo "----------------------" echo "" # Confirmation if [ "$skip_confirm" = "true" ]; then echo "Creating and pushing tag automatically (--no-confirm)" git tag -a "$new_tag" -m "Release $new_tag"$'\n\n'"$msg" git push origin "$new_tag" echo -e "${GREEN}✓ Release $new_tag successfully created and pushed${NC}" else read -p "Really create and push tag? [y/N] " answer case $answer in [yY]*) git tag -a "$new_tag" -m "Release $new_tag"$'\n\n'"$msg" git push origin "$new_tag" echo -e "${GREEN}✓ Release $new_tag successfully created and pushed${NC}" ;; *) echo "Aborted." exit 1 ;; esac fi } # Main script logic COMMAND="${1:-release}" case $COMMAND in release) shift # Remove 'release' from arguments create_release "$@" ;; next-tag) show_next_tag ;; check-branch) check_branch ;; check-changes) check_changes ;; help|--help|-h) show_help ;; --*) # If first argument is an option, assume 'release' command create_release "$@" ;; *) echo -e "${RED}Error: Unknown command '$COMMAND'${NC}" echo "" show_help exit 1 ;; esac