name: Publish a Forgejo release description: >- Create (or replace) a release on this Forgejo instance and upload assets, using the Forgejo API via curl. Reimplements forgejo-release / the hand-rolled curl uploads — no marketplace actions. inputs: token: description: API token with write access (e.g. secrets.FORGEJO_PACKAGE_TOKEN or the workflow token). required: true files: description: A directory (all regular files within are uploaded) or a glob of asset files. required: true tag: description: Release tag. Defaults to the pushed ref name (github.ref_name). default: "" draft: description: Create the release as a draft ("true"/"false"). default: "false" prerelease: description: Mark the release as a prerelease ("true"/"false"). default: "false" override: description: >- Delete any existing release (and its tag) with the same tag first, then recreate it at the current commit. Use for moving tags such as "latest". default: "false" runs: using: composite steps: - name: Create release and upload assets shell: bash env: TOKEN: ${{ inputs.token }} FILES: ${{ inputs.files }} IN_TAG: ${{ inputs.tag }} DRAFT: ${{ inputs.draft }} PRERELEASE: ${{ inputs.prerelease }} OVERRIDE: ${{ inputs.override }} SERVER_URL: ${{ github.server_url }} REPO: ${{ github.repository }} REF_NAME: ${{ github.ref_name }} SHA: ${{ github.sha }} run: | set -euo pipefail command -v jq >/dev/null 2>&1 || { apt-get update && apt-get install -y --no-install-recommends jq curl; } tag="${IN_TAG:-$REF_NAME}" api="${SERVER_URL}/api/v1/repos/${REPO}" auth=(-H "Authorization: token ${TOKEN}") # Override: remove an existing release+tag so a moving tag (e.g. latest) is recreated cleanly. if [ "$OVERRIDE" = "true" ]; then rid="$(curl -fsS "${auth[@]}" "${api}/releases/tags/${tag}" 2>/dev/null | jq -r '.id // empty' || true)" [ -n "$rid" ] && curl -fsS -X DELETE "${auth[@]}" "${api}/releases/${rid}" >/dev/null 2>&1 || true curl -fsS -X DELETE "${auth[@]}" "${api}/tags/${tag}" >/dev/null 2>&1 || true fi # Create the release. target_commitish pins a not-yet-existing tag to this commit. payload="$(jq -nc --arg t "$tag" --arg c "$SHA" \ --argjson d "$DRAFT" --argjson p "$PRERELEASE" \ '{tag_name:$t, name:$t, target_commitish:$c, draft:$d, prerelease:$p}')" rid="$(curl -fsS -X POST "${auth[@]}" -H "Content-Type: application/json" \ "${api}/releases" -d "$payload" | jq -r '.id')" echo "Created release ${tag} (id ${rid})" # Collect assets: a directory expands to its contents, otherwise treat the input as a glob. shopt -s nullglob if [ -d "$FILES" ]; then set -- "$FILES"/*; else set -- $FILES; fi for f in "$@"; do [ -f "$f" ] || continue name="$(basename "$f")" curl -fsS -X POST "${auth[@]}" \ "${api}/releases/${rid}/assets?name=${name}" \ -F "attachment=@${f};type=application/octet-stream" >/dev/null echo "uploaded ${name}" done