fix(framework): durable Gitea comment posting in pr-review.sh via REST + read-back verify (#812) (#852)
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

This commit was merged in pull request #852.
This commit is contained in:
2026-07-20 06:45:48 +00:00
parent 77c9a82614
commit aa999daf1b
5 changed files with 564 additions and 7 deletions

View File

@@ -81,7 +81,26 @@ get_repo_slug() {
gitea_url_matches_host() {
local url="${1:-}" host="${2:-}"
[[ -n "$url" && -n "$host" ]] || return 1
[[ "${url%/}" == "https://$host" || "${url%/}" == "http://$host" || "${url%/}" == *"//$host" ]]
python3 - "$url" "$host" <<'PY'
import sys
from urllib.parse import urlparse
url, remote_host = sys.argv[1:]
configured = urlparse(url)
remote = urlparse(f"//{remote_host}")
if configured.scheme not in {"http", "https"} or configured.hostname != remote.hostname:
raise SystemExit(1)
configured_port = configured.port
remote_port = remote.port
if remote_port is None:
default_port = 80 if configured.scheme == "http" else 443
if configured_port not in {None, default_port}:
raise SystemExit(1)
elif configured_port != remote_port:
raise SystemExit(1)
raise SystemExit(0)
PY
}
get_gitea_service_for_host() {
@@ -347,6 +366,47 @@ get_gitea_api_host_for_repo_override() {
get_host_from_url "${GITEA_URL:-}"
}
# Resolve owner/repo relative to a configured Gitea base URL. HTTP(S) clone
# URLs can include the deployment prefix (for example /gitea/owner/repo.git),
# but Gitea's /repos API expects only owner/repo. Root-mounted and SSH clone
# forms retain their existing owner/repo behavior.
get_gitea_repo_slug_for_url() {
local configured_url="$1" remote_url
remote_url=$(git remote get-url origin 2>/dev/null) || return 1
if [[ "$remote_url" =~ ^https?:// ]]; then
python3 - "$remote_url" "$configured_url" <<'PY'
import sys
from urllib.parse import urlparse
remote = urlparse(sys.argv[1])
base = urlparse(sys.argv[2])
remote_path = remote.path.strip("/")
if remote_path.endswith(".git"):
remote_path = remote_path[:-4]
base_path = base.path.strip("/")
remote_parts = [part for part in remote_path.split("/") if part]
base_parts = [part for part in base_path.split("/") if part]
if base_parts and remote_parts[:len(base_parts)] == base_parts:
repo_parts = remote_parts[len(base_parts):]
elif len(remote_parts) == 2:
# Preserve a root-shaped clone URL when provider API configuration carries
# a reverse-proxy prefix separately.
repo_parts = remote_parts
else:
raise SystemExit(1)
if len(repo_parts) != 2:
raise SystemExit(1)
print("/".join(repo_parts))
PY
return
fi
get_repo_slug
}
get_gitea_repo_args() {
local repo host login
repo=$(get_repo_slug) || return 1
@@ -370,6 +430,11 @@ get_remote_host() {
echo "${host##*@}"
return 0
fi
if [[ "$remote_url" =~ ^ssh://([^/]+)/ ]]; then
local host="${BASH_REMATCH[1]}"
echo "${host##*@}"
return 0
fi
if [[ "$remote_url" =~ ^git@([^:]+): ]]; then
echo "${BASH_REMATCH[1]}"
return 0
@@ -377,6 +442,51 @@ get_remote_host() {
return 1
}
# Resolve the configured Gitea base URL for a host from the same credential
# source used by get_gitea_token. The scheme and any deployment path prefix are
# provider configuration and must not be reconstructed from the git remote.
get_gitea_url_for_host() {
local host="$1" script_dir cred_loader url
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cred_loader="$script_dir/../_lib/credentials.sh"
if [[ -f "$cred_loader" ]]; then
url=$(
# shellcheck source=/dev/null
source "$cred_loader"
unset GITEA_TOKEN GITEA_URL
case "$host" in
git.mosaicstack.dev) load_credentials gitea-mosaicstack 2>/dev/null ;;
git.uscllc.com) load_credentials gitea-usc 2>/dev/null ;;
*)
for svc in gitea-mosaicstack gitea-usc; do
unset GITEA_TOKEN GITEA_URL
load_credentials "$svc" 2>/dev/null || continue
if gitea_url_matches_host "${GITEA_URL:-}" "$host"; then
break
fi
unset GITEA_TOKEN GITEA_URL
done
;;
esac
if gitea_url_matches_host "${GITEA_URL:-}" "$host"; then
printf '%s' "${GITEA_URL%/}"
fi
)
if [[ -n "$url" ]]; then
printf '%s\n' "$url"
return 0
fi
fi
if gitea_url_matches_host "${GITEA_URL:-}" "$host"; then
printf '%s\n' "${GITEA_URL%/}"
return 0
fi
return 1
}
# Resolve a Gitea API token for the given host.
# Priority: Mosaic credential loader → GITEA_TOKEN env → ~/.git-credentials
get_gitea_token() {
@@ -403,7 +513,7 @@ get_gitea_token() {
for svc in gitea-mosaicstack gitea-usc; do
unset GITEA_TOKEN GITEA_URL
load_credentials "$svc" 2>/dev/null || continue
if [[ "${GITEA_URL:-}" == "https://$host" || "${GITEA_URL:-}" == "http://$host" || "${GITEA_URL:-}" == *"//$host" ]]; then
if gitea_url_matches_host "${GITEA_URL:-}" "$host"; then
matched=true
break
fi
@@ -423,7 +533,7 @@ get_gitea_token() {
# 2. GITEA_TOKEN env var (only when GITEA_URL, if present, matches the remote host)
if [[ -n "${GITEA_TOKEN:-}" ]]; then
if [[ -z "${GITEA_URL:-}" || "${GITEA_URL:-}" == "https://$host" || "${GITEA_URL:-}" == "http://$host" || "${GITEA_URL:-}" == *"//$host" ]]; then
if [[ -z "${GITEA_URL:-}" ]] || gitea_url_matches_host "$GITEA_URL" "$host"; then
echo "$GITEA_TOKEN"
return 0
fi