Files
Carmine Paolino 16a9dde2ca Drop the old name from packages, release scripts and docs
Packages no longer install a fastpotify command or declare that they
replace, provide or conflict with the old packages. Releases no longer
carry the 0.9.1 bridge files, the release script only checks and sums
Spotifast downloads, and the Flatpak, Homebrew, macOS and Windows
recipes lose their old-identity branches and clean-ups. Packaging CI
tests the v0.11.2 release instead of installing the 0.8.0 package first.
The Rename page and the notes pointing to it are gone.

Updates begun by 0.10.2 or earlier on Windows relaunch fastpotify.exe,
which the installer no longer provides; such an install updates, but
needs starting by hand once.
2026-10-03 14:18:23 +02:00

278 lines
11 KiB
YAML

name: Release
on:
push:
tags: ["v*"]
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
build:
name: build (${{ matrix.target }})
runs-on: ${{ matrix.os }}
env:
CMAKE_GENERATOR: Ninja
strategy:
fail-fast: false
matrix:
include:
# Match the native packages' declared glibc 2.39 baseline.
- os: ubuntu-24.04
target: x86_64-unknown-linux-gnu
# A native arm64 runner, so the GUI's system libraries need no
# cross-compilation sysroot.
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
- os: windows-latest
target: x86_64-pc-windows-msvc
# Cross-compiled from x64: the MSVC arm64 linker ships with the
# runner's Visual Studio. projectm-sys only knows how to build
# libprojectM for x64 there, so this build goes without MilkDrop.
- os: windows-latest
target: aarch64-pc-windows-msvc
features: --no-default-features
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
# The repository pins its toolchain; add the cross-target's standard
# library to the toolchain the pin actually resolves to.
- run: rustup target add ${{ matrix.target }}
- name: GUI build dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libasound2-dev libpulse-dev libxkbcommon-dev \
libwayland-dev libgl1-mesa-dev cmake libclang-dev
# libprojectM reads OpenGL through GLEW on Windows; projectm-sys builds
# against vcpkg's static-CRT triplet, matching .cargo/config.toml.
- name: GLEW for libprojectM
if: runner.os == 'Windows' && matrix.features == ''
run: vcpkg install glew:x64-windows-static
# projectm-sys asks CMake for the Visual Studio generator, which the
# runner image no longer satisfies; Ninja inside the MSVC environment
# builds the same thing without caring which Visual Studio is on. Both
# Windows jobs also use dumpbin below to inspect the finished binary.
- name: MSVC environment
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
# No compiler cache: published binaries never build from outputs
# restored from an Actions cache.
- run: cargo build --release --target ${{ matrix.target }} ${{ matrix.features }}
# The zip and installer must run on a clean Windows machine without a
# separately installed Visual C++ redistributable.
- name: Verify standalone Windows runtime
if: runner.os == 'Windows'
shell: pwsh
run: |
$binary = "target\${{ matrix.target }}\release\spotifast.exe"
$imports = & dumpbin /dependents $binary | Out-String
$runtime = $imports | Select-String -Pattern 'MSVCP[0-9_]*\.dll|VCRUNTIME[0-9_]*\.dll'
if ($runtime) { throw "Spotifast imports an MSVC runtime:`n$runtime" }
- name: Package
shell: bash
run: |
name="spotifast-${GITHUB_REF_NAME}-${{ matrix.target }}"
mkdir -p "dist/$name"
if [ "${{ runner.os }}" = "Windows" ]; then
cp "target/${{ matrix.target }}/release/spotifast.exe" "dist/$name/"
else
cp "target/${{ matrix.target }}/release/spotifast" "dist/$name/"
fi
cp README.md LICENSE "dist/$name/"
cp packaging/spotifast-portable.txt "dist/$name/"
if [ "${{ runner.os }}" = "Linux" ]; then
# Desktop integration for package builds and hand-installs.
cp --parents packaging/applications/spotifast.desktop packaging/icons/spotifast.svg "dist/$name/"
cp --parents contrib/omarchy/spotifast.json.tpl contrib/omarchy/spotifast-theme "dist/$name/"
fi
cd dist
if [ "${{ runner.os }}" = "Windows" ]; then
7z a "$name.zip" "$name"
else
tar czf "$name.tar.gz" "$name"
fi
# Inno Setup ships with the runner image. PowerShell, because bash on
# Windows rewrites /D... arguments as paths.
- name: Installer
if: runner.os == 'Windows'
shell: pwsh
run: |
$version = $env:GITHUB_REF_NAME.TrimStart("v")
$arch = "${{ matrix.target }}".Split("-")[0]
$iscc = (Get-Command iscc -ErrorAction SilentlyContinue).Source
if (-not $iscc) { $iscc = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" }
& $iscc "/DVersion=$version" "/DArch=$arch" `
"/DBinary=$PWD\target\${{ matrix.target }}\release\spotifast.exe" `
"/DOutputDir=$PWD\dist" packaging\windows\spotifast.iss
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- uses: actions/upload-artifact@v7
with:
name: ${{ matrix.target }}
path: |
dist/*.tar.gz
dist/*.zip
dist/*-setup.exe
if-no-files-found: error
macos:
name: macOS universal app
runs-on: macos-latest
env:
# Complete Apple credentials enable native-packages signing/notarization.
APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin,x86_64-apple-darwin
- run: rustup target add aarch64-apple-darwin x86_64-apple-darwin
# No compiler cache, as in the build job above.
- name: Build both architectures
run: |
cargo build --release --target aarch64-apple-darwin
cargo build --release --target x86_64-apple-darwin
- name: Universal binary
run: |
mkdir -p universal
lipo -create \
target/aarch64-apple-darwin/release/spotifast \
target/x86_64-apple-darwin/release/spotifast \
-output universal/spotifast
- uses: ruby/setup-ruby@v1
with:
ruby-version: '4.0'
- name: Install native packaging
run: gem install native-packages --version 0.8.1 --no-document
- name: App bundle
run: |
version="${GITHUB_REF_NAME#v}"
mkdir -p dist/macos-input
bash packaging/macos/bundle.sh universal/spotifast dist/macos-input/Spotifast.app "$version"
cp README.md LICENSE dist/macos-input/
- name: Package, sign and notarize macOS app
run: |
native-packages build \
--version "${GITHUB_REF_NAME#v}" --target macos-universal --defer-recipes \
--output "$RUNNER_TEMP/macos-packages"
cp "$RUNNER_TEMP/macos-packages/packages/macos-universal/dmg/"*.dmg dist/
- uses: actions/upload-artifact@v7
with:
name: macos-universal
path: dist/*.dmg
if-no-files-found: error
# The Linux build packaged as a Flatpak bundle: the same binary, in the
# sandbox packaging/flatpak describes, so nothing compiles twice. Flathub
# builds from source on its own machines, from the manifest beside it.
flatpak:
name: Flatpak bundle
needs: build
runs-on: ubuntu-latest
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-24.08
options: --privileged
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v7
with:
name: x86_64-unknown-linux-gnu
path: dist
- name: Unpack the Linux build
run: |
tar xzf dist/spotifast-${GITHUB_REF_NAME}-x86_64-unknown-linux-gnu.tar.gz -C packaging/flatpak "spotifast-${GITHUB_REF_NAME}-x86_64-unknown-linux-gnu"
mv packaging/flatpak/spotifast-${GITHUB_REF_NAME}-x86_64-unknown-linux-gnu packaging/flatpak/built
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
manifest-path: packaging/flatpak/rocks.spotifast.Spotifast.bundle.yml
bundle: spotifast-${{ github.ref_name }}-x86_64.flatpak
cache: false
upload-artifact: false
- uses: actions/upload-artifact@v7
with:
name: flatpak
path: "*.flatpak"
if-no-files-found: error
publish:
name: GitHub release
# The bundle is welcome but not required: a Flatpak failure must not
# hold the release.
needs: [build, macos, flatpak]
if: ${{ !cancelled() && needs.build.result == 'success' && needs.macos.result == 'success' }}
runs-on: ubuntu-latest
# Publishing waits for the maintainer's approval, and only this job can
# read the release signing key (v* tags only).
environment: release-signing
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
# Include the source package so source distributions can verify it
# against the same published checksums as the binaries.
- name: Source archive
run: |
curl --fail --location --retry 3 \
"https://github.com/${GITHUB_REPOSITORY}/archive/refs/tags/${GITHUB_REF_NAME}.tar.gz" \
--output "dist/spotifast-${GITHUB_REF_NAME}-source.tar.gz"
- name: Public filenames, updater compatibility and checksums
run: python3 packaging/release-names.py dist "$GITHUB_REF_NAME"
- uses: ruby/setup-ruby@v1
with:
ruby-version: '4.0'
# Sign the manifest release-names.py wrote (checksums.txt.sig), then
# check the signature and every listed file against the committed key.
# Updaters that carry the key refuse releases without a valid one.
- name: Sign checksums
env:
SPOTIFAST_UPDATE_SIGNING_KEY: ${{ secrets.SPOTIFAST_UPDATE_SIGNING_KEY }}
run: |
gem install native-packages --version 0.8.1 --no-document
native-packages sign-checksums dist/checksums.txt \
--public-key assets/update-public-key.hex \
--key-env SPOTIFAST_UPDATE_SIGNING_KEY
native-packages verify-checksums dist/checksums.txt \
--public-key assets/update-public-key.hex
- uses: softprops/action-gh-release@v2
with:
files: dist/*
name: Spotifast ${{ github.ref_name }}
# Publish reviewed notes immediately, not a generated PR-only summary.
body_path: packaging/release-notes/${{ github.ref_name }}.md
generate_release_notes: false
# A tag with a suffix (v0.4.0-rc1) is a pre-release: it stays
# off "latest", so the app's update check never offers it.
prerelease: ${{ contains(github.ref_name, '-') }}
packaging:
# The optional Flatpak job may fail without blocking native packages.
if: ${{ !cancelled() && needs.publish.result == 'success' && startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-') }}
needs: publish
uses: ./.github/workflows/packaging.yml
with:
version: ${{ github.ref_name }}
secrets: inherit