diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index ecbbcbc..aee4bce 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -2,10 +2,103 @@ name: release on: workflow_dispatch: + inputs: + tag_name: + description: Release tag (for example v0.1.0) + required: true + release_name: + description: Optional release title + required: false + release_notes: + description: Release notes / body + required: false jobs: + create-release: + name: Create release + runs-on: ubuntu-latest + outputs: + release_id: ${{ steps.release.outputs.release_id }} + release_name: ${{ steps.release.outputs.release_name }} + steps: + - name: Create or reuse Gitea release + id: release + env: + GITEA_TOKEN: ${{ github.token }} + GITEA_API: ${{ github.server_url }}/api/v1 + REPO: ${{ github.repository }} + TAG_NAME: ${{ inputs.tag_name }} + INPUT_RELEASE_NAME: ${{ inputs.release_name }} + RELEASE_NOTES: ${{ inputs.release_notes }} + TARGET_COMMITISH: ${{ github.sha }} + run: | + set -euo pipefail + + if [ -n "${INPUT_RELEASE_NAME}" ]; then + RELEASE_NAME="${INPUT_RELEASE_NAME}" + else + RELEASE_NAME="Release ${TAG_NAME}" + fi + export RELEASE_NAME + + get_release_url="${GITEA_API}/repos/${REPO}/releases/tags/${TAG_NAME}" + create_release_url="${GITEA_API}/repos/${REPO}/releases" + + status="$(curl -sS -o /tmp/release.json -w '%{http_code}' \ + -H "Authorization: token ${GITEA_TOKEN}" \ + "${get_release_url}")" + + if [ "${status}" = "200" ]; then + python3 - <<'PY' >> "$GITHUB_OUTPUT" + import json + with open('/tmp/release.json', 'r', encoding='utf-8') as f: + data = json.load(f) + print(f"release_id={data['id']}") + print(f"release_name={data['name']}") + PY + exit 0 + fi + + if [ "${status}" != "404" ]; then + echo "Unexpected response while checking release: HTTP ${status}" + cat /tmp/release.json + exit 1 + fi + + python3 - <<'PY' > /tmp/release-payload.json + import json, os + payload = { + "tag_name": os.environ["TAG_NAME"], + "target_commitish": os.environ["TARGET_COMMITISH"], + "name": os.environ["RELEASE_NAME"], + "body": os.environ.get("RELEASE_NOTES", ""), + "draft": False, + "prerelease": False, + } + print(json.dumps(payload)) + PY + + curl -sS \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -X POST \ + --data @/tmp/release-payload.json \ + "${create_release_url}" \ + -o /tmp/release.json + + python3 - <<'PY' >> "$GITHUB_OUTPUT" + import json + with open('/tmp/release.json', 'r', encoding='utf-8') as f: + data = json.load(f) + if 'id' not in data: + raise SystemExit(json.dumps(data, indent=2)) + print(f"release_id={data['id']}") + print(f"release_name={data['name']}") + PY + build-release: name: ${{ matrix.toolchain.name }} + needs: create-release runs-on: ubuntu-latest strategy: fail-fast: false @@ -131,7 +224,7 @@ jobs: - name: Package release archive run: | - REF_NAME="${GITHUB_REF_NAME:-$(git rev-parse --short=9 HEAD)}" + REF_NAME="${{ inputs.tag_name }}" ARCHIVE="/tmp/peya-${REF_NAME}-${{ matrix.toolchain.host }}.zip" cd "build/${{ matrix.toolchain.host }}/release/bin" @@ -153,9 +246,55 @@ jobs: zip -ur "${ARCHIVE}" "${FILES[@]}" ls -lh "${ARCHIVE}" - - name: Upload build artifact + - name: Upload workflow artifact uses: https://github.com/actions/upload-artifact@v3 with: name: peya-${{ matrix.toolchain.host }} path: /tmp/peya-*-${{ matrix.toolchain.host }}.zip if-no-files-found: error + + - name: Upload release asset + env: + GITEA_TOKEN: ${{ github.token }} + GITEA_API: ${{ github.server_url }}/api/v1 + REPO: ${{ github.repository }} + RELEASE_ID: ${{ needs.create-release.outputs.release_id }} + ASSET_NAME: peya-${{ inputs.tag_name }}-${{ matrix.toolchain.host }}.zip + run: | + set -euo pipefail + + asset="$(echo /tmp/peya-*-${{ matrix.toolchain.host }}.zip)" + asset_name="$(basename "${asset}")" + assets_url="${GITEA_API}/repos/${REPO}/releases/${RELEASE_ID}/assets" + + curl -sS \ + -H "Authorization: token ${GITEA_TOKEN}" \ + "${assets_url}" \ + -o /tmp/release-assets.json + + existing_id="$(python3 - <<'PY' + import json, os + name = os.environ["ASSET_NAME"] + with open('/tmp/release-assets.json', 'r', encoding='utf-8') as f: + assets = json.load(f) + for asset in assets: + if asset.get('name') == name: + print(asset['id']) + break + PY + )" + + if [ -n "${existing_id}" ]; then + curl -sS \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -X DELETE \ + "${assets_url}/${existing_id}" \ + >/dev/null + fi + + curl -sS \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -X POST \ + -F "attachment=@${asset}" \ + "${assets_url}?name=${asset_name}" \ + >/dev/null