feat(ci): scripts/ci 基座(_env/lib-forgejo/notify)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-05 23:49:59 +08:00
parent 6be777dff5
commit b8343a8788
3 changed files with 172 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env bash
# lib-forgejo.sh — Forgejo/Gitea release API helpers shared by the pangolin
# release pipelines (website / server / client). `source` this after _env.sh.
#
# Provides:
# forgejo_release_ensure <tag> <title> -> looks up or creates the release
# for <tag>; sets/exports RELEASE_ID
# forgejo_upload_asset <tag> <file> -> uploads one asset to that release
#
# Requires env: FORGEJO_URL, FORGEJO_TOKEN, FORGEJO_REPO (see _env.sh for the
# default FORGEJO_REPO=wangjia/pangolin).
#
# No command substitution ($()) is used anywhere: HTTP status codes and JSON
# fields are written to temp files by curl/python3 and read back with `read`.
: "${FORGEJO_REPO:=wangjia/pangolin}"
# forgejo_release_ensure <tag> <title>
forgejo_release_ensure() {
local tag="$1" title="$2"
local get_code_file get_body_file get_code
get_code_file="/tmp/forgejo_get_code.$$"
get_body_file="/tmp/forgejo_get_body.$$.json"
curl -k -s -o "$get_body_file" -w '%{http_code}' \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"${FORGEJO_URL}/api/v1/repos/${FORGEJO_REPO}/releases/tags/${tag}" \
> "$get_code_file"
read -r get_code < "$get_code_file"
rm -f "$get_code_file"
if [ "$get_code" = "200" ]; then
echo "==> forgejo: release ${tag} already exists"
_forgejo_read_release_id "$get_body_file"
rm -f "$get_body_file"
return 0
fi
rm -f "$get_body_file"
echo "==> forgejo: creating release ${tag}"
local create_code_file create_body_file create_code
create_code_file="/tmp/forgejo_create_code.$$"
create_body_file="/tmp/forgejo_create_body.$$.json"
curl -k -s -o "$create_body_file" -w '%{http_code}' \
-X POST "${FORGEJO_URL}/api/v1/repos/${FORGEJO_REPO}/releases" \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"${tag}\",\"name\":\"${title}\",\"draft\":false,\"prerelease\":false}" \
> "$create_code_file"
read -r create_code < "$create_code_file"
rm -f "$create_code_file"
if [ "$create_code" -lt 200 ] || [ "$create_code" -ge 300 ]; then
echo "==> forgejo: release create FAILED (HTTP ${create_code})" >&2
cat "$create_body_file" >&2
rm -f "$create_body_file"
return 1
fi
_forgejo_read_release_id "$create_body_file"
rm -f "$create_body_file"
echo "==> forgejo: release_id=${RELEASE_ID}"
}
# _forgejo_read_release_id <json_file> — internal: sets/exports RELEASE_ID.
_forgejo_read_release_id() {
local json_file="$1" id_file
id_file="/tmp/forgejo_release_id.$$"
python3 -c "import json,sys; print(json.load(open(sys.argv[1]))['id'])" \
"$json_file" > "$id_file"
read -r RELEASE_ID < "$id_file"
rm -f "$id_file"
export RELEASE_ID
}
# forgejo_upload_asset <tag> <file>
forgejo_upload_asset() {
local tag="$1" file="$2"
if [ -z "${RELEASE_ID:-}" ]; then
forgejo_release_ensure "$tag" "$tag" || return 1
fi
local code_file body_file code
code_file="/tmp/forgejo_upload_code.$$"
body_file="/tmp/forgejo_upload_body.$$.json"
curl -k -s -o "$body_file" -w '%{http_code}' \
-X POST "${FORGEJO_URL}/api/v1/repos/${FORGEJO_REPO}/releases/${RELEASE_ID}/assets" \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-F "attachment=@${file}" \
> "$code_file"
read -r code < "$code_file"
rm -f "$code_file"
echo "==> forgejo: uploaded ${file} (HTTP ${code})"
if [ "$code" -lt 200 ] || [ "$code" -ge 300 ]; then
cat "$body_file" >&2
rm -f "$body_file"
return 1
fi
rm -f "$body_file"
}