test: harden version entrypoint
This commit is contained in:
Executable
+321
@@ -0,0 +1,321 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
source "$ROOT_DIR/entrypoint.sh"
|
||||
|
||||
fail() {
|
||||
printf '[error] %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
assert_eq() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local label="$3"
|
||||
|
||||
if [ "$expected" != "$actual" ]; then
|
||||
fail "$label: expected '$expected', got '$actual'"
|
||||
fi
|
||||
}
|
||||
|
||||
make_mock_curl() {
|
||||
local bin_dir="$1"
|
||||
local response_file="$2"
|
||||
|
||||
cat >"$bin_dir/curl" <<'EOF'
|
||||
#!/bin/sh
|
||||
if [ "${FAKE_CURL_STATUS:-0}" != "0" ]; then
|
||||
exit "$FAKE_CURL_STATUS"
|
||||
fi
|
||||
|
||||
cat "${FAKE_CURL_RESPONSE_FILE:?}"
|
||||
EOF
|
||||
chmod +x "$bin_dir/curl"
|
||||
}
|
||||
|
||||
make_mock_jq() {
|
||||
local bin_dir="$1"
|
||||
|
||||
cat >"$bin_dir/jq" <<'EOF'
|
||||
#!/bin/sh
|
||||
is_beta=""
|
||||
query=""
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-r)
|
||||
shift
|
||||
;;
|
||||
--arg)
|
||||
if [ "$2" = "is_beta" ]; then
|
||||
is_beta="$3"
|
||||
fi
|
||||
shift 3
|
||||
;;
|
||||
*)
|
||||
query="$1"
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
python3 -c 'import json, sys
|
||||
query = sys.argv[1]
|
||||
is_beta = sys.argv[2]
|
||||
payload = sys.stdin.read()
|
||||
try:
|
||||
data = json.loads(payload)
|
||||
except Exception:
|
||||
sys.exit(4)
|
||||
|
||||
def next_version(latest):
|
||||
parts = [int(p or 0) for p in latest.split(".")]
|
||||
while len(parts) < 3:
|
||||
parts.append(0)
|
||||
major, minor, patch = parts[:3]
|
||||
patch += 1
|
||||
if patch >= 10:
|
||||
patch = 0
|
||||
minor += 1
|
||||
if minor >= 10:
|
||||
minor = 0
|
||||
major += 1
|
||||
return f"{major}.{minor}.{patch}"
|
||||
|
||||
def beta_max(data, prefix):
|
||||
values = []
|
||||
for item in data:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
tag = item.get("tag_name")
|
||||
if isinstance(tag, str) and tag.startswith(prefix):
|
||||
suffix = tag[len(prefix):]
|
||||
try:
|
||||
values.append(int(suffix))
|
||||
except Exception:
|
||||
pass
|
||||
return max(values) if values else 0
|
||||
|
||||
if not isinstance(data, list):
|
||||
base = "0.0.0"
|
||||
else:
|
||||
base = "0.0.0"
|
||||
for item in data:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
tag = item.get("tag_name")
|
||||
if isinstance(tag, str) and "-beta." not in tag:
|
||||
base = tag[1:] if tag.startswith("v") else tag
|
||||
break
|
||||
|
||||
next_ver = next_version(base)
|
||||
if is_beta == "true":
|
||||
beta = beta_max(data, f"v{next_ver}-beta.") + 1
|
||||
sys.stdout.write(f"{base}\t{next_ver}-beta.{beta}")
|
||||
else:
|
||||
sys.stdout.write(f"{base}\t{next_ver}")
|
||||
' "$query" "$is_beta"
|
||||
EOF
|
||||
chmod +x "$bin_dir/jq"
|
||||
}
|
||||
|
||||
run_entrypoint() {
|
||||
local response_file="$1"
|
||||
local is_beta="$2"
|
||||
local token="${3:-}"
|
||||
local fake_status="${4:-0}"
|
||||
local workdir
|
||||
local output_file
|
||||
local bin_dir
|
||||
local stdout_file
|
||||
local stderr_file
|
||||
|
||||
workdir="$(mktemp -d)"
|
||||
bin_dir="$workdir/bin"
|
||||
mkdir -p "$bin_dir"
|
||||
make_mock_curl "$bin_dir" "$response_file"
|
||||
make_mock_jq "$bin_dir"
|
||||
|
||||
output_file="$workdir/github_output"
|
||||
stdout_file="$workdir/stdout"
|
||||
stderr_file="$workdir/stderr"
|
||||
|
||||
if [ -n "$token" ]; then
|
||||
FAKE_CURL_STATUS="$fake_status" \
|
||||
FAKE_CURL_RESPONSE_FILE="$response_file" \
|
||||
PATH="$bin_dir:$PATH" \
|
||||
GITEA_SERVER_URL="https://gitea.example.com" \
|
||||
GITEA_REPOSITORY="org/repo" \
|
||||
RUNNER_TOKEN="$token" \
|
||||
IS_BETA="$is_beta" \
|
||||
GITHUB_OUTPUT="$output_file" \
|
||||
bash "$ROOT_DIR/entrypoint.sh" >"$stdout_file" 2>"$stderr_file"
|
||||
else
|
||||
FAKE_CURL_STATUS="$fake_status" \
|
||||
FAKE_CURL_RESPONSE_FILE="$response_file" \
|
||||
PATH="$bin_dir:$PATH" \
|
||||
GITEA_SERVER_URL="https://gitea.example.com" \
|
||||
GITEA_REPOSITORY="org/repo" \
|
||||
IS_BETA="$is_beta" \
|
||||
GITHUB_OUTPUT="$output_file" \
|
||||
bash "$ROOT_DIR/entrypoint.sh" >"$stdout_file" 2>"$stderr_file"
|
||||
fi
|
||||
|
||||
printf '%s\n' "$output_file"
|
||||
}
|
||||
|
||||
test_unit_helpers() {
|
||||
assert_eq "false" "$(normalize_beta_flag "")" "normalize_beta_flag empty"
|
||||
assert_eq "false" "$(normalize_beta_flag "null")" "normalize_beta_flag null"
|
||||
assert_eq "true" "$(normalize_beta_flag "true")" "normalize_beta_flag true"
|
||||
assert_eq "0.1.0" "$(next_release_version "0.0.9")" "next_release_version carry patch"
|
||||
assert_eq "2.0.0" "$(next_release_version "1.9.9")" "next_release_version carry minor"
|
||||
}
|
||||
|
||||
test_stable_release_flow() {
|
||||
local response_file
|
||||
local output_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
cat >"$response_file" <<'EOF'
|
||||
[
|
||||
{"tag_name":"v1.2.3-beta.1"},
|
||||
{"tag_name":"v1.2.3"},
|
||||
{"tag_name":"v1.2.4-beta.1"}
|
||||
]
|
||||
EOF
|
||||
|
||||
output_file="$(run_entrypoint "$response_file" "false")"
|
||||
assert_eq "version=1.2.4" "$(cat "$output_file")" "stable release output"
|
||||
}
|
||||
|
||||
test_beta_release_flow() {
|
||||
local response_file
|
||||
local output_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
cat >"$response_file" <<'EOF'
|
||||
[
|
||||
{"tag_name":"v1.2.3"},
|
||||
{"tag_name":"v1.2.4-beta.1"},
|
||||
{"tag_name":"v1.2.4-beta.3"}
|
||||
]
|
||||
EOF
|
||||
|
||||
output_file="$(run_entrypoint "$response_file" "true")"
|
||||
assert_eq "version=1.2.4-beta.4" "$(cat "$output_file")" "beta release output"
|
||||
}
|
||||
|
||||
test_empty_release_list() {
|
||||
local response_file
|
||||
local output_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
printf '%s\n' '[]' >"$response_file"
|
||||
|
||||
output_file="$(run_entrypoint "$response_file" "false")"
|
||||
assert_eq "version=0.0.1" "$(cat "$output_file")" "empty release list"
|
||||
}
|
||||
|
||||
test_only_beta_releases() {
|
||||
local response_file
|
||||
local output_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
cat >"$response_file" <<'EOF'
|
||||
[
|
||||
{"tag_name":"v2.4.6-beta.1"},
|
||||
{"tag_name":"v2.4.6-beta.2"}
|
||||
]
|
||||
EOF
|
||||
|
||||
output_file="$(run_entrypoint "$response_file" "false")"
|
||||
assert_eq "version=0.0.1" "$(cat "$output_file")" "only beta releases"
|
||||
}
|
||||
|
||||
test_null_release_payload() {
|
||||
local response_file
|
||||
local output_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
printf '%s\n' 'null' >"$response_file"
|
||||
|
||||
output_file="$(run_entrypoint "$response_file" "false")"
|
||||
assert_eq "version=0.0.1" "$(cat "$output_file")" "null release payload"
|
||||
}
|
||||
|
||||
test_malformed_release_payload() {
|
||||
local response_file
|
||||
local workdir
|
||||
local bin_dir
|
||||
local output_file
|
||||
local stdout_file
|
||||
local stderr_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
printf '%s\n' '{' >"$response_file"
|
||||
workdir="$(mktemp -d)"
|
||||
bin_dir="$workdir/bin"
|
||||
mkdir -p "$bin_dir"
|
||||
make_mock_curl "$bin_dir" "$response_file"
|
||||
make_mock_jq "$bin_dir"
|
||||
output_file="$workdir/github_output"
|
||||
stdout_file="$workdir/stdout"
|
||||
stderr_file="$workdir/stderr"
|
||||
|
||||
if FAKE_CURL_STATUS=0 \
|
||||
FAKE_CURL_RESPONSE_FILE="$response_file" \
|
||||
PATH="$bin_dir:$PATH" \
|
||||
GITEA_SERVER_URL="https://gitea.example.com" \
|
||||
GITEA_REPOSITORY="org/repo" \
|
||||
IS_BETA="false" \
|
||||
GITHUB_OUTPUT="$output_file" \
|
||||
bash "$ROOT_DIR/entrypoint.sh" >"$stdout_file" 2>"$stderr_file"; then
|
||||
fail "malformed release payload: expected failure"
|
||||
fi
|
||||
}
|
||||
|
||||
test_curl_failure() {
|
||||
local response_file
|
||||
local workdir
|
||||
local bin_dir
|
||||
local output_file
|
||||
local stdout_file
|
||||
local stderr_file
|
||||
|
||||
response_file="$(mktemp)"
|
||||
printf '%s\n' '[]' >"$response_file"
|
||||
workdir="$(mktemp -d)"
|
||||
bin_dir="$workdir/bin"
|
||||
mkdir -p "$bin_dir"
|
||||
make_mock_curl "$bin_dir" "$response_file"
|
||||
output_file="$workdir/github_output"
|
||||
stdout_file="$workdir/stdout"
|
||||
stderr_file="$workdir/stderr"
|
||||
|
||||
if FAKE_CURL_STATUS=22 \
|
||||
FAKE_CURL_RESPONSE_FILE="$response_file" \
|
||||
PATH="$bin_dir:$PATH" \
|
||||
GITEA_SERVER_URL="https://gitea.example.com" \
|
||||
GITEA_REPOSITORY="org/repo" \
|
||||
IS_BETA="false" \
|
||||
GITHUB_OUTPUT="$output_file" \
|
||||
bash "$ROOT_DIR/entrypoint.sh" >"$stdout_file" 2>"$stderr_file"; then
|
||||
fail "curl failure: expected failure"
|
||||
fi
|
||||
}
|
||||
|
||||
test_unit_helpers
|
||||
test_stable_release_flow
|
||||
test_beta_release_flow
|
||||
test_empty_release_list
|
||||
test_only_beta_releases
|
||||
test_null_release_payload
|
||||
test_malformed_release_payload
|
||||
test_curl_failure
|
||||
|
||||
printf '[info] all tests passed\n'
|
||||
Reference in New Issue
Block a user