mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-11-04 10:13:59 +00:00
feat(packaging): Flathub, AUR, WinGet and Chocolatey publishing
- Flatpak manifest (GNOME 51, libvlc built from source) installing from a new portable spotube-linux-<version>-<arch>.tar.xz, shared with the AUR package - Release workflow builds and attaches the Linux tarballs for x86_64 and aarch64 - Package files are JMustache templates rendered by :composeApp:renderPackaging<Target> with the version, release asset checksums and git-cliff release notes; the metainfo release history is generated - Publish workflow (workflow_dispatch, release tag input) renders once and pushes to Flathub, the AUR, WinGet (PR from team-spotube/winget-pkgs) and Chocolatey - Chocolatey and WinGet updated for the NSIS installer
This commit is contained in:
parent
79d47c1d87
commit
8ab9463c9a
274
.github/workflows/spotube-publish-binary.yml
vendored
Normal file
274
.github/workflows/spotube-publish-binary.yml
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
name: Publish
|
||||
|
||||
# Publishes an existing GitHub release (made by spotube-release-binary.yml) to the package managers.
|
||||
# The `render` job checks out the release tag, downloads its assets and renders packaging/<target> with
|
||||
# Gradle (:composeApp:renderPackaging<Target>: version, checksums, git-cliff release notes). The publish
|
||||
# jobs only push what it rendered.
|
||||
#
|
||||
# Secrets:
|
||||
# FLATHUB_TOKEN PAT with push access to team-spotube/org.spotube.spotube
|
||||
# AUR_USERNAME, AUR_EMAIL, AUR_SSH_PRIVATE_KEY AUR account that maintains spotube-bin
|
||||
# WINGET_TOKEN classic PAT (public_repo) that can push to team-spotube/winget-pkgs and open PRs
|
||||
# CHOCO_API_KEY chocolatey.org API key
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release tag to publish (vX.Y.Z)
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
description: Jobs to run (flathub,aur,winget,chocolatey)
|
||||
required: true
|
||||
type: string
|
||||
default: flathub,aur,winget,chocolatey
|
||||
aur_pkgrel:
|
||||
description: AUR pkgrel (bump to re-release the same version)
|
||||
required: true
|
||||
type: string
|
||||
default: '1'
|
||||
dry_run:
|
||||
description: Dry run (render the packages, push nothing)
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TAG: ${{ inputs.tag }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
render:
|
||||
name: Render packages
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Validate tag and find release
|
||||
id: version
|
||||
env:
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "::error::tag must look like vX.Y.Z, got '$TAG'"
|
||||
exit 1
|
||||
fi
|
||||
is_draft=$(gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json isDraft --jq .isDraft)
|
||||
# The packages download from the public release URLs, which a draft doesn't have yet
|
||||
if [ "$is_draft" = "true" ] && [ "$DRY_RUN" != "true" ]; then
|
||||
echo "::error::release $TAG is still a draft; publish it first"
|
||||
exit 1
|
||||
fi
|
||||
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Full history: git-cliff builds the release notes from it
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 21
|
||||
|
||||
# Configuring :composeApp runs cargo (Gobley)
|
||||
- name: Set up Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
|
||||
- name: Install git-cliff
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: git-cliff
|
||||
|
||||
- name: Download release assets
|
||||
run: |
|
||||
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" --dir release-assets \
|
||||
--pattern 'spotube-linux-*.tar.xz' --pattern 'Spotube-windows-x86_64-setup.exe'
|
||||
|
||||
- name: Render packages
|
||||
env:
|
||||
PKGREL: ${{ inputs.aur_pkgrel }}
|
||||
run: |
|
||||
chmod +x gradlew
|
||||
./gradlew :composeApp:renderPackagingFlatpak :composeApp:renderPackagingAur \
|
||||
:composeApp:renderPackagingWinget :composeApp:renderPackagingChocolatey \
|
||||
-Pnightly=false -Ppkgrel="$PKGREL" -PpackagingArtifactsDir=release-assets
|
||||
for f in composeApp/build/packaging/{flatpak/*.yml,aur/PKGBUILD,winget/*.yaml,chocolatey/*.nuspec}; do
|
||||
echo "::group::$f"
|
||||
cat "$f"
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
- name: Upload rendered packages
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: packaging
|
||||
path: |
|
||||
composeApp/build/packaging/flatpak
|
||||
composeApp/build/packaging/aur
|
||||
composeApp/build/packaging/winget
|
||||
composeApp/build/packaging/chocolatey
|
||||
|
||||
# Chocolatey embeds the installer in the package
|
||||
- name: Upload Windows installer
|
||||
if: contains(inputs.jobs, 'chocolatey')
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: windows-installer
|
||||
path: release-assets/Spotube-windows-x86_64-setup.exe
|
||||
|
||||
flathub:
|
||||
name: Flathub
|
||||
needs: render
|
||||
if: contains(inputs.jobs, 'flathub')
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.render.outputs.version }}
|
||||
FLATHUB_REPO: team-spotube/org.spotube.spotube
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: packaging
|
||||
path: packaging
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
repository: ${{ env.FLATHUB_REPO }}
|
||||
token: ${{ secrets.FLATHUB_TOKEN }}
|
||||
path: flathub
|
||||
|
||||
- name: Commit
|
||||
working-directory: flathub
|
||||
run: |
|
||||
cp ../packaging/flatpak/org.spotube.spotube.yml .
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git switch -c "update-$VERSION"
|
||||
git add org.spotube.spotube.yml
|
||||
git diff --cached
|
||||
git commit -m "Update to $VERSION"
|
||||
|
||||
- name: Push and open PR
|
||||
if: ${{ !inputs.dry_run }}
|
||||
working-directory: flathub
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.FLATHUB_TOKEN }}
|
||||
run: |
|
||||
git push -u origin "update-$VERSION"
|
||||
gh pr create --repo "$FLATHUB_REPO" --head "update-$VERSION" \
|
||||
--title "Update to $VERSION" \
|
||||
--body "Release notes: https://github.com/$GITHUB_REPOSITORY/releases/tag/$TAG"
|
||||
|
||||
aur:
|
||||
name: AUR
|
||||
needs: render
|
||||
if: contains(inputs.jobs, 'aur')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: packaging
|
||||
path: packaging
|
||||
|
||||
- name: Publish to AUR
|
||||
if: ${{ !inputs.dry_run }}
|
||||
uses: KSXGitHub/github-actions-deploy-aur@v4.2.0
|
||||
with:
|
||||
pkgname: spotube-bin
|
||||
pkgbuild: packaging/aur/PKGBUILD
|
||||
commit_username: ${{ secrets.AUR_USERNAME }}
|
||||
commit_email: ${{ secrets.AUR_EMAIL }}
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Update to ${{ needs.render.outputs.version }}-${{ inputs.aur_pkgrel }}
|
||||
|
||||
winget:
|
||||
name: WinGet
|
||||
needs: render
|
||||
if: contains(inputs.jobs, 'winget')
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.render.outputs.version }}
|
||||
FORK: team-spotube/winget-pkgs
|
||||
MANIFEST_DIR: manifests/k/KRTirtho/Spotube
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: packaging
|
||||
path: packaging
|
||||
|
||||
- name: Sync fork with upstream
|
||||
if: ${{ !inputs.dry_run }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.WINGET_TOKEN }}
|
||||
run: gh repo sync "$FORK" --source microsoft/winget-pkgs --branch master
|
||||
|
||||
# winget-pkgs is huge: only fetch this package's directory
|
||||
- uses: actions/checkout@v7
|
||||
if: ${{ !inputs.dry_run }}
|
||||
with:
|
||||
repository: ${{ env.FORK }}
|
||||
ref: master
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
path: winget-pkgs
|
||||
sparse-checkout: ${{ env.MANIFEST_DIR }}
|
||||
|
||||
- name: Push and open PR
|
||||
if: ${{ !inputs.dry_run }}
|
||||
working-directory: winget-pkgs
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.WINGET_TOKEN }}
|
||||
run: |
|
||||
branch="KRTirtho.Spotube-$VERSION"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git switch -c "$branch"
|
||||
mkdir -p "$MANIFEST_DIR/$VERSION"
|
||||
cp ../packaging/winget/*.yaml "$MANIFEST_DIR/$VERSION/"
|
||||
git add "$MANIFEST_DIR/$VERSION"
|
||||
git commit -m "New version: KRTirtho.Spotube version $VERSION"
|
||||
git push -u origin "$branch"
|
||||
gh pr create --repo microsoft/winget-pkgs --base master --head "${FORK%%/*}:$branch" \
|
||||
--title "New version: KRTirtho.Spotube version $VERSION" \
|
||||
--body "Release notes: https://github.com/$GITHUB_REPOSITORY/releases/tag/$TAG"
|
||||
|
||||
chocolatey:
|
||||
name: Chocolatey
|
||||
needs: render
|
||||
if: contains(inputs.jobs, 'chocolatey')
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
VERSION: ${{ needs.render.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: packaging
|
||||
path: packaging
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: windows-installer
|
||||
path: packaging/chocolatey/tools
|
||||
|
||||
- name: Pack
|
||||
run: choco pack packaging/chocolatey/spotube.nuspec --outputdirectory dist
|
||||
|
||||
- name: Upload package
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: chocolatey-nupkg
|
||||
path: dist/*.nupkg
|
||||
|
||||
- name: Publish to Chocolatey
|
||||
if: ${{ !inputs.dry_run }}
|
||||
env:
|
||||
CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }}
|
||||
run: choco push "dist/spotube.$env:VERSION.nupkg" --source https://push.chocolatey.org/ --api-key "$env:CHOCO_API_KEY"
|
||||
58
.github/workflows/spotube-release-binary.yml
vendored
58
.github/workflows/spotube-release-binary.yml
vendored
@ -155,7 +155,10 @@ jobs:
|
||||
timeout-minutes: 120
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Full history: the metainfo's release notes come from git-cliff
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download maven local
|
||||
uses: actions/download-artifact@v8
|
||||
@ -196,6 +199,30 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew :composeApp:packageGraalvmDeb :composeApp:packageGraalvmRpm -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }}
|
||||
|
||||
# Portable tarball the AUR and Flathub packages install from. Like deb/rpm it uses the system's VLC,
|
||||
# GTK and WebKitGTK, so it is packed from the distributable before the AppImage build replaces it
|
||||
- name: Install git-cliff
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: git-cliff
|
||||
|
||||
- name: Package Linux tarball
|
||||
run: |
|
||||
if [ "${{ inputs.release_type }}" = "nightly" ]; then
|
||||
VERSION=nightly
|
||||
else
|
||||
VERSION=$(./gradlew -q :composeApp:printVersion)
|
||||
fi
|
||||
# Desktop entry + metainfo, with the release history from git-cliff
|
||||
./gradlew :composeApp:renderPackagingLinux -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }}
|
||||
packaging/package-linux-tarball.sh "$VERSION" "${{ inputs.release_type }}" .
|
||||
|
||||
- name: Upload tarball
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: linux-tarball
|
||||
path: spotube-linux-*-x86_64.tar.xz
|
||||
|
||||
# Only the AppImage bundles VLC, GTK and WebKitGTK; deb/rpm depend on the distro packages
|
||||
- name: Package Linux AppImage
|
||||
env:
|
||||
@ -241,7 +268,10 @@ jobs:
|
||||
timeout-minutes: 120
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
# Full history: the metainfo's release notes come from git-cliff
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# The arm64 runner image ships without an Android SDK/NDK, but :composeApp configuration needs both
|
||||
# (Gobley's cargo plugin resolves the NDK directory for the Android Rust targets)
|
||||
@ -289,6 +319,30 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew :composeApp:packageGraalvmDeb :composeApp:packageGraalvmRpm -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }}
|
||||
|
||||
# Portable tarball the AUR and Flathub packages install from. Like deb/rpm it uses the system's VLC,
|
||||
# GTK and WebKitGTK, so it is packed from the distributable before the AppImage build replaces it
|
||||
- name: Install git-cliff
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: git-cliff
|
||||
|
||||
- name: Package Linux tarball
|
||||
run: |
|
||||
if [ "${{ inputs.release_type }}" = "nightly" ]; then
|
||||
VERSION=nightly
|
||||
else
|
||||
VERSION=$(./gradlew -q :composeApp:printVersion)
|
||||
fi
|
||||
# Desktop entry + metainfo, with the release history from git-cliff
|
||||
./gradlew :composeApp:renderPackagingLinux -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }}
|
||||
packaging/package-linux-tarball.sh "$VERSION" "${{ inputs.release_type }}" .
|
||||
|
||||
- name: Upload tarball
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: linux-tarball-arm64
|
||||
path: spotube-linux-*-aarch64.tar.xz
|
||||
|
||||
# Only the AppImage bundles VLC, GTK and WebKitGTK; deb/rpm depend on the distro packages
|
||||
- name: Package Linux AppImage
|
||||
env:
|
||||
@ -507,7 +561,7 @@ jobs:
|
||||
run: |
|
||||
echo "## Downloads" > release-notes.md
|
||||
echo "" >> release-notes.md
|
||||
for dir in android-apk linux-deb linux-rpm linux-appimage linux-deb-arm64 linux-rpm-arm64 linux-appimage-arm64 windows-exe macos-dmg; do
|
||||
for dir in android-apk linux-deb linux-rpm linux-appimage linux-tarball linux-deb-arm64 linux-rpm-arm64 linux-appimage-arm64 linux-tarball-arm64 windows-exe macos-dmg; do
|
||||
if [ -d "$dir" ]; then
|
||||
echo "### $dir" >> release-notes.md
|
||||
for f in "$dir"/*; do
|
||||
@ -540,8 +594,10 @@ jobs:
|
||||
linux-deb/*.deb
|
||||
linux-rpm/*.rpm
|
||||
linux-appimage/*.AppImage
|
||||
linux-tarball/*.tar.xz
|
||||
linux-deb-arm64/*.deb
|
||||
linux-rpm-arm64/*.rpm
|
||||
linux-appimage-arm64/*.AppImage
|
||||
linux-tarball-arm64/*.tar.xz
|
||||
windows-exe/*.exe
|
||||
macos-dmg/*.dmg
|
||||
|
||||
@ -66,6 +66,12 @@
|
||||
- **Android signing**: decodes `secrets.KEYSTORE` (base64) → `composeApp/upload-keystore.jks`, writes signing config into `local.properties` from secrets.
|
||||
- `create-release` job (depends on all builds) uses `softprops/action-gh-release@v2` to create the GitHub release with all artifacts attached.
|
||||
|
||||
## Package managers (`packaging/`, `.github/workflows/spotube-publish-binary.yml`)
|
||||
- `packaging/<target>` (`linux`, `aur`, `flatpak`, `winget`, `chocolatey`) holds JMustache templates (`*.mustache`) plus files copied as is. `:composeApp:renderPackaging<Target>` renders them into `composeApp/build/packaging/<target>` (`RenderPackagingTask` in buildSrc documents the template data). Never hand-write versions, checksums or release notes into these files.
|
||||
- Checksums come from release assets in `-PpackagingArtifactsDir=<dir>`; a template using a missing value fails the render. Release notes come from `git-cliff --context` with `cliff.toml` (`GitCliffContextTask`): needs `git-cliff` on the PATH and full git history. `gradle.properties` defaults to `nightly=true`, which leaves commits unreleased: pass `-Pnightly=false` for a stable render.
|
||||
- `packaging/package-linux-tarball.sh` packs `spotube-linux-<version>-<arch>.tar.xz` (the AUR and Flathub source) from the GraalVM distributable and the rendered `linux` dir; the release workflow builds it before the AppImage step.
|
||||
- The publish workflow (`workflow_dispatch`, input `tag`) renders once, then pushes to Flathub (`team-spotube/org.spotube.spotube`), the AUR (`spotube-bin`), WinGet (PR from `team-spotube/winget-pkgs`) and Chocolatey.
|
||||
|
||||
## OpenCode Agent MCP Execution Directives
|
||||
|
||||
### 1. Code Discovery & Context Search
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// Build logic for the Linux AppImage bundle (see DownloadLinuxGtkBundleTask). Lives in buildSrc so the IDE
|
||||
// resolves it; an `apply(from = ...)` script plugin gets no Kotlin classpath in Android Studio.
|
||||
// Build logic: the Linux AppImage bundle (DownloadLinuxGtkBundleTask) and the package manager manifests
|
||||
// (GitCliffContextTask, RenderPackagingTask). Lives in buildSrc so the IDE resolves it; an
|
||||
// `apply(from = ...)` script plugin gets no Kotlin classpath in Android Studio.
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
@ -7,3 +8,7 @@ plugins {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.jmustache)
|
||||
}
|
||||
|
||||
8
buildSrc/settings.gradle.kts
Normal file
8
buildSrc/settings.gradle.kts
Normal file
@ -0,0 +1,8 @@
|
||||
// Shares the root version catalog (gradle/libs.versions.toml) with the build logic
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
create("libs") {
|
||||
from(files("../gradle/libs.versions.toml"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Writes git-cliff's changelog context (every release with its parsed, grouped commits) as JSON, using
|
||||
// the repository's cliff.toml. RenderPackagingTask turns it into release notes for the package manifests.
|
||||
// Needs `git-cliff` on the PATH and the full git history (CI: `fetch-depth: 0`).
|
||||
|
||||
package org.spotube.gradle
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.PathSensitive
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.work.DisableCachingByDefault
|
||||
import javax.inject.Inject
|
||||
|
||||
@DisableCachingByDefault(because = "Reads the git history, which is not a declared input")
|
||||
abstract class GitCliffContextTask @Inject constructor(private val execOperations: ExecOperations) : DefaultTask() {
|
||||
@get:Input
|
||||
abstract val executable: Property<String>
|
||||
|
||||
@get:InputFile
|
||||
@get:PathSensitive(PathSensitivity.NONE)
|
||||
abstract val configFile: RegularFileProperty
|
||||
|
||||
@get:Internal
|
||||
abstract val repositoryDir: DirectoryProperty
|
||||
|
||||
/** Tag for the commits since the last release (`--tag`); unset leaves them unreleased (nightlies). */
|
||||
@get:Input
|
||||
@get:Optional
|
||||
abstract val tag: Property<String>
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputFile: RegularFileProperty
|
||||
|
||||
init {
|
||||
group = "distribution"
|
||||
description = "Writes the git-cliff changelog context (releases and their commits) as JSON."
|
||||
executable.convention("git-cliff")
|
||||
// New commits and tags change the result without touching any declared input
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val output = outputFile.get().asFile
|
||||
output.parentFile.mkdirs()
|
||||
val args = buildList {
|
||||
add(executable.get())
|
||||
addAll(listOf("--config", configFile.get().asFile.absolutePath, "--context"))
|
||||
tag.orNull?.let { addAll(listOf("--tag", it)) }
|
||||
addAll(listOf("--output", output.absolutePath))
|
||||
}
|
||||
try {
|
||||
execOperations.exec {
|
||||
workingDir = repositoryDir.get().asFile
|
||||
commandLine(args)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
throw GradleException(
|
||||
"Running git-cliff failed (${args.joinToString(" ")}). Install it from https://git-cliff.org " +
|
||||
"and make sure the full git history is available.",
|
||||
e,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Renders one package manager's directory (packaging/<target>) into the build dir: `*.mustache` files are
|
||||
// rendered with JMustache (suffix dropped), everything else is copied as is.
|
||||
//
|
||||
// Template data:
|
||||
// version, tag, pkgrel, repositoryUrl
|
||||
// artifacts.<key>.{fileName, url, sha256, sha256Upper} release assets found in artifactsDir
|
||||
// release.{version, date, url, groups, notes} the release being packaged
|
||||
// releases tagged releases, newest first (metainfo)
|
||||
// groups[].{title, entries[].text} changelog grouped like cliff.toml
|
||||
// #indent2 / #indent4 indent a multi-line block (YAML block scalars)
|
||||
//
|
||||
// Missing variables fail the render, so a manifest never ships with an empty checksum or version.
|
||||
// HTML/XML escaping is on for .xml and .nuspec output only.
|
||||
|
||||
package org.spotube.gradle
|
||||
|
||||
import com.samskivert.mustache.Mustache
|
||||
import com.samskivert.mustache.MustacheException
|
||||
import groovy.json.JsonSlurper
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.PathSensitive
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import java.io.File
|
||||
import java.security.MessageDigest
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneOffset
|
||||
|
||||
@CacheableTask
|
||||
abstract class RenderPackagingTask : DefaultTask() {
|
||||
@get:InputDirectory
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
abstract val templateDir: DirectoryProperty
|
||||
|
||||
@get:Input
|
||||
abstract val version: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val pkgrel: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val repositoryUrl: Property<String>
|
||||
|
||||
/** Release assets by template key, e.g. `linuxX86_64` -> `spotube-linux-6.0.0-x86_64.tar.xz`. */
|
||||
@get:Input
|
||||
abstract val artifactNames: MapProperty<String, String>
|
||||
|
||||
/** Directory holding the downloaded release assets; only needed by templates that use `artifacts`. */
|
||||
@get:Internal
|
||||
abstract val artifactsDir: DirectoryProperty
|
||||
|
||||
/** The release assets that exist in [artifactsDir]; their checksums are part of the output. */
|
||||
@get:Input
|
||||
protected val artifactChecksums: Map<String, String>
|
||||
get() = artifactFiles().mapValues { (_, file) -> sha256(file) }
|
||||
|
||||
/** git-cliff `--context` output (GitCliffContextTask). */
|
||||
@get:InputFile
|
||||
@get:Optional
|
||||
@get:PathSensitive(PathSensitivity.NONE)
|
||||
abstract val changelogContext: RegularFileProperty
|
||||
|
||||
/** How many tagged releases `releases` lists. */
|
||||
@get:Input
|
||||
abstract val maxReleases: Property<Int>
|
||||
|
||||
@get:OutputDirectory
|
||||
abstract val outputDir: DirectoryProperty
|
||||
|
||||
init {
|
||||
group = "distribution"
|
||||
pkgrel.convention("1")
|
||||
maxReleases.convention(10)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun render() {
|
||||
val source = templateDir.get().asFile
|
||||
val target = outputDir.get().asFile
|
||||
target.deleteRecursively()
|
||||
target.mkdirs()
|
||||
|
||||
val data = templateData()
|
||||
source.walkTopDown().filter { it.isFile }.forEach { file ->
|
||||
val relative = file.relativeTo(source).path
|
||||
if (!relative.endsWith(TEMPLATE_SUFFIX)) {
|
||||
file.copyTo(target.resolve(relative), overwrite = true)
|
||||
return@forEach
|
||||
}
|
||||
val output = target.resolve(relative.removeSuffix(TEMPLATE_SUFFIX))
|
||||
val compiler = Mustache.compiler()
|
||||
.escapeHTML(output.extension in XML_EXTENSIONS)
|
||||
.emptyStringIsFalse(true)
|
||||
.zeroIsFalse(true)
|
||||
val rendered = try {
|
||||
compiler.compile(file.readText()).execute(data)
|
||||
} catch (e: MustacheException) {
|
||||
throw GradleException(
|
||||
"Rendering $relative failed: ${e.message?.trimEnd('.')}. Templates that use `artifacts` need " +
|
||||
"-PpackagingArtifactsDir=<dir with the release assets>.",
|
||||
e,
|
||||
)
|
||||
}
|
||||
output.parentFile.mkdirs()
|
||||
output.writeText(rendered)
|
||||
}
|
||||
}
|
||||
|
||||
private fun templateData(): Map<String, Any> {
|
||||
val version = version.get()
|
||||
val tag = "v$version"
|
||||
val repositoryUrl = repositoryUrl.get()
|
||||
val downloadUrl = "$repositoryUrl/releases/download/$tag"
|
||||
|
||||
val artifacts = artifactFiles().mapValues { (_, file) ->
|
||||
val sha256 = sha256(file)
|
||||
mapOf(
|
||||
"fileName" to file.name,
|
||||
"url" to "$downloadUrl/${file.name}",
|
||||
"sha256" to sha256,
|
||||
"sha256Upper" to sha256.uppercase(),
|
||||
)
|
||||
}
|
||||
|
||||
val changelog = changelogContext.orNull?.asFile?.let(::readChangelog).orEmpty()
|
||||
val tagged = changelog.filter { it.version != null }.sortedByDescending { it.timestamp }
|
||||
// The release being packaged; nightlies have no tag, so they get the unreleased commits
|
||||
val current = changelog.firstOrNull { it.version == tag }
|
||||
?: changelog.firstOrNull { it.version == null }
|
||||
?: ChangelogRelease(tag, Instant.now().epochSecond, emptyList())
|
||||
|
||||
return mapOf(
|
||||
"version" to version,
|
||||
"tag" to tag,
|
||||
"pkgrel" to pkgrel.get(),
|
||||
"repositoryUrl" to repositoryUrl,
|
||||
"artifacts" to artifacts,
|
||||
"release" to releaseData(current, version, repositoryUrl),
|
||||
"releases" to tagged.take(maxReleases.get()).map {
|
||||
releaseData(it, it.version!!.removePrefix("v"), repositoryUrl)
|
||||
},
|
||||
"indent2" to indent(2),
|
||||
"indent4" to indent(4),
|
||||
)
|
||||
}
|
||||
|
||||
private fun artifactFiles(): Map<String, File> {
|
||||
val dir = artifactsDir.orNull?.asFile ?: return emptyMap()
|
||||
return artifactNames.get()
|
||||
.mapValues { (_, name) -> dir.resolve(name) }
|
||||
.filterValues { it.isFile }
|
||||
}
|
||||
|
||||
private fun releaseData(release: ChangelogRelease, version: String, repositoryUrl: String): Map<String, Any> {
|
||||
val groups = release.commits
|
||||
.groupBy { it.group }
|
||||
.toSortedMap()
|
||||
.map { (group, commits) ->
|
||||
mapOf(
|
||||
// cliff.toml orders groups with an HTML comment prefix: "<!-- 0 -->Features"
|
||||
"title" to group.replace(HTML_COMMENT, "").trim(),
|
||||
"entries" to commits.map { mapOf("text" to it.text) },
|
||||
)
|
||||
}
|
||||
val notes = groups.joinToString("\n\n") { group ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val entries = group["entries"] as List<Map<String, String>>
|
||||
"${group["title"]}\n" + entries.joinToString("\n") { "- ${it["text"]}" }
|
||||
}
|
||||
return mapOf(
|
||||
"version" to version,
|
||||
"date" to LocalDate.ofInstant(Instant.ofEpochSecond(release.timestamp), ZoneOffset.UTC).toString(),
|
||||
"url" to "$repositoryUrl/releases/tag/v$version",
|
||||
"groups" to groups,
|
||||
"notes" to notes,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun readChangelog(file: File): List<ChangelogRelease> {
|
||||
val releases = JsonSlurper().parse(file) as List<Map<String, Any?>>
|
||||
return releases.map { release ->
|
||||
val commits = (release["commits"] as List<Map<String, Any?>>).mapNotNull { commit ->
|
||||
val group = commit["group"] as String? ?: return@mapNotNull null
|
||||
val message = (commit["message"] as String).plainText().replaceFirstChar { it.uppercase() }
|
||||
val scope = commit["scope"] as String?
|
||||
val breaking = commit["breaking"] == true
|
||||
val text = buildString {
|
||||
if (breaking) append("Breaking: ")
|
||||
if (scope != null) append("$scope: ")
|
||||
append(message)
|
||||
}
|
||||
ChangelogCommit(group, text)
|
||||
}
|
||||
ChangelogRelease(
|
||||
version = release["version"] as String?,
|
||||
timestamp = (release["timestamp"] as Number?)?.toLong() ?: Instant.now().epochSecond,
|
||||
commits = commits,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private data class ChangelogRelease(val version: String?, val timestamp: Long, val commits: List<ChangelogCommit>)
|
||||
|
||||
private data class ChangelogCommit(val group: String, val text: String)
|
||||
|
||||
private companion object {
|
||||
const val TEMPLATE_SUFFIX = ".mustache"
|
||||
val XML_EXTENSIONS = setOf("xml", "nuspec")
|
||||
val HTML_COMMENT = Regex("<!--.*?-->")
|
||||
val MARKDOWN_LINK = Regex("""\[([^\]]+)]\([^)]+\)""")
|
||||
|
||||
// cliff.toml's commit preprocessors turn issue numbers into Markdown links
|
||||
fun String.plainText() = replace(MARKDOWN_LINK, "$1").replace("**", "").trim()
|
||||
|
||||
fun indent(spaces: Int) = Mustache.Lambda { fragment, out ->
|
||||
val prefix = " ".repeat(spaces)
|
||||
out.write(fragment.execute().lines().joinToString("\n") { if (it.isEmpty()) it else prefix + it })
|
||||
}
|
||||
|
||||
fun sha256(file: File): String {
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
file.inputStream().use { input ->
|
||||
val buffer = ByteArray(1 shl 16)
|
||||
while (true) {
|
||||
val read = input.read(buffer)
|
||||
if (read < 0) break
|
||||
digest.update(buffer, 0, read)
|
||||
}
|
||||
}
|
||||
return digest.digest().joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,8 @@ import org.jetbrains.compose.reload.gradle.ComposeHotRun
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.spotube.gradle.DownloadLinuxGtkBundleTask
|
||||
import org.spotube.gradle.GitCliffContextTask
|
||||
import org.spotube.gradle.RenderPackagingTask
|
||||
import java.io.FileInputStream
|
||||
import java.util.Properties
|
||||
|
||||
@ -76,6 +78,37 @@ tasks.register("printVersion") {
|
||||
val appVersion = appVersionName
|
||||
doLast { println(appVersion) }
|
||||
}
|
||||
|
||||
// Package manager manifests: packaging/<target> rendered into build/packaging/<target> with the version, the
|
||||
// release assets' checksums (-PpackagingArtifactsDir=<dir>) and the git-cliff changelog. See RenderPackagingTask.
|
||||
val gitCliffContext = tasks.register<GitCliffContextTask>("gitCliffContext") {
|
||||
configFile.set(rootProject.layout.projectDirectory.file("cliff.toml"))
|
||||
repositoryDir.set(rootProject.layout.projectDirectory)
|
||||
// Nightlies are not a release: their commits stay unreleased
|
||||
if (!isNightly) tag.set("v$appVersionName")
|
||||
outputFile.set(layout.buildDirectory.file("packaging/changelog-context.json"))
|
||||
}
|
||||
val packagingRootDir = rootProject.layout.projectDirectory
|
||||
val packagingArtifactsDir = packagingRootDir.dir(providers.gradleProperty("packagingArtifactsDir"))
|
||||
listOf("linux", "aur", "flatpak", "winget", "chocolatey").forEach { target ->
|
||||
tasks.register<RenderPackagingTask>("renderPackaging${target.replaceFirstChar { it.uppercase() }}") {
|
||||
description = "Renders packaging/$target into build/packaging/$target."
|
||||
templateDir.set(packagingRootDir.dir("packaging/$target"))
|
||||
version.set(appVersionName)
|
||||
pkgrel.set(providers.gradleProperty("pkgrel").orElse("1"))
|
||||
repositoryUrl.set(appRepositoryUrl)
|
||||
artifactNames.set(
|
||||
mapOf(
|
||||
"linuxX86_64" to "spotube-linux-$appVersionName-x86_64.tar.xz",
|
||||
"linuxAarch64" to "spotube-linux-$appVersionName-aarch64.tar.xz",
|
||||
"windowsX64" to "Spotube-windows-x86_64-setup.exe",
|
||||
)
|
||||
)
|
||||
artifactsDir.set(packagingArtifactsDir)
|
||||
changelogContext.set(gitCliffContext.flatMap { it.outputFile })
|
||||
outputDir.set(layout.buildDirectory.dir("packaging/$target"))
|
||||
}
|
||||
}
|
||||
val githubRepositoryPath = repositoryUrl.removePrefix("https://github.com/")
|
||||
val latestReleaseApiUrl = "https://api.github.com/repos/$githubRepositoryPath/releases/latest"
|
||||
val generatedAppInfoDir = layout.buildDirectory.dir("generated/appBuildInfo/commonMain/kotlin")
|
||||
|
||||
@ -77,8 +77,11 @@ vanniktechMavenPublish = "0.37.0"
|
||||
uniffi = "0.3.7"
|
||||
kotlinx-atomicfu = "0.33.0"
|
||||
mokkery = "3.3.0"
|
||||
jmustache = "1.16"
|
||||
|
||||
[libraries]
|
||||
# buildSrc: renders the package manager manifests in packaging/
|
||||
jmustache = { module = "com.samskivert:jmustache", version.ref = "jmustache" }
|
||||
appdirs = { module = "net.harawata:appdirs", version.ref = "appdirs" }
|
||||
cache4k = { module = "io.github.reactivecircus.cache4k:cache4k", version.ref = "cache4k" }
|
||||
androidx-car-app = { module = "androidx.car.app:app", version.ref = "carApp" }
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
pkgbase = spotube-bin
|
||||
pkgdesc = Open source Music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!
|
||||
pkgver = 4.0.0
|
||||
pkgrel = 1
|
||||
url = https://spotube.org
|
||||
arch = x86_64
|
||||
license = AGPL-3.0-or-later
|
||||
depends = mpv
|
||||
depends = libappindicator-gtk3
|
||||
depends = libsecret
|
||||
depends = jsoncpp
|
||||
depends = libnotify
|
||||
depends = xdg-user-dirs
|
||||
depends = webkit2gtk-4.1
|
||||
optdepends = yt-dlp-git
|
||||
source = https://github.com/team-spotube/spotube/releases/download/v3.7.1/spotube-linux-3.7.1-x86_64.tar.xz
|
||||
md5sums = 475b1ae9b08f27743a4d4749391ae3db
|
||||
|
||||
pkgname = spotube-bin
|
||||
@ -1,40 +0,0 @@
|
||||
# Maintainer: Kingkor Roy Tirtho <krtirho@gmail.com>
|
||||
pkgname=spotube-bin
|
||||
pkgver=%{{SPOTUBE_VERSION}}%
|
||||
pkgrel=%{{PKGREL}}%
|
||||
epoch=
|
||||
pkgdesc="Open source Music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!"
|
||||
arch=(x86_64)
|
||||
url="https://spotube.org"
|
||||
license=('AGPL-3.0-or-later')
|
||||
groups=()
|
||||
depends=('mpv' 'libappindicator-gtk3' 'libsecret' 'jsoncpp' 'libnotify' 'xdg-user-dirs' 'webkit2gtk-4.1')
|
||||
makedepends=()
|
||||
checkdepends=()
|
||||
optdepends=('yt-dlp-git')
|
||||
provides=()
|
||||
conflicts=()
|
||||
replaces=()
|
||||
backup=()
|
||||
options=()
|
||||
install=
|
||||
changelog=
|
||||
source=("https://github.com/team-spotube/spotube/releases/download/v${pkgver}/spotube-linux-${pkgver}-x86_64.tar.xz")
|
||||
noextract=()
|
||||
md5sums=(%{{LINUX_MD5}}%)
|
||||
validpgpkeys=()
|
||||
|
||||
package() {
|
||||
install -dm755 "${pkgdir}/usr/share/icons/spotube"
|
||||
install -dm755 "${pkgdir}/usr/share/applications"
|
||||
install -dm755 "${pkgdir}/usr/share/appdata"
|
||||
install -dm755 "${pkgdir}/usr/share/${pkgname}"
|
||||
install -dm755 "${pkgdir}/usr/bin"
|
||||
|
||||
mv ./spotube.desktop "${pkgdir}/usr/share/applications"
|
||||
mv ./spotube-logo.png "${pkgdir}/usr/share/icons/spotube/"
|
||||
mv ./com.github.KRTirtho.Spotube.appdata.xml "${pkgdir}/usr/share/appdata/spotube.appdata.xml"
|
||||
cp -ra ./data ./lib ./spotube "${pkgdir}/usr/share/${pkgname}"
|
||||
sed -i 's|com.github.KRTirtho.Spotube|spotube|' "${pkgdir}/usr/share/appdata/spotube.appdata.xml"
|
||||
ln -s "/usr/share/${pkgname}/spotube" "${pkgdir}/usr/bin/spotube"
|
||||
}
|
||||
32
packaging/aur/PKGBUILD.mustache
Normal file
32
packaging/aur/PKGBUILD.mustache
Normal file
@ -0,0 +1,32 @@
|
||||
# Maintainer: Kingkor Roy Tirtho <krtirho@gmail.com>
|
||||
pkgname=spotube-bin
|
||||
pkgver={{version}}
|
||||
pkgrel={{pkgrel}}
|
||||
pkgdesc="Open source, plugin powered music streaming client"
|
||||
arch=(x86_64 aarch64)
|
||||
url="https://spotube.org"
|
||||
license=('AGPL-3.0-or-later')
|
||||
# libvlc + plugins for playback (FFmpeg demux/decode, GnuTLS for HTTPS streams, PulseAudio/PipeWire output),
|
||||
# WebKitGTK 4.1 for the webview, and the X11/GL/ALSA libraries the AWT/Skiko natives link
|
||||
depends=(
|
||||
'libvlc' 'vlc-plugins-base' 'vlc-plugin-ffmpeg' 'vlc-plugin-gnutls' 'vlc-plugin-pulse'
|
||||
'webkit2gtk-4.1' 'gtk3' 'glib2' 'dbus' 'alsa-lib' 'libglvnd' 'fontconfig' 'freetype2'
|
||||
'libx11' 'libxext' 'libxi' 'libxrender' 'libxtst' 'zlib'
|
||||
)
|
||||
provides=('spotube')
|
||||
conflicts=('spotube')
|
||||
options=('!strip' '!debug')
|
||||
source_x86_64=("https://github.com/team-spotube/spotube/releases/download/v${pkgver}/spotube-linux-${pkgver}-x86_64.tar.xz")
|
||||
source_aarch64=("https://github.com/team-spotube/spotube/releases/download/v${pkgver}/spotube-linux-${pkgver}-aarch64.tar.xz")
|
||||
sha256sums_x86_64=('{{artifacts.linuxX86_64.sha256}}')
|
||||
sha256sums_aarch64=('{{artifacts.linuxAarch64.sha256}}')
|
||||
|
||||
package() {
|
||||
cd "spotube-linux-${pkgver}-${CARCH}"
|
||||
|
||||
install -dm755 "${pkgdir}/opt" "${pkgdir}/usr/bin" "${pkgdir}/usr/share"
|
||||
cp -a app "${pkgdir}/opt/spotube"
|
||||
cp -a share/. "${pkgdir}/usr/share/"
|
||||
ln -s /opt/spotube/spotube "${pkgdir}/usr/bin/spotube"
|
||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Do not remove this test for UTF-8: if “Ω” doesn’t appear as greek uppercase omega letter
|
||||
enclosed in quotation marks, you should use an editor that supports UTF-8, not this one. -->
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<!-- == PACKAGE SPECIFIC SECTION == -->
|
||||
<id>spotube</id>
|
||||
<version>%{{SPOTUBE_VERSION}}%</version>
|
||||
<packageSourceUrl>https://github.com/team-spotube/spotube/tree/master/choco-struct</packageSourceUrl>
|
||||
<owners>Kingkor Roy Tirtho</owners>
|
||||
<!-- ============================== -->
|
||||
|
||||
<!-- == SOFTWARE SPECIFIC SECTION == -->
|
||||
<title>spotube (Install)</title>
|
||||
<authors>Kingkor Roy Tirtho</authors>
|
||||
<projectUrl>https://spotube.org</projectUrl>
|
||||
<iconUrl>
|
||||
https://rawcdn.githack.com/team-spotube/spotube/7edb0bb834eb18c05551e30a891720a6abf53dbe/assets/branding/spotube-logo.png</iconUrl>
|
||||
<copyright>2022 Spotube</copyright>
|
||||
<!-- If there is a license Url available, it is required for the community feed -->
|
||||
<licenseUrl>https://github.com/team-spotube/spotube/blob/master/LICENSE</licenseUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<projectSourceUrl>https://github.com/team-spotube/spotube</projectSourceUrl>
|
||||
<docsUrl>https://spotube.org</docsUrl>
|
||||
<bugTrackerUrl>https://github.com/team-spotube/spotube/issues/new</bugTrackerUrl>
|
||||
<tags>spotube music audio youtube flutter</tags>
|
||||
<summary>🎧 Open source music client that doesn't require Premium nor uses Electron! Available
|
||||
for both desktop & mobile! </summary>
|
||||
<description>
|
||||
Spotube is a Flutter based lightweight music client. It utilizes the power
|
||||
of music metadata providers & Youtube's public API & creates a hazardless, performant
|
||||
& resource
|
||||
friendly User Experience
|
||||
|
||||
# Features
|
||||
- Open source/libre software
|
||||
- Anonymous/guest login
|
||||
- Cross platform support
|
||||
- No telemetry, diagnostics or user data collection
|
||||
- Lightweight & resource-friendly
|
||||
- Native performance (Thanks to Flutter+Skia)
|
||||
- Playback control is done locally instead of on the server
|
||||
- Small size & less data usage
|
||||
- No ads since it uses all public & free APIs (It is still recommended
|
||||
to support the creators by watching/liking/subscribing to the artists' YouTube channels or
|
||||
liking their tracks on different music platforms.)
|
||||
- Time synced lyrics
|
||||
- Downloadable tracks
|
||||
</description>
|
||||
<releaseNotes>https://github.com/team-spotube/spotube/releases/tag/v%{{SPOTUBE_VERSION}}%</releaseNotes>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="tools\**" target="tools" />
|
||||
</files>
|
||||
</package>
|
||||
48
packaging/chocolatey/spotube.nuspec.mustache
Normal file
48
packaging/chocolatey/spotube.nuspec.mustache
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Do not remove this test for UTF-8: if “Ω” doesn’t appear as greek uppercase omega letter
|
||||
enclosed in quotation marks, you should use an editor that supports UTF-8, not this one. -->
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<!-- == PACKAGE SPECIFIC SECTION == -->
|
||||
<id>spotube</id>
|
||||
<version>{{version}}</version>
|
||||
<packageSourceUrl>https://github.com/team-spotube/spotube/tree/master/packaging/chocolatey</packageSourceUrl>
|
||||
<owners>Kingkor Roy Tirtho</owners>
|
||||
<!-- ============================== -->
|
||||
|
||||
<!-- == SOFTWARE SPECIFIC SECTION == -->
|
||||
<title>spotube (Install)</title>
|
||||
<authors>Team Spotube</authors>
|
||||
<projectUrl>https://spotube.org</projectUrl>
|
||||
<iconUrl>
|
||||
https://rawcdn.githack.com/team-spotube/spotube/69a310c78f5ceaf4eab7dfee98f187d38211c9ba/assets/branding/spotube-logo.png</iconUrl>
|
||||
<copyright>2026 Kingkor Roy Tirtho and Spotube Contributors</copyright>
|
||||
<!-- If there is a license Url available, it is required for the community feed -->
|
||||
<licenseUrl>https://github.com/team-spotube/spotube/blob/master/LICENSE</licenseUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<projectSourceUrl>https://github.com/team-spotube/spotube</projectSourceUrl>
|
||||
<docsUrl>https://spotube.org</docsUrl>
|
||||
<bugTrackerUrl>https://github.com/team-spotube/spotube/issues/new</bugTrackerUrl>
|
||||
<tags>spotube music audio music-player streaming lyrics plugins foss</tags>
|
||||
<summary>Open source, plugin powered music streaming client</summary>
|
||||
<description>
|
||||
A cross-platform, extensible, open source music streaming platform. Bring your own music
|
||||
metadata, playlists and audio sources with plugins made by the community or by yourself.
|
||||
|
||||
# Features
|
||||
- Plugin powered: supports any platform or custom music service through plugins
|
||||
- Community driven plugins for popular platforms, or create your own
|
||||
- Freely downloadable tracks with tagged metadata
|
||||
- Time synced lyrics regardless of plugin support
|
||||
- No telemetry, diagnostics or user data collection
|
||||
- Small size, low data usage and native performance
|
||||
- Open source/libre software
|
||||
</description>
|
||||
<releaseNotes>{{release.url}}
|
||||
|
||||
{{release.notes}}</releaseNotes>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="tools\**" target="tools" />
|
||||
</files>
|
||||
</package>
|
||||
@ -7,17 +7,17 @@ in verifying that this package's contents are trustworthy.
|
||||
Please go to releases page
|
||||
https://github.com/team-spotube/spotube/releases
|
||||
|
||||
Download same version as this choco package (example for v%{{SPOTUBE_VERSION}}%)
|
||||
https://github.com/team-spotube/spotube/releases/tag/v%{{SPOTUBE_VERSION}}%
|
||||
Download same version as this choco package (v{{version}})
|
||||
https://github.com/team-spotube/spotube/releases/tag/v{{version}}
|
||||
|
||||
1. get hashes. Run:
|
||||
powershell -command Get-FileHash tools\Spotube-windows-x86_64-setup.exe
|
||||
|
||||
2. The checksums should match the following:
|
||||
---
|
||||
Version Hashes for v%{{SPOTUBE_VERSION}}%
|
||||
Version Hashes for v{{version}}
|
||||
|
||||
|
||||
Algorithm Hash Path
|
||||
--------- ---- ----
|
||||
SHA256 %{{WIN_SHA256}}% tools\Spotube-windows-x86_64-setup.exe
|
||||
SHA256 {{artifacts.windowsX64.sha256Upper}} tools\Spotube-windows-x86_64-setup.exe
|
||||
@ -5,13 +5,15 @@ $fileLocation = Join-Path $toolsDir 'Spotube-windows-x86_64-setup.exe'
|
||||
|
||||
$packageArgs = @{
|
||||
packageName = $env:ChocolateyPackageName
|
||||
unzipLocation = $toolsDir
|
||||
fileType = 'exe' #only one of these: exe, msi, msu
|
||||
fileType = 'exe'
|
||||
file = $fileLocation
|
||||
|
||||
softwareName = 'spotube*' #part or all of the Display Name as you see it in Programs and Features. It should be enough to be unique
|
||||
silentArgs = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-' # Inno Setup
|
||||
softwareName = 'Spotube*'
|
||||
silentArgs = '/S' # NSIS (electron-builder one-click, per-user)
|
||||
validExitCodes= @(0)
|
||||
}
|
||||
|
||||
Install-ChocolateyInstallPackage @packageArgs
|
||||
|
||||
# The installer was only needed to install; don't keep a copy in the package directory
|
||||
Remove-Item $fileLocation -Force -ErrorAction SilentlyContinue
|
||||
|
||||
@ -1,17 +1,23 @@
|
||||
$ErrorActionPreference = 'Stop'; # stop on all errors
|
||||
$packageArgs = @{
|
||||
packageName = $env:ChocolateyPackageName
|
||||
softwareName = 'spotube*'
|
||||
softwareName = 'Spotube*'
|
||||
fileType = 'exe'
|
||||
validExitCodes= @(0, 3010, 1605, 1614, 1641)
|
||||
silentArgs = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-' # Inno Setup
|
||||
validExitCodes= @(0)
|
||||
}
|
||||
|
||||
[array]$key = Get-UninstallRegistryKey -SoftwareName $packageArgs['softwareName']
|
||||
|
||||
if ($key.Count -eq 1) {
|
||||
$key | % {
|
||||
$packageArgs['file'] = "$($_.UninstallString)" #NOTE: You may need to split this if it contains spaces, see below
|
||||
# electron-builder writes UninstallString as "<dir>\Uninstall Spotube.exe" /currentuser
|
||||
if ($_.UninstallString -match '^\s*"([^"]+)"\s*(.*)$') {
|
||||
$packageArgs['file'] = $Matches[1]
|
||||
$packageArgs['silentArgs'] = "$($Matches[2]) /S".Trim()
|
||||
} else {
|
||||
$packageArgs['file'] = $_.UninstallString
|
||||
$packageArgs['silentArgs'] = '/S'
|
||||
}
|
||||
|
||||
Uninstall-ChocolateyPackage @packageArgs
|
||||
}
|
||||
|
||||
112
packaging/flatpak/org.spotube.spotube.yml.mustache
Normal file
112
packaging/flatpak/org.spotube.spotube.yml.mustache
Normal file
@ -0,0 +1,112 @@
|
||||
id: org.spotube.spotube
|
||||
# GTK 3 and WebKitGTK 4.1 (the webview) come from the GNOME runtime
|
||||
runtime: org.gnome.Platform
|
||||
runtime-version: '51'
|
||||
sdk: org.gnome.Sdk
|
||||
command: spotube
|
||||
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --share=network
|
||||
# Compose renders through AWT/Skiko, which needs X11 (XWayland on Wayland sessions)
|
||||
- --socket=x11
|
||||
- --socket=pulseaudio
|
||||
- --device=dri
|
||||
# Downloaded tracks go to ~/Downloads/Spotube; local tracks are scanned from ~/Music and ~/Downloads
|
||||
- --filesystem=xdg-download
|
||||
- --filesystem=xdg-music:ro
|
||||
# Tray icon (StatusNotifierItem)
|
||||
- --talk-name=org.kde.StatusNotifierWatcher
|
||||
|
||||
cleanup:
|
||||
- /include
|
||||
- /lib/pkgconfig
|
||||
- /share/man
|
||||
- /share/doc
|
||||
- '*.la'
|
||||
- '*.a'
|
||||
|
||||
modules:
|
||||
# libvlc for vlcj (the audio player). Audio only: no video outputs, UI or Lua; decoding and demuxing
|
||||
# go through the runtime's FFmpeg (proprietary codecs come from the auto-installed codecs-extra extension).
|
||||
- name: vlc
|
||||
build-options:
|
||||
env:
|
||||
# configure looks for a c99/c11 wrapper for its build-time tools
|
||||
BUILDCC: gcc -std=gnu11
|
||||
config-opts:
|
||||
- --disable-vlc
|
||||
- --disable-qt
|
||||
- --disable-skins2
|
||||
- --disable-ncurses
|
||||
- --disable-lua
|
||||
- --disable-a52
|
||||
- --disable-dbus
|
||||
- --disable-xcb
|
||||
- --disable-xvideo
|
||||
- --disable-wayland
|
||||
- --disable-vdpau
|
||||
- --disable-libva
|
||||
- --disable-gles2
|
||||
- --disable-sdl-image
|
||||
- --disable-chromecast
|
||||
- --disable-udev
|
||||
- --disable-v4l2
|
||||
- --disable-dc1394
|
||||
- --disable-dv1394
|
||||
- --disable-linsys
|
||||
- --disable-dvbpsi
|
||||
- --disable-bluray
|
||||
- --disable-dvdread
|
||||
- --disable-dvdnav
|
||||
- --disable-vcd
|
||||
- --disable-libcddb
|
||||
- --disable-screen
|
||||
- --disable-addonmanagermodules
|
||||
- --disable-update-check
|
||||
cleanup:
|
||||
- /share/applications
|
||||
- /share/icons
|
||||
- /share/kde4
|
||||
- /share/metainfo
|
||||
- /share/solid
|
||||
- /share/vlc
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://download.videolan.org/pub/videolan/vlc/3.0.24/vlc-3.0.24.tar.xz
|
||||
sha256: e7cab503d1d7d5849b89d2cf0e1ee60d0ef6d012407791b644b9cfc0cc225fdf
|
||||
x-checker-data:
|
||||
type: anitya
|
||||
project-id: 6504
|
||||
stable-only: true
|
||||
versions: {<: '4.0'}
|
||||
url-template: https://download.videolan.org/pub/videolan/vlc/$version/vlc-$version.tar.xz
|
||||
|
||||
# The GraalVM native image, repackaged from the release tarball (packaging/package-linux-tarball.sh)
|
||||
- name: spotube
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- cp -a app ${FLATPAK_DEST}/lib/spotube
|
||||
- install -d ${FLATPAK_DEST}/bin
|
||||
- ln -s ../lib/spotube/spotube ${FLATPAK_DEST}/bin/spotube
|
||||
- cp -a share/. ${FLATPAK_DEST}/share/
|
||||
sources:
|
||||
- type: archive
|
||||
only-arches: [x86_64]
|
||||
url: {{artifacts.linuxX86_64.url}}
|
||||
sha256: {{artifacts.linuxX86_64.sha256}}
|
||||
x-checker-data:
|
||||
type: json
|
||||
url: https://api.github.com/repos/team-spotube/spotube/releases/latest
|
||||
version-query: .tag_name | sub("^v"; "")
|
||||
url-query: '"https://github.com/team-spotube/spotube/releases/download/v" + $version + "/spotube-linux-" + $version + "-x86_64.tar.xz"'
|
||||
is-main-source: true
|
||||
- type: archive
|
||||
only-arches: [aarch64]
|
||||
url: {{artifacts.linuxAarch64.url}}
|
||||
sha256: {{artifacts.linuxAarch64.sha256}}
|
||||
x-checker-data:
|
||||
type: json
|
||||
url: https://api.github.com/repos/team-spotube/spotube/releases/latest
|
||||
version-query: .tag_name | sub("^v"; "")
|
||||
url-query: '"https://github.com/team-spotube/spotube/releases/download/v" + $version + "/spotube-linux-" + $version + "-aarch64.tar.xz"'
|
||||
12
packaging/linux/org.spotube.spotube.desktop
Normal file
12
packaging/linux/org.spotube.spotube.desktop
Normal file
@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Spotube
|
||||
GenericName=Music Player
|
||||
Comment=Open source, plugin powered music streaming client
|
||||
Exec=spotube %U
|
||||
Icon=org.spotube.spotube
|
||||
Terminal=false
|
||||
Categories=AudioVideo;Audio;Music;Player;
|
||||
Keywords=music;streaming;player;audio;lyrics;playlist;
|
||||
StartupNotify=true
|
||||
StartupWMClass=org-spotube-spotube-MainKt
|
||||
99
packaging/linux/org.spotube.spotube.metainfo.xml.mustache
Normal file
99
packaging/linux/org.spotube.spotube.metainfo.xml.mustache
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>org.spotube.spotube</id>
|
||||
<!-- The Flutter-era app shipped on Flathub as com.github.KRTirtho.Spotube -->
|
||||
<provides>
|
||||
<id>com.github.KRTirtho.Spotube</id>
|
||||
</provides>
|
||||
<replaces>
|
||||
<id>com.github.KRTirtho.Spotube</id>
|
||||
</replaces>
|
||||
|
||||
<name>Spotube</name>
|
||||
<summary>Plugin powered, open source music streaming client</summary>
|
||||
<developer id="org.spotube">
|
||||
<name>Team Spotube</name>
|
||||
</developer>
|
||||
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>AGPL-3.0-or-later</project_license>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
A cross-platform, extensible, open source music streaming platform. Bring your own music
|
||||
metadata, playlists and audio sources with plugins made by the community or by yourself.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Plugin powered: supports any platform or custom music service through plugins</li>
|
||||
<li>Community driven plugins for popular platforms, or create your own</li>
|
||||
<li>Freely downloadable tracks with tagged metadata</li>
|
||||
<li>Time synced lyrics regardless of plugin support</li>
|
||||
<li>No telemetry, diagnostics or user data collection</li>
|
||||
<li>Small size, low data usage and native performance</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<launchable type="desktop-id">org.spotube.spotube.desktop</launchable>
|
||||
|
||||
<categories>
|
||||
<category>AudioVideo</category>
|
||||
<category>Audio</category>
|
||||
<category>Music</category>
|
||||
</categories>
|
||||
<keywords>
|
||||
<keyword>music</keyword>
|
||||
<keyword>streaming</keyword>
|
||||
<keyword>player</keyword>
|
||||
<keyword>lyrics</keyword>
|
||||
</keywords>
|
||||
|
||||
<url type="homepage">https://spotube.org</url>
|
||||
<url type="bugtracker">https://github.com/team-spotube/spotube/issues</url>
|
||||
<url type="vcs-browser">https://github.com/team-spotube/spotube</url>
|
||||
<url type="donation">https://opencollective.com/spotube</url>
|
||||
<url type="contribute">https://github.com/team-spotube/spotube/blob/master/CONTRIBUTION.md</url>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Spotube on the desktop</caption>
|
||||
<image>https://raw.githubusercontent.com/team-spotube/spotube/master/assets/branding/spotube-screenshot.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#84b2ff</color>
|
||||
<color type="primary" scheme_preference="dark">#01185c</color>
|
||||
</branding>
|
||||
|
||||
<content_rating type="oars-1.1" />
|
||||
|
||||
<requires>
|
||||
<display_length compare="ge">360</display_length>
|
||||
</requires>
|
||||
<supports>
|
||||
<control>pointing</control>
|
||||
<control>keyboard</control>
|
||||
<control>touch</control>
|
||||
</supports>
|
||||
|
||||
<!-- Generated from the git-cliff changelog (RenderPackagingTask) -->
|
||||
<releases>
|
||||
{{#releases}}
|
||||
<release version="{{version}}" date="{{date}}">
|
||||
<url type="details">{{url}}</url>
|
||||
{{#notes}}
|
||||
<description>
|
||||
{{#groups}}
|
||||
<p>{{title}}</p>
|
||||
<ul>
|
||||
{{#entries}}
|
||||
<li>{{text}}</li>
|
||||
{{/entries}}
|
||||
</ul>
|
||||
{{/groups}}
|
||||
</description>
|
||||
{{/notes}}
|
||||
</release>
|
||||
{{/releases}}
|
||||
</releases>
|
||||
</component>
|
||||
67
packaging/package-linux-tarball.sh
Executable file
67
packaging/package-linux-tarball.sh
Executable file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Packs the GraalVM native distributable into spotube-linux-<version>-<arch>.tar.xz, the
|
||||
# portable tarball the AUR (spotube-bin) and Flathub (org.spotube.spotube) packages install from.
|
||||
#
|
||||
# Run after `:composeApp:createGraalvmNativeDistributable` WITHOUT -PappImage=true (the tarball uses the
|
||||
# system's or the Flatpak runtime's VLC, GTK 3 and WebKitGTK, like the deb/rpm) and
|
||||
# `:composeApp:renderPackagingLinux` (desktop entry + metainfo with the release notes).
|
||||
#
|
||||
# Usage: packaging/package-linux-tarball.sh <version> [stable|nightly] [out-dir]
|
||||
#
|
||||
# Layout:
|
||||
# spotube-linux-<version>-<arch>/
|
||||
# app/ binary + the JDK/Skiko libraries it loads
|
||||
# share/applications/org.spotube.spotube.desktop
|
||||
# share/metainfo/org.spotube.spotube.metainfo.xml
|
||||
# share/icons/hicolor/512x512/apps/org.spotube.spotube.png
|
||||
# LICENSE
|
||||
set -euo pipefail
|
||||
|
||||
version="${1:?usage: $0 <version> [stable|nightly] [out-dir]}"
|
||||
channel="${2:-stable}"
|
||||
out_dir="${3:-.}"
|
||||
|
||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
app_dir="${SPOTUBE_APP_DIR:-$root/composeApp/build/compose/binaries/main/graalvm-app/org.spotube.spotube}"
|
||||
linux_dir="$root/composeApp/build/packaging/linux"
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64 | amd64) arch=x86_64 ;;
|
||||
aarch64 | arm64) arch=aarch64 ;;
|
||||
*) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
if [[ ! -x "$app_dir/spotube" ]]; then
|
||||
echo "No native distributable at $app_dir; run :composeApp:createGraalvmNativeDistributable first" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$linux_dir/org.spotube.spotube.metainfo.xml" ]]; then
|
||||
echo "No rendered metainfo in $linux_dir; run :composeApp:renderPackagingLinux first" >&2
|
||||
exit 1
|
||||
fi
|
||||
# An AppImage build (-PappImage=true) leaves VLC plugins and a GTK/WebKit tree in the same dir
|
||||
if [[ -d "$app_dir/plugins" || -d "$app_dir/usr" ]]; then
|
||||
echo "$app_dir bundles VLC/GTK (an -PappImage=true build); rebuild without it" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
name="spotube-linux-$version-$arch"
|
||||
staging="$(mktemp -d)"
|
||||
trap 'rm -rf "$staging"' EXIT
|
||||
dest="$staging/$name"
|
||||
|
||||
mkdir -p "$dest/share/applications" "$dest/share/metainfo" "$dest/share/icons/hicolor/512x512/apps"
|
||||
cp -a "$app_dir" "$dest/app"
|
||||
rm -f "$dest/app/.complete"
|
||||
install -m644 "$linux_dir/org.spotube.spotube.desktop" "$dest/share/applications/"
|
||||
install -m644 "$linux_dir/org.spotube.spotube.metainfo.xml" "$dest/share/metainfo/"
|
||||
install -m644 "$root/composeApp/icons/$channel/icon.png" "$dest/share/icons/hicolor/512x512/apps/org.spotube.spotube.png"
|
||||
install -m644 "$root/LICENSE" "$dest/LICENSE"
|
||||
|
||||
mkdir -p "$out_dir"
|
||||
tarball="$(cd "$out_dir" && pwd)/$name.tar.xz"
|
||||
tar -C "$staging" --sort=name --owner=0 --group=0 --numeric-owner \
|
||||
--mtime="@${SOURCE_DATE_EPOCH:-$(git -C "$root" log -1 --format=%ct)}" \
|
||||
-cf - "$name" | xz -T0 -9 > "$tarball"
|
||||
|
||||
echo "$tarball"
|
||||
21
packaging/winget/KRTirtho.Spotube.installer.yaml.mustache
Normal file
21
packaging/winget/KRTirtho.Spotube.installer.yaml.mustache
Normal file
@ -0,0 +1,21 @@
|
||||
# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.10.0.schema.json
|
||||
|
||||
PackageIdentifier: KRTirtho.Spotube
|
||||
PackageVersion: {{version}}
|
||||
Platform:
|
||||
- Windows.Desktop
|
||||
MinimumOSVersion: 10.0.0.0
|
||||
# electron-builder one-click NSIS installer (Nucleus), installs per user; winget's nullsoft default /S is silent
|
||||
InstallerType: nullsoft
|
||||
Scope: user
|
||||
InstallModes:
|
||||
- silent
|
||||
- silentWithProgress
|
||||
UpgradeBehavior: install
|
||||
ReleaseDate: {{release.date}}
|
||||
Installers:
|
||||
- Architecture: x64
|
||||
InstallerUrl: {{artifacts.windowsX64.url}}
|
||||
InstallerSha256: {{artifacts.windowsX64.sha256Upper}}
|
||||
ManifestType: installer
|
||||
ManifestVersion: 1.10.0
|
||||
34
packaging/winget/KRTirtho.Spotube.locale.en-US.yaml.mustache
Normal file
34
packaging/winget/KRTirtho.Spotube.locale.en-US.yaml.mustache
Normal file
@ -0,0 +1,34 @@
|
||||
# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.10.0.schema.json
|
||||
|
||||
PackageIdentifier: KRTirtho.Spotube
|
||||
PackageVersion: {{version}}
|
||||
PackageLocale: en-US
|
||||
Publisher: Team Spotube
|
||||
PublisherUrl: https://github.com/team-spotube
|
||||
PublisherSupportUrl: https://github.com/team-spotube/spotube/issues
|
||||
PrivacyUrl: https://spotube.org/p/privacy
|
||||
Author: Team Spotube
|
||||
PackageName: Spotube
|
||||
PackageUrl: https://spotube.org
|
||||
License: AGPL-3.0-or-later
|
||||
LicenseUrl: https://github.com/team-spotube/spotube/blob/master/LICENSE
|
||||
Copyright: Copyright (c) 2022-2026 Kingkor Roy Tirtho and Spotube Contributors
|
||||
ShortDescription: Open source, plugin powered music streaming client
|
||||
Description: |-
|
||||
A cross-platform, extensible, open source music streaming platform. Bring your own music
|
||||
metadata, playlists and audio sources with plugins made by the community or by yourself.
|
||||
Moniker: spotube
|
||||
Tags:
|
||||
- audio
|
||||
- music
|
||||
- music-player
|
||||
- streaming
|
||||
- lyrics
|
||||
- plugins
|
||||
{{#release.notes}}
|
||||
ReleaseNotes: |-
|
||||
{{#indent2}}{{release.notes}}{{/indent2}}
|
||||
{{/release.notes}}
|
||||
ReleaseNotesUrl: {{release.url}}
|
||||
ManifestType: defaultLocale
|
||||
ManifestVersion: 1.10.0
|
||||
7
packaging/winget/KRTirtho.Spotube.yaml.mustache
Normal file
7
packaging/winget/KRTirtho.Spotube.yaml.mustache
Normal file
@ -0,0 +1,7 @@
|
||||
# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.10.0.schema.json
|
||||
|
||||
PackageIdentifier: KRTirtho.Spotube
|
||||
PackageVersion: {{version}}
|
||||
DefaultLocale: en-US
|
||||
ManifestType: version
|
||||
ManifestVersion: 1.10.0
|
||||
Loading…
Reference in New Issue
Block a user