diff --git a/.github/workflows/spotube-release-binary.yml b/.github/workflows/spotube-release-binary.yml index c3ddf0f8..e612fa07 100644 --- a/.github/workflows/spotube-release-binary.yml +++ b/.github/workflows/spotube-release-binary.yml @@ -10,6 +10,7 @@ on: default: 'stable' options: - stable + - beta - nightly dry_run: description: 'Dry run (build & upload artifacts only, skip creating release)' @@ -26,7 +27,7 @@ on: permissions: contents: read -# Never cancel a running release when another is dispatched, and let stable and nightly run side by side +# Never cancel a running release when another is dispatched, and let stable, beta and nightly run side by side concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.release_type }} cancel-in-progress: false @@ -215,7 +216,7 @@ jobs: 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 }}" . + packaging/package-linux-tarball.sh "$VERSION" "${{ inputs.release_type == 'nightly' && 'nightly' || 'stable' }}" . - name: Upload tarball uses: actions/upload-artifact@v7 @@ -335,7 +336,7 @@ jobs: 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 }}" . + packaging/package-linux-tarball.sh "$VERSION" "${{ inputs.release_type == 'nightly' && 'nightly' || 'stable' }}" . - name: Upload tarball uses: actions/upload-artifact@v7 @@ -538,8 +539,9 @@ jobs: - name: Set release variables id: vars run: | - if [ "${{ inputs.release_type }}" = "stable" ]; then + if [ "${{ inputs.release_type }}" != "nightly" ]; then chmod +x gradlew + # printVersion includes the -beta.N suffix when betaNumber is set in build.gradle.kts VERSION=$(./gradlew -q :composeApp:printVersion) TAG="v${VERSION}" echo "is_prerelease=false" >> "$GITHUB_OUTPUT" diff --git a/README.md b/README.md index 833b6e2c..2cc7453b 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Android picks the Rust profile from its build type (`debug` or `release`) on its ### Releases -Releases are built by [`spotube-release-binary.yml`](.github/workflows/spotube-release-binary.yml), run manually (`workflow_dispatch`) as `stable` or `nightly`. Each desktop platform (Linux x86_64 and aarch64, Windows, macOS) builds its native installers on its own runner. Android builds a signed APK. +Releases are built by [`spotube-release-binary.yml`](.github/workflows/spotube-release-binary.yml), run manually (`workflow_dispatch`) as `stable`, `beta` or `nightly`. A beta is the stable build released like a stable release (draft, not a pre-release), tagged `v-beta.N` (set `betaNumber` in `composeApp/build.gradle.kts` to N, and back to `null` for stable). Each desktop platform (Linux x86_64 and aarch64, Windows, macOS) builds its native installers on its own runner. Android builds a signed APK. ## 👥 The Spotube team diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 571aa28d..a72f675f 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -48,6 +48,10 @@ plugins { val bundleId = "org.spotube.spotube" val version = "6.0.0" +// Set to N to release -beta.N (same app id, icons and name as stable); null for a plain stable release. +// Installer metadata (packageVersion) must stay numeric, so it keeps using plain `version`. +val betaNumber: Int? = 0 +// Betas share the stable app id, so bump this for every beta: Android only updates to a higher versionCode. val buildNumber = 46 // Desktop icon channel; Android picks its icons via the stable/nightly product flavor. Use -Pnightly=true. val isNightly = providers.gradleProperty("nightly").map { it.toBoolean() }.getOrElse(false) @@ -70,7 +74,7 @@ val isProductionBuild = providers.gradleProperty("production").map { it.toBoolea val targetName = "Spotube" val homePageUrl = "https://spotube.cc" val repositoryUrl = "https://github.com/team-spotube/spotube" -val appVersionName = version +val appVersionName = if (betaNumber != null) "$version-beta.$betaNumber" else version val appBuildNumber = if (isNightly) nightlyBuildNumber else buildNumber val appRepositoryUrl = repositoryUrl // CI reads the release version from here instead of scraping this file. @@ -375,8 +379,8 @@ android { applicationId = bundleId minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() - versionCode = buildNumber - versionName = version + versionCode = appBuildNumber + versionName = appVersionName } // stable = production channel, nightly = beta channel (own icon, name and installable side by side) flavorDimensions += "channel"