blob: 435334037f5473d9734dd9f4132aec627c37831a [file]
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
set -euo pipefail
set_value_or_error() {
local value="$1"
local default_value="$2"
local variable_name="$3"
if [[ -n "$value" ]]; then
decided_value="$value"
elif [[ -n "$default_value" ]]; then
echo "${variable_name}: Using default value: ${default_value}"
decided_value="$default_value"
else
echo "ERROR: A value for ${variable_name} is required." >&2
exit 1
fi
eval "export ${variable_name}=\"\$decided_value\""
}
echo "::group::Setup"
set_value_or_error "${GITHUB_WORKSPACE:-}" "." "GIT_SAFE_DIR"
set_value_or_error "${GIT_USER_NAME:-}" "${GITHUB_ACTOR:-github-actions}" "GIT_USER_NAME"
set_value_or_error "${SOURCE_BRANCH:-}" "${GITHUB_REF#refs/heads/}" "SOURCE_BRANCH"
set_value_or_error "${BRANCH_ORDER:-}" "" "BRANCH_ORDER"
git config --global --add safe.directory "${GIT_SAFE_DIR}"
git config --global user.email "${GIT_USER_NAME}@users.noreply.github.com"
git config --global user.name "${GIT_USER_NAME}"
git fetch origin --prune
echo "Source Branch: ${SOURCE_BRANCH}"
echo "Branch Order: ${BRANCH_ORDER}"
echo "::endgroup::"
normalized_branch_order="$(printf '%s\n' "${BRANCH_ORDER}" | tr ',\n' ' ')"
read -r -a branch_sequence <<< "${normalized_branch_order}"
if [[ ${#branch_sequence[@]} -eq 0 ]]; then
echo "ERROR: BRANCH_ORDER did not contain any branch names." >&2
exit 1
fi
source_index=-1
for i in "${!branch_sequence[@]}"; do
if [[ "${branch_sequence[$i]}" == "${SOURCE_BRANCH}" ]]; then
source_index=$i
break
fi
done
if [[ ${source_index} -lt 0 ]]; then
echo "SOURCE_BRANCH '${SOURCE_BRANCH}' was not found in BRANCH_ORDER. Nothing to merge."
exit 0
fi
if [[ ${source_index} -eq $((${#branch_sequence[@]} - 1)) ]]; then
echo "No downstream branches found after ${SOURCE_BRANCH}. Nothing to merge."
exit 0
fi
source_branch="${branch_sequence[$source_index]}"
target_branch="${branch_sequence[$((source_index + 1))]}"
if git rev-parse --verify --quiet "${source_branch}" >/dev/null; then
source_ref="${source_branch}"
else
source_ref="origin/${source_branch}"
fi
echo "::group::Merge ${source_branch} into ${target_branch}"
git checkout -B "${target_branch}" "origin/${target_branch}"
skip_merge_commits="$(git log --format='%H %s' "origin/${target_branch}..${source_ref}" | grep '\[skip merge\]' || true)"
if [[ -n "${skip_merge_commits}" ]]; then
echo "Commits marked with [skip merge] were found between ${source_branch} and ${target_branch}:" >&2
printf '%s\n' "${skip_merge_commits}" >&2
echo "ERROR: Manual merge required for ${source_branch} -> ${target_branch}." >&2
echo "::endgroup::"
exit 1
fi
if git merge --no-ff --no-edit -m "[skip ci] Merge ${source_branch} into ${target_branch}" "${source_ref}"; then
if git diff --quiet "origin/${target_branch}" HEAD; then
echo "${target_branch} is already up to date with ${source_branch}."
else
git push origin "${target_branch}"
echo "Merged ${source_branch} into ${target_branch}."
fi
else
git merge --abort || true
echo "ERROR: Merge conflict while merging ${source_branch} into ${target_branch}. Resolve manually." >&2
echo "::endgroup::"
exit 1
fi
echo "::endgroup::"