Lidarr's smallest unit is a MusicBrainz release, so asking for one track means monitoring a whole discography. Soulseek trades individual files but has no concept of a request. muse bridges the two: search, click, and the song lands in the library correctly tagged. The design point is that the user picks the exact track before anything downloads, so muse holds artist, album, year and track number as ground truth and tags deterministically rather than inferring them afterwards from whatever a stranger named the file. Search is Deezer rather than MusicBrainz, decided on measurement: MusicBrainz put eight covers above the real recording for "radiohead creep" and never surfaced Queen for "bohemian rhapsody" across 90 results, because its index matches a word in a cover's title as readily as in the artist field. Re-ranking cannot rescue a result set missing the right row. Imports are os.link(), so downloads keep seeding from the Soulseek share while the library gets a second name for the same bytes.
76 lines
2.3 KiB
YAML
76 lines
2.3 KiB
YAML
name: release
|
|
|
|
# Publishes ghcr.io/<owner>/muse. The package inherits this repo's visibility
|
|
# on first publish, so it lands PRIVATE — pulling it needs a token with
|
|
# read:packages (see README, "Pulling on a server").
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
tags: ["v*"]
|
|
# Docs-only edits shouldn't burn a build or move :latest.
|
|
paths-ignore:
|
|
- "**.md"
|
|
- ".gitignore"
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
# A newer push makes an in-flight build pointless.
|
|
group: release-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write # required to push to GHCR
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Sanity-check the app before publishing
|
|
run: |
|
|
python3 -m pip install --quiet -r requirements.txt
|
|
python3 -c "import app; print('app imports OK')"
|
|
|
|
- uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to GHCR
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
# Automatically provided; no PAT needed for pushing from CI.
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Tags and labels
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ghcr.io/${{ github.repository }}
|
|
tags: |
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
type=sha,format=short
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
|
|
- name: Build and push
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
# amd64 only: the only host that runs this is x86_64. Adding arm64
|
|
# means QEMU emulation and a 3-5x slower build for nothing.
|
|
platforms: linux/amd64
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
- name: Summary
|
|
run: |
|
|
echo "### Published" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|