diff --git a/git-hangman-lab/scripts/publish-package b/git-hangman-lab/scripts/publish-package index 00e9eee..3ff457d 100755 --- a/git-hangman-lab/scripts/publish-package +++ b/git-hangman-lab/scripts/publish-package @@ -118,17 +118,49 @@ do_docker() { fi fi - LINK_RESP=$(curl -s -w "%{http_code}" -X POST \ - -u "${OWNER}:${TOKEN}" \ - "https://git.hangman-lab.top/api/v1/packages/${OWNER}/container/${IMAGE}/-/link/${REPO_NAME}") - LINK_STATUS="${LINK_RESP: -3}" - LINK_BODY="${LINK_RESP:0:-3}" + # Gitea's link/unlink endpoints are not idempotent: POST /-/link/{repo} + # returns HTTP 400 "invalid argument" when the package already has ANY link + # (even to the same repo), and POST /-/unlink returns 400 when nothing is + # linked. So read the current link first and branch accordingly. + TARGET_LINK="${REPO_OWNER}/${REPO_NAME}" + STATE_RESP=$(curl -s -w "\n%{http_code}" -u "${OWNER}:${TOKEN}" \ + "https://git.hangman-lab.top/api/v1/packages/${OWNER}/container/${IMAGE}/${TAG}") + STATE_STATUS=$(printf "%s" "$STATE_RESP" | tail -n1) + STATE_BODY=$(printf "%s" "$STATE_RESP" | sed '$d') - if [[ "$LINK_STATUS" != "200" && "$LINK_STATUS" != "201" ]]; then - if echo "$LINK_BODY" | grep -q '"message".*repository does not exist'; then - echo "Warning: repository '$REPO_NAME' is not owned by '$OWNER' — skipping link (requires site admin or matching owner)." + CURRENT_LINK="" + if [[ "$STATE_STATUS" == "200" ]]; then + CURRENT_LINK=$(printf "%s" "$STATE_BODY" | python3 -c \ + 'import sys, json; p=json.load(sys.stdin); r=p.get("repository") or {}; print(r.get("full_name") or "")' \ + 2>/dev/null || echo "") + fi + + if [[ "$CURRENT_LINK" == "$TARGET_LINK" ]]; then + echo "Package already linked to ${TARGET_LINK}, skipping link step." + else + if [[ -n "$CURRENT_LINK" ]]; then + echo "Package currently linked to ${CURRENT_LINK}, unlinking first..." + UNLINK_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST -u "${OWNER}:${TOKEN}" \ + "https://git.hangman-lab.top/api/v1/packages/${OWNER}/container/${IMAGE}/-/unlink") + if [[ "$UNLINK_STATUS" != "204" ]]; then + echo "Warning: unlink returned HTTP $UNLINK_STATUS, proceeding with link attempt anyway..." + fi + fi + + LINK_RESP=$(curl -s -w "%{http_code}" -X POST \ + -u "${OWNER}:${TOKEN}" \ + "https://git.hangman-lab.top/api/v1/packages/${OWNER}/container/${IMAGE}/-/link/${REPO_NAME}") + LINK_STATUS="${LINK_RESP: -3}" + LINK_BODY="${LINK_RESP:0:-3}" + + if [[ "$LINK_STATUS" != "200" && "$LINK_STATUS" != "201" ]]; then + if echo "$LINK_BODY" | grep -q '"message".*repository does not exist'; then + echo "Warning: repository '$REPO_NAME' is not owned by '$OWNER' — skipping link (requires site admin or matching owner)." + else + echo "Warning: package link failed (HTTP $LINK_STATUS): $LINK_BODY" + fi else - echo "Warning: package link failed (HTTP $LINK_STATUS): $LINK_BODY" + echo "Linked package to ${TARGET_LINK}." fi fi