name: CI # Checks run on every push and PR. Pushes to main and v* tags build and package # the plugin, then publish the .ndp artifact to both this repo's Gitea package # registry and pkgs.daubney.dev - but only once every check has passed. Every # run is reported to ntfy. on: push: branches: ["**"] tags: ["v*"] pull_request: workflow_dispatch: env: UV_VERSION: "0.7.21" NAVIDROME_VERSION: "0.64.2" PLUGIN_ID: navidrome-scrobbled jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: https://github.com/astral-sh/setup-uv@v6 with: # Exact version: avoids an unauthenticated GitHub API lookup for "latest". version: ${{ env.UV_VERSION }} - run: uv sync --locked - run: uv run ruff check - run: uv run ruff format --check test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: https://github.com/astral-sh/setup-uv@v6 with: version: ${{ env.UV_VERSION }} - run: uv sync --locked - run: uv run python -m unittest discover -s tests -v build: needs: [lint, test] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install extism-py and Binaryen # Official installer: fetches the latest extism-py release for this # OS/arch and installs wasm-merge/wasm-opt (Binaryen) if missing. run: curl -fsSL https://raw.githubusercontent.com/extism/python-pdk/main/install.sh | bash - run: make build - run: make package - name: Install navidrome CLI run: | curl -fsSL "https://github.com/navidrome/navidrome/releases/download/v${NAVIDROME_VERSION}/navidrome_${NAVIDROME_VERSION}_linux_amd64.tar.gz" \ | tar -xz -C /usr/local/bin navidrome - run: navidrome plugin validate dist/${{ env.PLUGIN_ID }}.ndp - uses: actions/upload-artifact@v4 with: name: ${{ env.PLUGIN_ID }} path: dist/${{ env.PLUGIN_ID }}.ndp if-no-files-found: error publish: needs: [lint, test, build] if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: name: ${{ env.PLUGIN_ID }} path: dist - name: Upload plugin artifact to ProGet env: API_KEY: ${{ secrets.PKGS_API_KEY }} BASE: https://${{ vars.PKGS_HOST }}/endpoints/${{ vars.PKGS_ASSET_FEED }}/content/${{ env.PLUGIN_ID }} run: | if [[ "$GITHUB_REF" == refs/tags/v* ]]; then dirs="${GITHUB_REF_NAME#v}"; else dirs="main sha-${GITHUB_SHA::7}"; fi # POST creates or overwrites (ProGet rejects PUT to an existing path). for dir in $dirs; do curl -fsS -X POST -H "X-ApiKey: $API_KEY" -H "Content-Type: application/octet-stream" \ --data-binary "@dist/${PLUGIN_ID}.ndp" "$BASE/$dir/${PLUGIN_ID}.ndp" curl -fsS -X POST -H "X-ApiKey: $API_KEY" -H "Content-Type: application/json" \ --data-binary "@manifest.json" "$BASE/$dir/manifest.json" echo "uploaded $dir/${PLUGIN_ID}.ndp" done - name: Upload plugin artifact to Gitea package registry env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} BASE: ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/generic/${{ env.PLUGIN_ID }} run: | if [[ "$GITHUB_REF" == refs/tags/v* ]]; then dirs="${GITHUB_REF_NAME#v}"; else dirs="main sha-${GITHUB_SHA::7}"; fi # Generic packages are immutable per version: delete first (ignored if absent) so # a re-run or a repeated push to a mutable version like "main" doesn't 409. for dir in $dirs; do curl -fsS -X DELETE -H "Authorization: token $GITEA_TOKEN" "$BASE/$dir" || true curl -fsS -X PUT -H "Authorization: token $GITEA_TOKEN" \ --upload-file "dist/${PLUGIN_ID}.ndp" "$BASE/$dir/${PLUGIN_ID}.ndp" curl -fsS -X PUT -H "Authorization: token $GITEA_TOKEN" \ --upload-file "manifest.json" "$BASE/$dir/manifest.json" echo "uploaded $dir/${PLUGIN_ID}.ndp to Gitea packages" done - name: Link Gitea package to this repo env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | repo_name="${GITHUB_REPOSITORY#*/}" curl -fsS -X POST -H "Authorization: token $GITEA_TOKEN" \ "${{ github.server_url }}/api/v1/packages/${{ github.repository_owner }}/generic/${{ env.PLUGIN_ID }}/-/link/$repo_name" \ || echo "link skipped (already linked, or not yet supported)" notify: needs: [lint, test, build, publish] if: always() runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - id: summary name: Summarise the run env: NEEDS: ${{ toJSON(needs) }} run: | python3 - <<'PY' import json, os needs = json.loads(os.environ["NEEDS"]) results = {job: info["result"] for job, info in needs.items()} if "failure" in results.values(): status = "failure" elif "cancelled" in results.values(): status = "cancelled" else: status = "success" ran = [f"{job}: {result}" for job, result in results.items() if result != "skipped"] ref = os.environ["GITHUB_REF"] title = f"Release {os.environ['GITHUB_REF_NAME']}" if ref.startswith("refs/tags/") else f"CI {os.environ['GITHUB_REF_NAME']}" with open(os.environ["GITHUB_OUTPUT"], "a") as out: out.write(f"status={status}\ntitle={title}\n") out.write("message<