Breaking change. The monorepo's gitea host was previously inferred from the first target's subrepo_url, silently coupling the two and breaking on any multi-host setup (monorepo on host A, target on host B). v2.0.0 replaces the inference with a required josh.monorepo_url field that mirrors subrepo_url — same parsing, same SSH/HTTPS auth options, same shape. - schema_version: 2 is now required; v1 configs are rejected with a clear migration error - josh.monorepo_url is required; josh.monorepo_auth is optional (default https) - mono_auth_url() in lib/auth.sh mirrors subrepo_auth_url() - MONOREPO_API derives from monorepo_url's host instead of .[0].gitea_host; env-var override preserved as escape hatch - initial_import() and force-push call mono_auth_url() instead of building URLs inline - ADR-012 documents the rationale; CHANGELOG includes migration snippet Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
116 lines
4.7 KiB
Bash
116 lines
4.7 KiB
Bash
#!/usr/bin/env bash
|
|
# lib/auth.sh — Authenticated URLs, remote queries, and PR creation
|
|
#
|
|
# Requires: lib/core.sh and lib/config.sh sourced first
|
|
# Expects: JOSH_PROXY_URL, MONOREPO_PATH, MONOREPO_URL, MONOREPO_AUTH,
|
|
# BOT_USER, GITEA_TOKEN, JOSH_FILTER,
|
|
# SUBREPO_URL, SUBREPO_AUTH, SUBREPO_TOKEN (set by parse_config + load_target)
|
|
|
|
# ─── Josh-Proxy Auth URL ───────────────────────────────────────────
|
|
# Josh always uses HTTPS. Filter is embedded in the URL path.
|
|
# Result: https://user:token@proxy/org/repo.git:/services/app.git
|
|
|
|
josh_auth_url() {
|
|
local base="${JOSH_PROXY_URL}/${MONOREPO_PATH}.git${JOSH_FILTER}.git"
|
|
# shellcheck disable=SC2001 # sed is clearer than ${var//} for URL injection
|
|
echo "$base" | sed "s|https://|https://${BOT_USER}:${GITEA_TOKEN}@|"
|
|
}
|
|
|
|
# ─── Subrepo Auth URL ──────────────────────────────────────────────
|
|
# HTTPS: injects user:token into URL
|
|
# SSH: returns bare URL (auth via GIT_SSH_COMMAND set by load_target)
|
|
|
|
subrepo_auth_url() {
|
|
if [ "${SUBREPO_AUTH:-https}" = "ssh" ]; then
|
|
echo "$SUBREPO_URL"
|
|
else
|
|
# shellcheck disable=SC2001
|
|
echo "$SUBREPO_URL" | sed "s|https://|https://${BOT_USER}:${SUBREPO_TOKEN}@|"
|
|
fi
|
|
}
|
|
|
|
# ─── Monorepo Auth URL ─────────────────────────────────────────────
|
|
# HTTPS: injects user:token into MONOREPO_URL (auto-converts git@ form to https)
|
|
# SSH: returns bare MONOREPO_URL (auth via user's ssh-agent / ~/.ssh/config,
|
|
# or via GIT_SSH_COMMAND if the caller wired one up for the monorepo host)
|
|
|
|
mono_auth_url() {
|
|
if [ "${MONOREPO_AUTH:-https}" = "ssh" ]; then
|
|
echo "$MONOREPO_URL"
|
|
else
|
|
local https_url="$MONOREPO_URL"
|
|
# Convert git@host:org/repo.git → https://host/org/repo.git so token injection works
|
|
if [[ "$https_url" == git@* ]]; then
|
|
https_url=$(echo "$https_url" | sed -E 's|^git@([^:]+):(.+)$|https://\1/\2|')
|
|
elif [[ "$https_url" == ssh://* ]]; then
|
|
https_url=$(echo "$https_url" | sed -E 's|^ssh://[^@]*@([^/]+)/(.+)$|https://\1/\2|')
|
|
fi
|
|
# shellcheck disable=SC2001
|
|
echo "$https_url" | sed "s|https://|https://${BOT_USER}:${GITEA_TOKEN}@|"
|
|
fi
|
|
}
|
|
|
|
# ─── Remote Queries ─────────────────────────────────────────────────
|
|
|
|
subrepo_ls_remote() {
|
|
local ref="${1:-HEAD}"
|
|
local output
|
|
output=$(git ls-remote "$(subrepo_auth_url)" "refs/heads/${ref}") \
|
|
|| die "Failed to reach subrepo (check SSH key / auth)"
|
|
echo "$output" | awk '{print $1}'
|
|
}
|
|
|
|
# ─── PR Creation ────────────────────────────────────────────────────
|
|
# Shared helpers for creating PRs on Gitea/GitHub API.
|
|
# Usage: create_pr <api_url> <token> <base> <head> <title> <body>
|
|
# number=$(create_pr_number <api_url> <token> <base> <head> <title> <body>)
|
|
#
|
|
# create_pr — fire-and-forget (stdout suppressed, safe inside sync functions)
|
|
# create_pr_number — returns the new PR number via stdout
|
|
|
|
create_pr_number() {
|
|
local api_url="$1" token="$2" base="$3" head="$4" title="$5" body="$6"
|
|
|
|
curl -sf -X POST \
|
|
-H "Authorization: token ${token}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$(jq -n \
|
|
--arg base "$base" \
|
|
--arg head "$head" \
|
|
--arg title "$title" \
|
|
--arg body "$body" \
|
|
'{base:$base, head:$head, title:$title, body:$body}')" \
|
|
"${api_url}/pulls" | jq -r '.number'
|
|
}
|
|
|
|
create_pr() {
|
|
create_pr_number "$@" >/dev/null
|
|
}
|
|
|
|
# ─── PR API Helpers ──────────────────────────────────────────────
|
|
# Used by onboard and migrate-pr commands.
|
|
|
|
# List open PRs on a repo. Returns JSON array.
|
|
# Usage: list_open_prs <api_url> <token>
|
|
list_open_prs() {
|
|
local api_url="$1" token="$2"
|
|
curl -sf -H "Authorization: token ${token}" \
|
|
"${api_url}/pulls?state=open&limit=50"
|
|
}
|
|
|
|
# Get PR diff as plain text.
|
|
# Usage: get_pr_diff <api_url> <token> <pr_number>
|
|
get_pr_diff() {
|
|
local api_url="$1" token="$2" pr_number="$3"
|
|
curl -sf -H "Authorization: token ${token}" \
|
|
"${api_url}/pulls/${pr_number}.diff"
|
|
}
|
|
|
|
# Get single PR as JSON (for checking merge status, metadata, etc.).
|
|
# Usage: get_pr <api_url> <token> <pr_number>
|
|
get_pr() {
|
|
local api_url="$1" token="$2" pr_number="$3"
|
|
curl -sf -H "Authorization: token ${token}" \
|
|
"${api_url}/pulls/${pr_number}"
|
|
}
|