diff --git a/.github/scripts/generate_manifest.py b/.github/scripts/generate_manifest.py new file mode 100644 index 0000000..14c92c9 --- /dev/null +++ b/.github/scripts/generate_manifest.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +"""Generate/update Jellyfin plugin repository manifest.""" + +import argparse +import json +import os +import sys +from datetime import datetime, timezone + +def load_build_yaml(path="build.yaml"): + """Load plugin metadata from build.yaml.""" + import re + with open(path) as f: + content = f.read() + + def get_field(name): + match = re.search(rf'^{name}:\s*["\']?([^"\'\n]+)["\']?', content, re.MULTILINE) + return match.group(1).strip() if match else "" + + return { + "guid": get_field("guid"), + "name": get_field("name"), + "description": get_field("description") or get_field("overview"), + "overview": get_field("overview") or get_field("description"), + "owner": get_field("owner"), + "category": get_field("category"), + "targetAbi": get_field("targetAbi"), + "imageUrl": get_field("imageUrl"), + } + + +def generate_manifest(version, tag, repo, output, build_yaml="build.yaml", checksum=""): + meta = load_build_yaml(build_yaml) + + zip_name = f"{meta['name'].replace(' ', '_')}_{version}.zip" + source_url = f"https://github.com/{repo}/releases/download/{tag}/{zip_name}" + + # If checksum not provided, try to read from a .md5 file beside the zip + if not checksum: + md5_path = f"{zip_name}.md5" + if os.path.exists(md5_path): + with open(md5_path) as f: + checksum = f.read().strip() + + new_version_entry = { + "version": version, + "changelog": f"Release {tag}. See https://github.com/{repo}/releases/tag/{tag}", + "targetAbi": meta.get("targetAbi", "10.9.0.0"), + "sourceUrl": source_url, + "checksum": checksum, + "timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + } + + # Load existing manifest or create new + manifest = [] + if os.path.exists(output): + with open(output) as f: + try: + manifest = json.load(f) + except json.JSONDecodeError: + manifest = [] + + # Find or create plugin entry + plugin_entry = None + for entry in manifest: + if entry.get("guid") == meta["guid"]: + plugin_entry = entry + break + + if plugin_entry is None: + plugin_entry = { + "guid": meta["guid"], + "name": meta["name"], + "description": meta.get("description", ""), + "overview": meta.get("overview", ""), + "owner": meta.get("owner", ""), + "category": meta.get("category", "General"), + "imageUrl": meta.get("imageUrl", ""), + "versions": [] + } + manifest.append(plugin_entry) + + # Prepend new version (newest first) + versions = plugin_entry.get("versions", []) + versions = [v for v in versions if v["version"] != version] # remove existing same-version entry + versions.insert(0, new_version_entry) + plugin_entry["versions"] = versions + + os.makedirs(os.path.dirname(output) if os.path.dirname(output) else ".", exist_ok=True) + with open(output, "w") as f: + json.dump(manifest, f, indent=2) + + print(f"Manifest written to {output}") + print(f"Plugin: {meta['name']} v{version}") + print(f"sourceUrl: {source_url}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--version", required=True) + parser.add_argument("--tag", required=True) + parser.add_argument("--repo", required=True) + parser.add_argument("--output", required=True) + parser.add_argument("--build-yaml", default="build.yaml") + parser.add_argument("--checksum", default="") + args = parser.parse_args() + generate_manifest(args.version, args.tag, args.repo, args.output, args.build_yaml, args.checksum) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..26c74ac --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: Build + +on: + push: + branches: [main, develop] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '9.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore --configuration Release + + - name: Run tests + run: dotnet test --no-build --configuration Release --logger "trx;LogFileName=test-results.trx" + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: '**/*.trx' + retention-days: 7 + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: plugin-build + path: '**/bin/Release/net9.0/' + retention-days: 7 diff --git a/.github/workflows/init-pages.yml b/.github/workflows/init-pages.yml new file mode 100644 index 0000000..3053eb0 --- /dev/null +++ b/.github/workflows/init-pages.yml @@ -0,0 +1,24 @@ +name: Initialize gh-pages + +on: + workflow_dispatch: + +jobs: + init: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Create gh-pages branch + run: | + git clone https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} repo + cd repo + git checkout --orphan gh-pages + git rm -rf . + echo '[]' > repository.json + echo '
Add this URL to Jellyfin: https://BarbellDwarf.github.io/PureFin-Plugin/repository.json