name: Release Jellyfin plugin on: push: tags: - "jellyfin/*/v*" jobs: release: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - name: Parse tag id: meta run: | set -euo pipefail TAG="${GITHUB_REF_NAME}" # jellyfin//v1.2.3 if [[ ! "$TAG" =~ ^jellyfin/([a-z0-9-]+)/v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then echo "Tag must match jellyfin//vX.Y.Z (got: $TAG)" exit 1 fi SLUG="${BASH_REMATCH[1]}" VERSION="${BASH_REMATCH[2]}" PLUGIN_DIR="Jellyfin/${SLUG}" if [[ ! -f "${PLUGIN_DIR}/build.yaml" ]]; then echo "Missing ${PLUGIN_DIR}/build.yaml" exit 1 fi echo "slug=${SLUG}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "plugin_dir=${PLUGIN_DIR}" >> "$GITHUB_OUTPUT" echo "tag=${TAG}" >> "$GITHUB_OUTPUT" echo "version4=${VERSION}.0" >> "$GITHUB_OUTPUT" - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "9.0.x" - name: Install jprm run: | python3 -m venv /tmp/jprm-venv /tmp/jprm-venv/bin/pip install --upgrade pip jprm - name: Build plugin package id: build run: | set -euo pipefail PLUGIN_DIR="${{ steps.meta.outputs.plugin_dir }}" mkdir -p "${PLUGIN_DIR}/artifacts" sed -i -E "s/^version:.*/version: \"${{ steps.meta.outputs.version4 }}\"/" "${PLUGIN_DIR}/build.yaml" /tmp/jprm-venv/bin/jprm --verbosity=info plugin build "${PLUGIN_DIR}" --output "${PLUGIN_DIR}/artifacts" ARTIFACT=$(find "${PLUGIN_DIR}/artifacts" -type f -name '*.zip' | head -n1) if [[ -z "$ARTIFACT" ]]; then echo "No zip produced by jprm" ls -laR "${PLUGIN_DIR}/artifacts" || true exit 1 fi NAME=$(basename "$ARTIFACT") CHECKSUM=$(sha256sum "$ARTIFACT" | awk '{print $1}') echo "artifact=${ARTIFACT}" >> "$GITHUB_OUTPUT" echo "artifact_name=${NAME}" >> "$GITHUB_OUTPUT" echo "checksum=${CHECKSUM}" >> "$GITHUB_OUTPUT" echo "Built ${NAME} sha256=${CHECKSUM}" - name: Create Gitea release and upload asset id: release env: GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail GITEA_URL="${{ github.server_url }}" REPO_OWNER="${{ github.repository_owner }}" REPO_NAME="${{ github.event.repository.name }}" TAG="${{ steps.meta.outputs.tag }}" VERSION="${{ steps.meta.outputs.version }}" SLUG="${{ steps.meta.outputs.slug }}" ARTIFACT="${{ steps.build.outputs.artifact }}" ARTIFACT_NAME="${{ steps.build.outputs.artifact_name }}" BODY=$(printf 'Jellyfin plugin **%s** %s\n\nAdd the raw Jellyfin/manifest.json URL from this repo as a plugin repository.' \ "$SLUG" "$VERSION") BODY_JSON=$(printf '%s' "$BODY" | jq -Rs .) RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ "${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases" \ -d "{ \"tag_name\": \"${TAG}\", \"name\": \"${SLUG} ${VERSION}\", \"body\": ${BODY_JSON}, \"draft\": false, \"prerelease\": false }") HTTP_CODE=$(echo "$RESPONSE" | tail -n1) RESP_BODY=$(echo "$RESPONSE" | sed '$d') if [[ "$HTTP_CODE" != "201" && "$HTTP_CODE" != "200" ]]; then echo "Failed to create release: HTTP $HTTP_CODE" echo "$RESP_BODY" exit 1 fi RELEASE_ID=$(echo "$RESP_BODY" | jq -r '.id') echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT" curl -sS -f -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/zip" \ --data-binary "@${ARTIFACT}" \ "${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/${RELEASE_ID}/assets?name=${ARTIFACT_NAME}" DOWNLOAD_URL="${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/releases/download/${TAG}/${ARTIFACT_NAME}" echo "download_url=${DOWNLOAD_URL}" >> "$GITHUB_OUTPUT" - name: Update Jellyfin/manifest.json env: GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail SLUG="${{ steps.meta.outputs.slug }}" VERSION="${{ steps.meta.outputs.version4 }}" CHECKSUM="${{ steps.build.outputs.checksum }}" DOWNLOAD_URL="${{ steps.release.outputs.download_url }}" TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") PLUGIN_DIR="${{ steps.meta.outputs.plugin_dir }}" GUID=$(grep -E '^guid:' "${PLUGIN_DIR}/build.yaml" | head -1 | sed -E 's/guid:[[:space:]]*"?([^"]*)"?/\1/') TARGET_ABI=$(grep -E '^targetAbi:' "${PLUGIN_DIR}/build.yaml" | head -1 | sed -E 's/targetAbi:[[:space:]]*"?([^"]*)"?/\1/') NEW_VERSION=$(jq -n \ --arg version "$VERSION" \ --arg changelog "Release ${VERSION}" \ --arg targetAbi "$TARGET_ABI" \ --arg sourceUrl "$DOWNLOAD_URL" \ --arg checksum "$CHECKSUM" \ --arg timestamp "$TIMESTAMP" \ '{ version: $version, changelog: $changelog, targetAbi: $targetAbi, sourceUrl: $sourceUrl, checksum: $checksum, timestamp: $timestamp }') jq --arg guid "$GUID" --argjson newver "$NEW_VERSION" ' map(if .guid == $guid then .versions = ([$newver] + (.versions // [])) else . end) ' Jellyfin/manifest.json > Jellyfin/manifest.json.tmp mv Jellyfin/manifest.json.tmp Jellyfin/manifest.json git config user.name "gitea-actions" git config user.email "actions@local" # Detach from tag checkout: update default branch DEFAULT_BRANCH=$(git remote show origin | sed -n '/HEAD branch/s/.*: //p') git fetch origin "$DEFAULT_BRANCH" git checkout -B "$DEFAULT_BRANCH" "origin/${DEFAULT_BRANCH}" # Re-apply manifest change if checkout overwrote jq --arg guid "$GUID" --argjson newver "$NEW_VERSION" ' map(if .guid == $guid then .versions = ([$newver] + (.versions // [])) else . end) ' Jellyfin/manifest.json > Jellyfin/manifest.json.tmp mv Jellyfin/manifest.json.tmp Jellyfin/manifest.json git add Jellyfin/manifest.json if git diff --staged --quiet; then echo "Manifest already up to date" exit 0 fi git commit -m "chore(jellyfin): publish ${SLUG} ${VERSION} to catalog" git push origin "$DEFAULT_BRANCH"