217 lines
6.1 KiB
Bash
Executable File
217 lines
6.1 KiB
Bash
Executable File
# functions.sh
|
|
|
|
# _exit should be called from the main script only. If called from
|
|
# another function, it will not cause the main script to exit
|
|
_exit() {
|
|
local exit_code="$1"
|
|
local message="$2"
|
|
if [ "$exit_code" -ne 0 ]; then
|
|
echo -e "\nERROR: $message"
|
|
else
|
|
echo -e "\n$message"
|
|
fi
|
|
echo "Exiting script [exit_code=$exit_code]"
|
|
exit "$exit_code"
|
|
}
|
|
|
|
getTestDir() {
|
|
echo "/tmp"
|
|
}
|
|
|
|
getTestRepoName() {
|
|
echo "spring-modulith-temp-copy"
|
|
}
|
|
|
|
isBlank() {
|
|
[[ "$1" =~ ^[[:space:]]*$ ]]
|
|
}
|
|
|
|
isValidIssueNumber() {
|
|
local issue="$1"
|
|
# Check if the provided number matches an existing issue number
|
|
# Note: The issue status should be "open" (backporting is done before an issue is closed)
|
|
# But it is not necessary to filter on status - it is preferable not to constrain
|
|
if ! gh issue list --limit 10000 --state "all" --json number --jq '.[].number' | grep -x -q "^$issue$"; then
|
|
echo "The provided issue number [$issue] does not match an existing GitHub issue number"
|
|
# output value
|
|
false
|
|
else
|
|
echo "The provided issue number [$issue] matches an existing GitHub issue number"
|
|
# output value
|
|
true
|
|
fi
|
|
}
|
|
|
|
isValidVersionNumber() {
|
|
local version="$1"
|
|
# Check input format
|
|
local regex='^[0-9]+\.[0-9]+\.[0-9]+$'
|
|
if [[ "$version" =~ $regex ]]; then
|
|
echo "Version [$version] matches the required format"
|
|
# Check for branch
|
|
local targetBranch=$(getTargetBranch "$version")
|
|
local branch=$(git ls-remote --heads origin "$targetBranch")
|
|
if [[ -n "$branch" ]]; then
|
|
echo "Branch [$targetBranch] exists"
|
|
# Check for milestone
|
|
local targetMilestone=$(getTargetMilestone "$version")
|
|
local milestone=$(gh api repos/:owner/:repo/milestones --jq ".[] | select(.title == \"$targetMilestone\") | .title")
|
|
if [[ -n "$milestone" ]]; then
|
|
echo "Milestone [$targetMilestone] exists"
|
|
true
|
|
else
|
|
echo "Milestone [$targetMilestone] does not exist"
|
|
false
|
|
fi
|
|
else
|
|
echo "Branch [$targetBranch] does not exist"
|
|
false
|
|
fi
|
|
else
|
|
echo "Version [$version] does not match the required format [$regex]"
|
|
false
|
|
fi
|
|
}
|
|
|
|
getTargetBranch() {
|
|
local version="$1"
|
|
local targetBranch="$(echo $version | grep -oE '^[0-9]+\.[0-9]+').x"
|
|
echo "$targetBranch"
|
|
}
|
|
|
|
getTargetMilestone() {
|
|
local version="$1"
|
|
local targetMilestone="$version"
|
|
echo "$targetMilestone"
|
|
}
|
|
|
|
isDefaultBranch() {
|
|
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
local default_branch=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')
|
|
if [ "$current_branch" != "$default_branch" ]; then
|
|
echo "Current branch [$current_branch] is NOT the default branch [$default_branch]"
|
|
# output value
|
|
false
|
|
else
|
|
echo "Current branch [$current_branch] is the default branch"
|
|
# output value
|
|
true
|
|
fi
|
|
}
|
|
|
|
isCleanBranch() {
|
|
local branch=$(git symbolic-ref --short HEAD)
|
|
local remote_branch="origin/$branch"
|
|
|
|
# Check for ongoing cherry-pick
|
|
if [ -d .git/sequencer ]; then
|
|
echo "Error: Ongoing cherry-pick operation detected."
|
|
# return code
|
|
return 1
|
|
fi
|
|
|
|
# Check for uncommitted changes
|
|
if ! git diff-index --quiet HEAD --; then
|
|
echo "Error: Uncommitted changes in the working directory."
|
|
# return code
|
|
return 1
|
|
fi
|
|
|
|
# Check for untracked files and directories
|
|
if [ -n "$(git clean -fdn)" ]; then
|
|
echo "Error: Untracked files or directories present."
|
|
# return code
|
|
return 1
|
|
fi
|
|
|
|
# Fetch latest changes from the remote
|
|
git fetch origin &>/dev/null
|
|
|
|
# Check if local branch is ahead/behind the remote branch
|
|
local local_status=$(git rev-list --left-right --count ${branch}...${remote_branch})
|
|
local ahead=$(echo $local_status | awk '{print $1}')
|
|
local behind=$(echo $local_status | awk '{print $2}')
|
|
|
|
if [ "$ahead" -ne 0 ]; then
|
|
echo "Error: Local branch is ahead of the remote branch by $ahead commit(s)."
|
|
# return code
|
|
return 1
|
|
elif [ "$behind" -ne 0 ]; then
|
|
echo "Error: Local branch is behind the remote branch by $behind commit(s)."
|
|
# return code
|
|
return 1
|
|
fi
|
|
|
|
# If all checks pass
|
|
echo "Local branch matches the remote branch."
|
|
# return code
|
|
return 0
|
|
}
|
|
|
|
getGHCode() {
|
|
echo "GH-$1"
|
|
}
|
|
|
|
getIssueCandidatesForMilestone() {
|
|
local number="$1"
|
|
local milestone="$2"
|
|
|
|
local json=$(gh issue view "$number" --json=title,labels)
|
|
local title=$(echo "$json" | jq -r '.title')
|
|
local labels=$(echo "$json" | jq -r '.labels[].name' | paste -sd ',' -)
|
|
local body="Back-port of $(getGHCode $number)."
|
|
|
|
local targetCandidateNumbers=$(gh issue list --limit 10000 --state "open" --assignee "@me" --label "$labels" --milestone "$targetMilestone" --json number,title,body --jq '
|
|
.[] | select(.title == "'"$title"'" and (.body | contains("'"$body"'")) ) | .number')
|
|
echo "$targetCandidateNumbers"
|
|
}
|
|
|
|
createIssueForMilestone() {
|
|
local number="$1"
|
|
local milestone="$2"
|
|
|
|
local json=$(gh issue view "$number" --json=title,labels)
|
|
local title=$(echo "$json" | jq -r '.title')
|
|
local labels=$(echo "$json" | jq -r '.labels[].name' | paste -sd ',' -)
|
|
local body="Back-port of $(getGHCode $number)."
|
|
|
|
local targetNumber=$(gh issue create --assignee "@me" --label "$labels" --milestone "$targetMilestone" --title "$title" --body "$body" | awk -F '/' '{print $NF}')
|
|
echo "$targetNumber"
|
|
}
|
|
|
|
isCleanIssue() {
|
|
local targetNumber="$1"
|
|
local targetGh=$(getGHCode "$targetNumber")
|
|
|
|
# Check for commits mentioning the issue number
|
|
# $test_filter set globally in calling script
|
|
local commits
|
|
if [[ "$test_filter" == "" ]]; then
|
|
commits=$(git log --grep="\b$targetGh\b")
|
|
else
|
|
commits=$(git log --grep="\b$targetGh\b" "$test_filter")
|
|
fi
|
|
if [ -z "$commits" ]; then
|
|
# There are no commits that reference this issue
|
|
# output value
|
|
true
|
|
else
|
|
# output value
|
|
false
|
|
fi
|
|
}
|
|
|
|
updateCommitMessage() {
|
|
local source="$1"
|
|
local target="$2"
|
|
local message=$(git log -1 --pretty=format:"%B" | sed "s/$source/$target/g")
|
|
if [[ $(echo $message | grep "$target") != "" ]]; then
|
|
# Update commit message to refer to new ticket
|
|
git commit --amend -m "$message"
|
|
[ "$?" -eq 0 ] || return 1
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|