hive-forge: fix assign endpoint + surface API errors via --fail-with-body (#353)

This commit is contained in:
damocles 2026-05-23 15:53:06 +02:00
parent b3e94760e1
commit 8e5112aa27

View file

@ -27,21 +27,28 @@ pkgs.writeShellApplication {
_token=$(cat "$_token_file") _token=$(cat "$_token_file")
FORGE_API="$HIVE_FORGE_URL/api/v1" FORGE_API="$HIVE_FORGE_URL/api/v1"
# `-sS --fail-with-body` makes curl quiet on success, print errors to
# stderr on transport failures, AND surface the response body for HTTP
# error codes (4xx/5xx) before exiting non-zero. Without this, a 500 /
# 404 from forge silently returned an empty stdout — combined with the
# script's `set -o pipefail` + the `| jq ...` consumer, the failure
# propagated as "no output" with no clue about what went wrong (closes
# #353).
forge_get() { forge_get() {
${pkgs.curl}/bin/curl -sf \ ${pkgs.curl}/bin/curl -sS --fail-with-body \
-H "Authorization: token $_token" \ -H "Authorization: token $_token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
"$1" "$1"
} }
forge_post() { forge_post() {
${pkgs.curl}/bin/curl -sf -X POST \ ${pkgs.curl}/bin/curl -sS --fail-with-body -X POST \
-H "Authorization: token $_token" \ -H "Authorization: token $_token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-d "$2" "$1" -d "$2" "$1"
} }
forge_patch() { forge_patch() {
${pkgs.curl}/bin/curl -sf -X PATCH \ ${pkgs.curl}/bin/curl -sS --fail-with-body -X PATCH \
-H "Authorization: token $_token" \ -H "Authorization: token $_token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
@ -51,13 +58,13 @@ pkgs.writeShellApplication {
local _url="$1" local _url="$1"
local _body="''${2:-}" local _body="''${2:-}"
if [ -n "$_body" ]; then if [ -n "$_body" ]; then
${pkgs.curl}/bin/curl -sf -X DELETE \ ${pkgs.curl}/bin/curl -sS --fail-with-body -X DELETE \
-H "Authorization: token $_token" \ -H "Authorization: token $_token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-d "$_body" "$_url" -d "$_body" "$_url"
else else
${pkgs.curl}/bin/curl -sf -X DELETE \ ${pkgs.curl}/bin/curl -sS --fail-with-body -X DELETE \
-H "Authorization: token $_token" \ -H "Authorization: token $_token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
"$_url" "$_url"
@ -189,17 +196,29 @@ pkgs.writeShellApplication {
cmd_assign() { cmd_assign() {
# assign <number> <user> [--remove] # assign <number> <user> [--remove]
# Assign or unassign a user on an issue or PR. # Assign or unassign a user on an issue or PR.
#
# The Forgejo API has no dedicated `POST /issues/{n}/assignees`
# endpoint (closes #353) — assignees are an EditIssueOption field
# on the issue itself. We patch the full assignee list:
# - add: GET current assignees, append `_user`, PATCH back
# - remove: GET current assignees, drop `_user`, PATCH back
# The PATCH is idempotent: re-adding an existing assignee or
# removing one that's not on the list is a no-op (the resulting
# assignee list is unchanged).
if [ $# -lt 2 ]; then echo "usage: hive-forge assign <number> <user> [--remove]" >&2; exit 1; fi if [ $# -lt 2 ]; then echo "usage: hive-forge assign <number> <user> [--remove]" >&2; exit 1; fi
local _n="$1" _user="$2" _remove="''${3:-}" local _n="$1" _user="$2" _remove="''${3:-}"
local _payload local _current _payload
_payload=$(jq -n --arg u "$_user" '{assignees:[$u]}') _current=$(forge_get "$FORGE_API/repos/$HIVE_FORGE_REPO/issues/$_n" \
| jq -c '[.assignees[]?.login]')
if [ "$_remove" = "--remove" ]; then if [ "$_remove" = "--remove" ]; then
forge_delete "$FORGE_API/repos/$HIVE_FORGE_REPO/issues/$_n/assignees" "$_payload" \ _payload=$(jq -n --argjson cur "$_current" --arg u "$_user" \
| jq '{number,assignees:[.assignees[]?.login]}' '{assignees: ($cur - [$u])}')
else else
forge_post "$FORGE_API/repos/$HIVE_FORGE_REPO/issues/$_n/assignees" "$_payload" \ _payload=$(jq -n --argjson cur "$_current" --arg u "$_user" \
| jq '{number,assignees:[.assignees[]?.login]}' '{assignees: (($cur + [$u]) | unique)}')
fi fi
forge_patch "$FORGE_API/repos/$HIVE_FORGE_REPO/issues/$_n" "$_payload" \
| jq '{number,assignees:[.assignees[]?.login]}'
} }
cmd_close() { cmd_close() {