Files
Genarrative/scripts/jenkins-checkout-source.sh

106 lines
3.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
SOURCE_BRANCH="${SOURCE_BRANCH:-master}"
COMMIT_HASH="${COMMIT_HASH:-}"
GIT_REMOTE_URL="${GIT_REMOTE_URL:-}"
GIT_REMOTE_FALLBACK_URL="${GIT_REMOTE_FALLBACK_URL:-}"
SOURCE_COMMIT_FILE="${SOURCE_COMMIT_FILE:-.jenkins-source-commit}"
# Windows PowerShell 5.1 的 UTF-8 输出可能带 BOM下游参数校验前先剥离不可见字节。
SOURCE_BRANCH="$(printf "%s" "${SOURCE_BRANCH}" | sed $'s/^\xef\xbb\xbf//' | tr -d '\r\n')"
COMMIT_HASH="$(printf "%s" "${COMMIT_HASH}" | sed $'s/^\xef\xbb\xbf//' | tr -d '\r\n')"
GIT_REMOTE_URL="$(printf "%s" "${GIT_REMOTE_URL}" | sed $'s/^\xef\xbb\xbf//' | tr -d '\r\n')"
GIT_REMOTE_FALLBACK_URL="$(printf "%s" "${GIT_REMOTE_FALLBACK_URL}" | sed $'s/^\xef\xbb\xbf//' | tr -d '\r\n')"
if [[ ! "${SOURCE_BRANCH}" =~ ^[0-9A-Za-z._/-]+$ ]]; then
echo "[jenkins-checkout-source] SOURCE_BRANCH 只能包含数字、字母、点、下划线、短横线和斜杠: ${SOURCE_BRANCH}" >&2
exit 1
fi
if [[ "${SOURCE_BRANCH}" == /* || "${SOURCE_BRANCH}" == */ || "${SOURCE_BRANCH}" == *..* ]]; then
echo "[jenkins-checkout-source] SOURCE_BRANCH 不能以斜杠开头/结尾,也不能包含连续点号: ${SOURCE_BRANCH}" >&2
exit 1
fi
if [[ -n "${COMMIT_HASH}" && ! "${COMMIT_HASH}" =~ ^[0-9a-fA-F]{7,40}$ ]]; then
echo "[jenkins-checkout-source] COMMIT_HASH 只能填写 7 到 40 位十六进制 Git commit hash: ${COMMIT_HASH}" >&2
exit 1
fi
GIT_REMOTE_CANDIDATES=()
add_git_remote_candidate() {
local candidate="$1"
local existing
if [[ -z "${candidate}" ]]; then
return
fi
for existing in "${GIT_REMOTE_CANDIDATES[@]}"; do
if [[ "${existing}" == "${candidate}" ]]; then
return
fi
done
GIT_REMOTE_CANDIDATES+=("${candidate}")
}
fetch_source_branch() {
local remote_url="$1"
if [[ -n "${remote_url}" ]]; then
git remote set-url origin "${remote_url}"
fi
echo "[jenkins-checkout-source] 尝试 Git 远端: ${remote_url:-origin}"
if [[ -z "${COMMIT_HASH}" ]]; then
git fetch --no-tags --prune --depth=1 origin "+refs/heads/${SOURCE_BRANCH}:refs/remotes/origin/${SOURCE_BRANCH}"
else
git fetch --no-tags --prune origin "+refs/heads/${SOURCE_BRANCH}:refs/remotes/origin/${SOURCE_BRANCH}"
fi
}
add_git_remote_candidate "${GIT_REMOTE_URL}"
add_git_remote_candidate "${GIT_REMOTE_FALLBACK_URL}"
git reset --hard HEAD
if [[ "${#GIT_REMOTE_CANDIDATES[@]}" -eq 0 ]]; then
fetch_source_branch ""
else
fetch_ok=0
for git_remote_candidate in "${GIT_REMOTE_CANDIDATES[@]}"; do
if fetch_source_branch "${git_remote_candidate}"; then
GIT_REMOTE_URL="${git_remote_candidate}"
fetch_ok=1
break
fi
echo "[jenkins-checkout-source] Git 远端拉取失败: ${git_remote_candidate}" >&2
done
if [[ "${fetch_ok}" -ne 1 ]]; then
echo "[jenkins-checkout-source] 所有 Git 远端均拉取失败。" >&2
exit 1
fi
fi
if [[ -n "${COMMIT_HASH}" && "$(git rev-parse --is-shallow-repository 2>/dev/null || echo false)" == "true" ]]; then
git fetch --unshallow --no-tags origin "+refs/heads/${SOURCE_BRANCH}:refs/remotes/origin/${SOURCE_BRANCH}" || true
fi
git cat-file -e "refs/remotes/origin/${SOURCE_BRANCH}^{commit}"
if [[ -n "${COMMIT_HASH}" ]]; then
git cat-file -e "${COMMIT_HASH}^{commit}"
RESOLVED_COMMIT="$(git rev-parse "${COMMIT_HASH}^{commit}")"
if ! git merge-base --is-ancestor "${RESOLVED_COMMIT}" "refs/remotes/origin/${SOURCE_BRANCH}"; then
echo "[jenkins-checkout-source] 指定 commit 不属于 origin/${SOURCE_BRANCH}: ${RESOLVED_COMMIT}" >&2
exit 1
fi
else
RESOLVED_COMMIT="$(git rev-parse "refs/remotes/origin/${SOURCE_BRANCH}^{commit}")"
fi
git checkout --detach "${RESOLVED_COMMIT}"
git reset --hard HEAD
git clean -fd
printf "%s\n" "${RESOLVED_COMMIT}" >"${SOURCE_COMMIT_FILE}"
echo "[jenkins-checkout-source] 使用源码: branch=${SOURCE_BRANCH} commit=${RESOLVED_COMMIT} remote=${GIT_REMOTE_URL:-origin}"