Floatplane channel plugin for Jellyfin 10.10.x: browse, HLS proxy, cookie session, CI release
Some checks failed
release / build-release (push) Has been cancelled
Some checks failed
release / build-release (push) Has been cancelled
- IChannel: creators -> sub-channels -> video posts (public listing API, search mapped) - IRequiresMediaInfoCallback -> signed proxy URLs; stream controller rewrites HLS so the AES-128 key is fetched server-side with the session cookie, segments stay on the CDN - delivery/info cached per token lifetime and throttled (~2/min) - config page: paste sails.sid + validate, extra creators, quality, search test - scripts/package.sh -> plugin folder + zip + md5 + manifest.json; Gitea release workflow - research docs, HAR analysis (HAR itself gitignored), install-pi5.sh Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
150
doc/research/reference-sources/chaosflix/.github/workflows/release.yml
vendored
Normal file
150
doc/research/reference-sources/chaosflix/.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
name: Release
|
||||
|
||||
# release.sh commits a manifest.json whose sourceUrl points at the release
|
||||
# asset, so the asset has to exist the moment the tag is pushed — otherwise
|
||||
# every server that has the repository added downloads a 404 (see #19).
|
||||
# This job owns the artifact: release.sh no longer builds one, because a ZIP
|
||||
# built on the tagging machine is never byte-identical to the published one and
|
||||
# its checksum described bytes nobody could download (#49).
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
DOTNET_NOLOGO: "1"
|
||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: "1"
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: "1"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
# The annotated tag's own message is the fallback for the release notes,
|
||||
# and it only arrives with the tag object itself.
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.x"
|
||||
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', 'Directory.Build.props') }}
|
||||
restore-keys: nuget-${{ runner.os }}-
|
||||
|
||||
- name: Check the tag against meta.json
|
||||
run: |
|
||||
meta=$(python3 -c "import json;print(json.load(open('Jellyfin.Plugin.Chaosflix/meta.json'))['version'])")
|
||||
tagged="${GITHUB_REF_NAME#v}"
|
||||
if [[ "${meta%.*}" != "$tagged" ]]; then
|
||||
echo "::warning::tag ${GITHUB_REF_NAME} does not match meta.json version ${meta}"
|
||||
fi
|
||||
|
||||
# Same output as release.sh: publish to ./artifacts, drop meta.json next
|
||||
# to the DLL, and zip exactly those two files flat.
|
||||
- name: Build the plugin
|
||||
run: |
|
||||
dotnet publish Jellyfin.Plugin.Chaosflix/Jellyfin.Plugin.Chaosflix.csproj -c Release -o ./artifacts
|
||||
cp Jellyfin.Plugin.Chaosflix/meta.json artifacts/
|
||||
|
||||
- name: Create the ZIP
|
||||
id: zip
|
||||
run: |
|
||||
zip_name="chaosflix-jellyfin-${GITHUB_REF_NAME}.zip"
|
||||
(cd artifacts && zip -j "../${zip_name}" Jellyfin.Plugin.Chaosflix.dll meta.json)
|
||||
md5=$(md5sum "${zip_name}" | cut -d' ' -f1)
|
||||
echo "name=${zip_name}" >> "$GITHUB_OUTPUT"
|
||||
echo "md5=${md5}" >> "$GITHUB_OUTPUT"
|
||||
{
|
||||
echo "### ${GITHUB_REF_NAME}"
|
||||
echo
|
||||
echo "- asset: \`${zip_name}\`"
|
||||
echo "- md5: \`${md5}\` — recorded as \`checksum\` in manifest.json"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# release.sh writes release-notes-v<version>.md but .gitignore keeps it
|
||||
# out of the commit, so in practice the tag message is what is used.
|
||||
- name: Collect the release notes
|
||||
id: notes
|
||||
run: |
|
||||
notes_file="release-notes-${GITHUB_REF_NAME}.md"
|
||||
if [[ -s "${notes_file}" ]]; then
|
||||
cp "${notes_file}" notes.md
|
||||
else
|
||||
git tag -l --format='%(contents)' "${GITHUB_REF_NAME}" > notes.md
|
||||
fi
|
||||
if [[ ! -s notes.md ]]; then
|
||||
echo "Release ${GITHUB_REF_NAME}" > notes.md
|
||||
fi
|
||||
|
||||
# Re-runnable on purpose: a failure in a later step used to be
|
||||
# unrecoverable, because re-running the job started here and gh refused an
|
||||
# existing release, leaving the checksum unrecorded (#100).
|
||||
- name: Create or update the GitHub release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
ASSET: ${{ steps.zip.outputs.name }}
|
||||
run: |
|
||||
if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
|
||||
echo "release ${GITHUB_REF_NAME} exists; uploading the asset again"
|
||||
gh release upload "${GITHUB_REF_NAME}" "${ASSET}" --clobber
|
||||
else
|
||||
gh release create "${GITHUB_REF_NAME}" "${ASSET}" \
|
||||
--title "${GITHUB_REF_NAME}" \
|
||||
--notes-file notes.md
|
||||
fi
|
||||
|
||||
# The checksum is taken from the asset as it was downloaded back from the
|
||||
# release, and it lands on the default branch rather than on the tag: a
|
||||
# tag is immutable, and what servers read is manifest.json on that branch.
|
||||
- name: Record the checksum in manifest.json
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
ASSET: ${{ steps.zip.outputs.name }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
BRANCH: ${{ github.event.repository.default_branch }}
|
||||
run: |
|
||||
git fetch origin "${BRANCH}"
|
||||
git checkout "${BRANCH}"
|
||||
|
||||
gh release download "${TAG}" --pattern "${ASSET}" --dir published --clobber
|
||||
MD5=$(md5sum "published/${ASSET}" | cut -d' ' -f1) && export MD5
|
||||
rm -rf published
|
||||
|
||||
python3 - <<'PYTHON'
|
||||
import json, os, sys
|
||||
|
||||
with open("manifest.json") as f:
|
||||
data = json.load(f)
|
||||
|
||||
wanted = os.environ["TAG"].lstrip("v")
|
||||
for entry in data[0]["versions"]:
|
||||
if entry["version"] == wanted or entry["version"].startswith(wanted + "."):
|
||||
entry["checksum"] = os.environ["MD5"]
|
||||
break
|
||||
else:
|
||||
sys.exit(f"manifest.json has no entry for {wanted}")
|
||||
|
||||
with open("manifest.json", "w") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
f.write("\n")
|
||||
PYTHON
|
||||
|
||||
if git diff --quiet manifest.json; then
|
||||
echo "manifest.json already carries this checksum"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add manifest.json
|
||||
git commit -m "release: record the ${TAG} checksum [skip ci]"
|
||||
git push origin "HEAD:${BRANCH}"
|
||||
Reference in New Issue
Block a user