266 lines
6.9 KiB
Bash
266 lines
6.9 KiB
Bash
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
readonly LINE="=================================================="
|
|
readonly SUBLINE="--------------------------------------------------"
|
|
readonly RELEASES_PER_PAGE=10
|
|
|
|
section() {
|
|
printf '\n%s\n%s\n%s\n' "$LINE" "$1" "$SUBLINE"
|
|
}
|
|
|
|
info() {
|
|
printf '[info] %s\n' "$1"
|
|
}
|
|
|
|
fail() {
|
|
printf '[error] %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
require_env() {
|
|
local name="$1"
|
|
local value="$2"
|
|
|
|
if [ -z "$value" ] || [ "$value" = "null" ]; then
|
|
fail "$name 未設定"
|
|
fi
|
|
|
|
printf '%s=%s\n' "$name" "$value"
|
|
}
|
|
|
|
write_output() {
|
|
printf 'version=%s\n' "$1" >> "$GITHUB_OUTPUT"
|
|
}
|
|
|
|
normalize_beta_flag() {
|
|
local value="${1:-false}"
|
|
|
|
if [ -z "$value" ] || [ "$value" = "null" ]; then
|
|
printf '%s\n' "false"
|
|
return
|
|
fi
|
|
|
|
printf '%s\n' "$value"
|
|
}
|
|
|
|
latest_stable_version() {
|
|
local release_json="$1"
|
|
|
|
if [ -z "$release_json" ] || [ "$release_json" = "null" ]; then
|
|
printf '%s\n' "0.0.0"
|
|
return
|
|
fi
|
|
|
|
printf '%s' "$release_json" | jq -r '
|
|
( if type == "array" then . else [] end )
|
|
| [ .[]
|
|
| select(.tag_name? and (.tag_name | test("-beta\\.") | not))
|
|
| .tag_name
|
|
| sub("^v"; "")
|
|
| select(test("^[0-9]+(\\.[0-9]+)*$"))
|
|
| split(".")
|
|
| map(tonumber)
|
|
]
|
|
| if length == 0 then [0, 0, 0] else (sort | last) end
|
|
| "\(.[0] // 0).\(.[1] // 0).\(.[2] // 0)"
|
|
'
|
|
}
|
|
|
|
next_release_version() {
|
|
local latest_version="$1"
|
|
local major minor patch
|
|
|
|
IFS='.' read -r major minor patch <<< "$latest_version"
|
|
major="${major:-0}"
|
|
minor="${minor:-0}"
|
|
patch="${patch:-0}"
|
|
|
|
patch=$((patch + 1))
|
|
if [ "$patch" -ge 10 ]; then
|
|
patch=0
|
|
minor=$((minor + 1))
|
|
fi
|
|
|
|
if [ "$minor" -ge 10 ]; then
|
|
minor=0
|
|
major=$((major + 1))
|
|
fi
|
|
|
|
printf '%s.%s.%s\n' "$major" "$minor" "$patch"
|
|
}
|
|
|
|
next_beta_number() {
|
|
local release_json="$1"
|
|
local version="$2"
|
|
|
|
if [ -z "$release_json" ] || [ "$release_json" = "null" ]; then
|
|
printf '%s\n' "1"
|
|
return
|
|
fi
|
|
|
|
printf '%s' "$release_json" | jq -r --arg prefix "v${version}-beta." '
|
|
if type == "array" then
|
|
[ .[]
|
|
| select(.tag_name? and (.tag_name | startswith($prefix)))
|
|
| .tag_name
|
|
| ltrimstr($prefix)
|
|
| try tonumber catch empty
|
|
] | if length > 0 then max else 0 end
|
|
else
|
|
0
|
|
end
|
|
' | awk '{print $1 + 1}'
|
|
}
|
|
|
|
calculate_version() {
|
|
local release_json="$1"
|
|
local is_beta="$2"
|
|
|
|
if [ -z "$release_json" ] || [ "$release_json" = "null" ]; then
|
|
if [ "$is_beta" = "true" ]; then
|
|
printf '%s\t%s\n' "0.0.0" "0.0.1-beta.1"
|
|
else
|
|
printf '%s\t%s\n' "0.0.0" "0.0.1"
|
|
fi
|
|
return
|
|
fi
|
|
|
|
printf '%s' "$release_json" | jq -r --arg is_beta "$is_beta" '
|
|
def stable_version:
|
|
( if type == "array" then . else [] end )
|
|
| [ .[]
|
|
| select(.tag_name? and (.tag_name | test("-beta\\.") | not))
|
|
| .tag_name
|
|
| sub("^v"; "")
|
|
| select(test("^[0-9]+(\\.[0-9]+)*$"))
|
|
| split(".")
|
|
| map(tonumber)
|
|
]
|
|
| if length == 0 then [0, 0, 0] else (sort | last) end
|
|
| "\(.[0] // 0).\(.[1] // 0).\(.[2] // 0)";
|
|
|
|
def next_release($latest):
|
|
($latest | split(".") | map(tonumber? // 0)) as $parts
|
|
| ($parts[0] // 0) as $major
|
|
| ($parts[1] // 0) as $minor
|
|
| ($parts[2] // 0) as $patch
|
|
| ($patch + 1) as $next_patch
|
|
| if $next_patch >= 10 then
|
|
if ($minor + 1) >= 10 then
|
|
"\(($major + 1)).0.0"
|
|
else
|
|
"\($major).\($minor + 1).0"
|
|
end
|
|
else
|
|
"\($major).\($minor).\($next_patch)"
|
|
end;
|
|
|
|
def beta_max($prefix):
|
|
[ .[]
|
|
| select(.tag_name? and (.tag_name | startswith($prefix)))
|
|
| .tag_name
|
|
| ltrimstr($prefix)
|
|
| try tonumber catch empty
|
|
] | if length > 0 then max else 0 end;
|
|
|
|
(stable_version) as $base
|
|
| (next_release($base)) as $next
|
|
| if $is_beta == "true" then
|
|
$base + "\t" + ($next + "-beta." + ((beta_max("v" + $next + "-beta.") + 1) | tostring))
|
|
else
|
|
$base + "\t" + $next
|
|
end
|
|
'
|
|
}
|
|
|
|
fetch_releases() {
|
|
local base_url="$1"
|
|
local -a auth_args=()
|
|
|
|
if [ -n "${GITEA_TOKEN:-}" ] && [ "${GITEA_TOKEN:-}" != "null" ]; then
|
|
info "使用授權 token 取得 release" >&2
|
|
auth_args=(-H "Authorization: token $GITEA_TOKEN")
|
|
else
|
|
info "使用匿名請求取得 release" >&2
|
|
fi
|
|
|
|
local page=1
|
|
local combined="[]"
|
|
local page_json count
|
|
|
|
while :; do
|
|
if ! page_json="$(curl -fsS ${auth_args[@]+"${auth_args[@]}"} "${base_url}?limit=${RELEASES_PER_PAGE}&page=${page}")"; then
|
|
fail "release API 請求失敗 (page=${page})"
|
|
fi
|
|
|
|
# 空字串或 null 代表已無更多資料
|
|
if [ -z "$page_json" ] || [ "$page_json" = "null" ]; then
|
|
break
|
|
fi
|
|
|
|
if ! count="$(printf '%s' "$page_json" | jq 'if type == "array" then length else -1 end')"; then
|
|
fail "release API 回傳資料無法解析 (page=${page})"
|
|
fi
|
|
|
|
if [ "$count" = "-1" ]; then
|
|
fail "release API 回傳非陣列資料 (page=${page})"
|
|
fi
|
|
|
|
info "第 ${page} 頁取得 ${count} 筆 release" >&2
|
|
|
|
if ! combined="$(jq -n --argjson acc "$combined" --argjson page "$page_json" '$acc + $page')"; then
|
|
fail "合併 release 資料失敗 (page=${page})"
|
|
fi
|
|
|
|
# 不足一頁代表已取完
|
|
if [ "$count" -lt "$RELEASES_PER_PAGE" ]; then
|
|
break
|
|
fi
|
|
|
|
page=$((page + 1))
|
|
done
|
|
|
|
printf '%s' "$combined"
|
|
}
|
|
|
|
main() {
|
|
section "參數檢查"
|
|
|
|
require_env "GITEA_SERVER_URL" "${GITEA_SERVER_URL:-}"
|
|
require_env "GITEA_REPOSITORY" "${GITEA_REPOSITORY:-}"
|
|
|
|
if [ -n "${GITEA_TOKEN:-}" ] && [ "${GITEA_TOKEN:-}" != "null" ]; then
|
|
info "GITEA_TOKEN=***"
|
|
else
|
|
info "GITEA_TOKEN=未提供"
|
|
fi
|
|
|
|
IS_BETA="$(normalize_beta_flag "${IS_BETA:-false}")"
|
|
info "IS_BETA=$IS_BETA"
|
|
|
|
section "取得版本資料"
|
|
|
|
RELEASE_URL="$GITEA_SERVER_URL/api/v1/repos/$GITEA_REPOSITORY/releases"
|
|
info "RELEASE_URL=$RELEASE_URL"
|
|
|
|
if ! RELEASE_JSON="$(fetch_releases "$RELEASE_URL")"; then
|
|
fail "取得 release 資料失敗"
|
|
fi
|
|
|
|
VERSION_INFO="$(calculate_version "$RELEASE_JSON" "$IS_BETA")"
|
|
IFS=$'\t' read -r LATEST_TAG NEW_VERSION <<< "$VERSION_INFO"
|
|
|
|
info "LATEST_VERSION=$LATEST_TAG"
|
|
|
|
section "計算版本號"
|
|
|
|
info "NEW_VERSION=$NEW_VERSION"
|
|
write_output "$NEW_VERSION"
|
|
}
|
|
|
|
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
main "$@"
|
|
fi
|