The v1.1.0 release job created the release then died with a jq parse error before uploading either package. The runner executes run: steps with a shell whose echo expands backslash escapes. Passing the API response through `echo "$BODY" | jq` turned the \n escapes in the release body field into real newlines, producing invalid JSON. This only surfaced now because the release body became multi-line; every earlier release had a single-line body with no \n to expand. Keep the response in a file and read it with jq directly, so no JSON passes through echo. Also fall back to the existing release for the tag when creation returns non-2xx, so a partially completed release can be re-run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
182 lines
7.2 KiB
YAML
182 lines
7.2 KiB
YAML
name: 'Release Plugin'
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*.*.*'
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: 'Version to release (e.g., v1.0.0)'
|
|
required: true
|
|
type: string
|
|
|
|
jobs:
|
|
build-and-release:
|
|
runs-on: linux/amd64
|
|
container:
|
|
image: gitea.tourolle.paris/dtourolle/jellylms-builder:latest
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
path: release-${{ github.run_id }}
|
|
|
|
- name: Get version
|
|
id: get_version
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
VERSION="${{ github.event.inputs.version }}"
|
|
else
|
|
VERSION="${GITHUB_REF#refs/tags/}"
|
|
fi
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
echo "version_number=${VERSION#v}" >> $GITHUB_OUTPUT
|
|
echo "Building version: ${VERSION}"
|
|
|
|
- name: Cache NuGet packages
|
|
uses: actions/cache@v3
|
|
with:
|
|
path: ~/.nuget/packages
|
|
key: nuget-${{ hashFiles('**/Jellyfin.Plugin.JellyLMS.csproj') }}
|
|
restore-keys: nuget-
|
|
|
|
- name: Restore dependencies
|
|
working-directory: release-${{ github.run_id }}
|
|
run: dotnet restore Jellyfin.Plugin.JellyLMS.sln
|
|
|
|
- name: Build solution
|
|
working-directory: release-${{ github.run_id }}
|
|
run: dotnet build Jellyfin.Plugin.JellyLMS.sln --configuration Release --no-restore --no-self-contained /m:1
|
|
|
|
- name: Build Jellyfin plugin packages
|
|
id: jprm
|
|
working-directory: release-${{ github.run_id }}
|
|
run: |
|
|
VERSION="${{ steps.get_version.outputs.version_number }}"
|
|
for VARIANT in jf11 jf12; do
|
|
ARTIFACT=$(./build-plugin.sh "${VARIANT}" "${VERSION}")
|
|
echo "${VARIANT}_artifact=${ARTIFACT}" >> $GITHUB_OUTPUT
|
|
echo "${VARIANT}_artifact_name=$(basename "${ARTIFACT}")" >> $GITHUB_OUTPUT
|
|
echo "${VARIANT}_checksum=$(md5sum "${ARTIFACT}" | awk '{print $1}')" >> $GITHUB_OUTPUT
|
|
echo "Built ${VARIANT}: ${ARTIFACT}"
|
|
done
|
|
|
|
- name: Create Release
|
|
working-directory: release-${{ github.run_id }}
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
# Get repository information
|
|
REPO_OWNER="${{ github.repository_owner }}"
|
|
REPO_NAME="${{ github.event.repository.name }}"
|
|
GITEA_URL="${{ github.server_url }}"
|
|
|
|
# Create release using Gitea API
|
|
VERSION="${{ steps.get_version.outputs.version }}"
|
|
RELEASE_BODY=$(printf '%s\n' \
|
|
"JellyLMS Jellyfin Plugin ${VERSION}." \
|
|
"" \
|
|
"Pick the package matching your server:" \
|
|
"" \
|
|
"- \`${{ steps.jprm.outputs.jf11_artifact_name }}\` - Jellyfin 10.11.x" \
|
|
"- \`${{ steps.jprm.outputs.jf12_artifact_name }}\` - Jellyfin 12.0.x")
|
|
API_URL="${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}"
|
|
|
|
# Keep the API response in a file: it contains \n escapes, and `echo` in
|
|
# this shell expands those into real newlines, which corrupts the JSON.
|
|
HTTP_CODE=$(curl -s -o release-response.json -w "%{http_code}" -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${API_URL}/releases" \
|
|
-d "$(jq -n --arg tag "$VERSION" --arg name "Release $VERSION" --arg body "$RELEASE_BODY" '{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')")
|
|
|
|
if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
|
|
echo "Create release returned HTTP ${HTTP_CODE}:"
|
|
cat release-response.json
|
|
echo "Falling back to an existing release for ${VERSION}..."
|
|
curl -sf -o release-response.json \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${API_URL}/releases/tags/${VERSION}"
|
|
fi
|
|
|
|
RELEASE_ID=$(jq -r '.id // empty' release-response.json)
|
|
if [ -z "${RELEASE_ID}" ]; then
|
|
echo "Could not determine release ID from:"
|
|
cat release-response.json
|
|
exit 1
|
|
fi
|
|
echo "Using release ID: ${RELEASE_ID}"
|
|
|
|
# Upload plugin artifacts (one per supported Jellyfin generation)
|
|
for ASSET in \
|
|
"${{ steps.jprm.outputs.jf11_artifact }}" \
|
|
"${{ steps.jprm.outputs.jf12_artifact }}"; do
|
|
echo "Uploading $(basename "${ASSET}")..."
|
|
curl -f -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/zip" \
|
|
--data-binary "@${ASSET}" \
|
|
"${API_URL}/releases/${RELEASE_ID}/assets?name=$(basename "${ASSET}")"
|
|
done
|
|
|
|
rm -f release-response.json
|
|
echo "Release created successfully!"
|
|
echo "View at: ${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/releases/tag/${{ steps.get_version.outputs.version }}"
|
|
|
|
- name: Update manifest.json
|
|
working-directory: release-${{ github.run_id }}
|
|
run: |
|
|
git config user.name "Gitea Actions"
|
|
git config user.email "actions@gitea.tourolle.paris"
|
|
git fetch origin master
|
|
git checkout master
|
|
|
|
VERSION="${{ steps.get_version.outputs.version_number }}"
|
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
REPO_OWNER="${{ github.repository_owner }}"
|
|
REPO_NAME="${{ github.event.repository.name }}"
|
|
GITEA_URL="${{ github.server_url }}"
|
|
RELEASE_URL="${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/releases/download/${{ steps.get_version.outputs.version }}"
|
|
|
|
# One manifest entry per Jellyfin generation. Jellyfin filters the list by
|
|
# targetAbi, so both entries can share the same version number.
|
|
add_version() {
|
|
local abi="$1" artifact_name="$2" checksum="$3"
|
|
jq \
|
|
--arg version "${VERSION}" \
|
|
--arg abi "${abi}" \
|
|
--arg url "${RELEASE_URL}/${artifact_name}" \
|
|
--arg checksum "${checksum}" \
|
|
--arg timestamp "${TIMESTAMP}" \
|
|
'.[0].versions = [{
|
|
version: $version,
|
|
changelog: "Release \($version)",
|
|
targetAbi: $abi,
|
|
sourceUrl: $url,
|
|
checksum: $checksum,
|
|
timestamp: $timestamp
|
|
}] + .[0].versions' manifest.json > manifest.tmp.json
|
|
mv manifest.tmp.json manifest.json
|
|
}
|
|
|
|
add_version "10.11.0.0" "${{ steps.jprm.outputs.jf11_artifact_name }}" "${{ steps.jprm.outputs.jf11_checksum }}"
|
|
add_version "12.0.0.0" "${{ steps.jprm.outputs.jf12_artifact_name }}" "${{ steps.jprm.outputs.jf12_checksum }}"
|
|
|
|
echo "Updated manifest.json:"
|
|
cat manifest.json
|
|
|
|
- name: Commit and push manifest
|
|
working-directory: release-${{ github.run_id }}
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
git add manifest.json
|
|
git commit -m "Update manifest.json for ${{ steps.get_version.outputs.version }}"
|
|
git push origin master
|
|
|
|
- name: Cleanup
|
|
if: always()
|
|
run: rm -rf release-${{ github.run_id }}
|