feat: enhance release publishing logic in CI workflow to handle existing releases and asset management
CI / Windows x64 (push) Successful in 8m52s
CI / Windows x64 (push) Successful in 8m52s
This commit is contained in:
+41
-18
@@ -135,6 +135,16 @@ jobs:
|
||||
|
||||
# Releases go through the Gitea API directly: it is GitHub-compatible in
|
||||
# shape, but a self-hosted instance may not have ready-made actions.
|
||||
#
|
||||
# The step is written to be repeatable. Creating a release in the Gitea
|
||||
# web UI also creates the tag, so by the time this runs the release
|
||||
# usually exists already and a blind POST would fail with 409. The same
|
||||
# goes for re-running a build over a tag whose assets are in place.
|
||||
#
|
||||
# Keep it POSIX: the runner executes steps with dash, so no `pipefail`.
|
||||
# curl calls therefore stay out of pipelines — under `set -e` a failed
|
||||
# command substitution aborts the step, which is what pipefail bought us.
|
||||
# No -x anywhere here: these commands carry the token.
|
||||
- name: Publish release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
@@ -142,29 +152,42 @@ jobs:
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
# Keep this POSIX: the runner executes steps with dash, where
|
||||
# `set -o pipefail` does not exist. So the curl call is kept out of a
|
||||
# pipeline — under `set -e` a failed command substitution aborts the
|
||||
# step, which is what pipefail would have bought us. Without that, a
|
||||
# failing curl would be masked by a successful jq, id would become
|
||||
# null, and assets would be uploaded to a release that never existed.
|
||||
# No -x here: the command carries the token.
|
||||
set -eu
|
||||
response=$(curl -fsS -X POST "$API/releases" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\"}")
|
||||
auth="Authorization: token $TOKEN"
|
||||
|
||||
id=$(printf '%s' "$response" | jq -r '.id // empty')
|
||||
# Reuse the release if it is already there, create it otherwise.
|
||||
existing=$(curl -sS -o /tmp/release.json -w '%{http_code}' \
|
||||
-H "$auth" "$API/releases/tags/$TAG")
|
||||
|
||||
if [ "$existing" = "200" ]; then
|
||||
echo "release $TAG already exists, attaching assets to it"
|
||||
else
|
||||
echo "creating release $TAG"
|
||||
curl -fsS -o /tmp/release.json -X POST "$API/releases" \
|
||||
-H "$auth" -H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\"}"
|
||||
fi
|
||||
|
||||
id=$(jq -r '.id // empty' /tmp/release.json)
|
||||
if [ -z "$id" ]; then
|
||||
echo "no release id in response: $response" >&2
|
||||
echo "could not resolve release id for $TAG:" >&2
|
||||
cat /tmp/release.json >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "release $TAG (id $id)"
|
||||
|
||||
for file in dist/*.exe; do
|
||||
echo "uploading $(basename "$file")"
|
||||
curl -fsS -X POST "$API/releases/$id/assets?name=$(basename "$file")" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@$file" > /dev/null
|
||||
name=$(basename "$file")
|
||||
|
||||
# Replace an asset of the same name rather than ending up with two.
|
||||
curl -fsS -o /tmp/assets.json -H "$auth" "$API/releases/$id/assets"
|
||||
for old in $(jq -r --arg n "$name" '.[] | select(.name==$n) | .id' /tmp/assets.json); do
|
||||
echo "removing previous $name (asset $old)"
|
||||
curl -fsS -X DELETE -H "$auth" "$API/releases/$id/assets/$old" > /dev/null
|
||||
done
|
||||
|
||||
echo "uploading $name"
|
||||
curl -fsS -X POST "$API/releases/$id/assets?name=$name" \
|
||||
-H "$auth" -F "attachment=@$file" > /dev/null
|
||||
done
|
||||
|
||||
echo "release $TAG (id $id) is ready"
|
||||
|
||||
Reference in New Issue
Block a user